做者: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 代码运行单元测试。