做者:Dr. Axel Rauschmayer翻譯:瘋狂的技術宅html
原文:https://2ality.com/2020/04/we...前端
未經容許嚴禁轉載webpack
本文介紹瞭如何經過 TypeScript 和 webpack 建立 Web 應用程序。咱們僅使用 DOM API,而不使用特定的前端框架。源碼文件 ts-demo-webpack
能夠從 GitHub 下載。git
必需的知識:若是你對 TypeScript,webpack 和 npm 的工做原理有一個大概的瞭解,那麼它會有所幫助。程序員
經過 TypeScript 和 npm 使用 ES 模塊仍然很脆弱。因此咱們將會堅持將 CommonJS 模塊捆綁爲腳本文件。github
ts-demo-webpack
存儲庫 ts-demo-webpack
的結構以下:web
ts-demo-webpack/ build/ (created on demand) html/ index.html package.json ts/ src/ main.ts tsconfig.json webpack.config.js
爲了構建 Web 應用程序,咱們須要將兩組文件編譯到目錄 build/
中:面試
ts/
中。html/
中。這兩個任務都由 webpack 處理:typescript
main.ts
開始處理,找到全部使用的 TypeScript 和 JavaScript 文件,並將它們編譯成單個腳本文件 build/main-bundle.js
。此過程稱爲 bundling。爲了將 TypeScript 編譯爲JavaScript,webpack 使用了 loader(插件)ts-loader
。copy-webpack-plugin
複製 html/
中的文件。首先須要安裝咱們的網絡應用依賴的全部 npm 軟件包:npm
npm install
而後,須要經過 package.json
中的腳原本運行 webpack(在上一步中也已安裝):
npm run wpw
從如今開始,webpack 會監視存儲庫中的文件是否有更改,並在檢測到任何修改時從新構建該 Web 應用。
在另外一個命令行中,咱們如今能夠啓動一個在本地主機上提供 build/
內容的 Web 服務器:
npm run serve
若是轉到 Web 服務器輸出的 URL,則能夠看到正在運行的 Web 應用程序。
請注意,因爲緩存的緣由,簡單的從新加載可能看不到更改後的結果。從新加載時,可能須要按 shift 鍵來強制從新加載。
除了能夠用命令行進行構建外,咱們還能夠在 Visual Studio Code 中經過所謂的 build task 進行構建:
.vscode/tasks.json
設置適當的問題匹配器:"problemMatcher": ["$tsc-watch"],
如今咱們能夠從 「Terminal」 菜單執行 「Run Build Task...」。
package.json
package.json
指定項目所依賴的腳本和 npm 軟件包:
{ "private": true, "scripts": { "tsc": "tsc", "tscw": "tsc --watch", "wp": "webpack", "wpw": "webpack --watch", "serve": "http-server build" }, "dependencies": { "@types/lodash": "···", "copy-webpack-plugin": "···", "http-server": "···", "lodash": "···", "ts-loader": "···", "typescript": "···", "webpack": "···", "webpack-cli": "···" } }
"private": true
表示若是咱們不提供軟件包名稱和軟件包版本,npm 不會報錯。tsc,tscw
:若是咱們將 webpack 與 ts-loader
一塊兒使用,可能不會直接調用 TypeScript 編譯器 tsc
。
wp
:運行 webpack 一次編譯全部內容。wpw
:用 webpack 監視,並僅編譯修改過的文件。
serve
:運行服務器 http-server
並提供目錄 build/
的內容。依賴項:
webpack
、webpack-cli
、ts-loader
、copy-webpack-plugin
ts-loader
:typescript
http-server
lodash
、@ types/lodash
webpack.config.js
這是咱們配置 webpack 的方式:
const path = require('path'); const CopyWebpackPlugin = require('copy-webpack-plugin'); module.exports = { mode: "development", devtool: "inline-source-map", entry: { main: "./ts/src/main.ts", }, output: { path: path.resolve(__dirname, 'build'), filename: "[name]-bundle.js", }, resolve: { // Add ".ts" and ".tsx" as resolvable extensions. extensions: [".ts", ".tsx", ".js"], }, module: { rules: [ // all files with a `.ts` or `.tsx` extension will be handled by `ts-loader` { test: /\.tsx?$/, loader: "ts-loader" }, ], }, plugins: [ new CopyWebpackPlugin([ { from: './html', } ]), ], };
有關配置 webpack 的更多信息,請參閱 webpack 網站。
tsconfig.json
此文件用來配置 TypeScript 編譯器:
{ "compilerOptions": { "rootDir": "ts", "outDir": "dist", "target": "es2019", "lib": [ "es2019", "dom" ], "module": "commonjs", "esModuleInterop": true, "strict": true, "sourceMap": true } }
若是咱們把 webpack 與 ts-loader
放在一塊兒使用,則不須要選項 outDir
。可是若是咱們在不使用加載程序的狀況下使用 webpack,則須要(如本文稍後所述)。
index.html
這是 Web 應用的 HTML 頁面:
<!doctype html> <html> <head> <meta charset="UTF-8"> <title>ts-demo-webpack</title> </head> <body> <div id="output"></div> <script src="main-bundle.js"></script> </body> </html>
帶有id output
的 <div>
是 web 應用顯示其輸出的位置。 main-bundle.js
包含捆綁的代碼。
main.ts
這是 Web 應用的 TypeScript 代碼:
import template from 'lodash/template'; const outputElement = document.getElementById('output'); if (outputElement) { var compiled = template(` <h1><%- heading %></h1> Current date and time: <%- dateTimeString %> `.trim()); outputElement.innerHTML = compiled({ heading: 'ts-demo-webpack', dateTimeString: new Date().toISOString(), }); }
有關 template()
的更多信息,請參見 Lodash 的文檔。
webpack-no-loader.config.js
除了依賴於 ts-loader
以外,咱們還能夠先將全部 TypeScript 文件編譯爲 JavaScript 文件(經過 TypeScript 編譯器),而後經過 webpack 捆綁這些文件。有關其工做原理的更多信息,請參見博客文章「經過TypeScript建立基於CommonJS 的 npm 軟件包」。
如今,咱們沒必要配置 ts-loader
,而且 webpack 配置文件更加簡單:
const path = require('path'); module.exports = { entry: { main: "./dist/src/main.js", }, output: { path: path.join(__dirname, 'build'), filename: '[name]-bundle.js', }, plugins: [ new CopyWebpackPlugin([ { from: './html', } ]), ], };
爲何要在捆綁中間文件以前產生中間文件?好處是咱們能夠用 Node.js 對某些 TypeScript 代碼運行單元測試。