首先把 webpack 相关的依赖安装了:
npm i -D webpack webpack-cli
安装各个 loader:
npm i -D ts-loader babel-loader source-map-loader
安装 babel 的核心:
npm i -D @babel/core
安装 babel 的 preset:
npm i -D @babel/preset-env @babel/preset-typescript
安装 babel 的 plugins:
npm i -D @babel/plugin-transform-runtime @babel/runtime
接下来在项目根目录创建一个 webpack 配置文件:
webpack.config.dev.js:
module.exports = { entry: "./src/main.ts", mode: "development", output: { path: path.resolve(__dirname, "dist/dev"), filename: "bundle.js" }, devtool: "source-map", resolve: { extensions: [ ".ts", ".tsx", ".js" ] }, module: { rules: [ { test: /\.tsx?$/, loader: "ts-loader", exclude: /(node_modules|bower_components)/ }, { test: /\.ts$/, use: { loader: "babel-loader", options: { presets: [ [ "@babel/preset-env", { targets: { "chrome": "58", "ie": "11" } } ], [ "@babel/preset-typescript" ] ], plugins: [ "@babel/transform-runtime" ] } }, exclude: /(node_modules|bower_components)/ }, { test: /\.js$/, loader: "source-map-loader", exclude: /(node_modules|bower_components)/ } ] } };
webpack.config.pro.js:
const path = require("path"); module.exports = { entry: "./src/main.ts", mode: "production", output: { path: path.resolve(__dirname, "dist/pro"), filename: "bundle.js" }, resolve: { extensions: [ ".ts", ".tsx", ".js" ] }, module: { rules: [ { test: /\.tsx?$/, loader: "ts-loader", exclude: /(node_modules|bower_components)/ }, { test: /\.ts$/, use: [ { loader: "babel-loader", options: { presets: [ [ "@babel/preset-env", { targets: { "chrome": "58", "ie": "11" } } ], [ "@babel/preset-typescript" ] ], plugins: [ "@babel/transform-runtime" ] } } ], exclude: /(node_modules|bower_components)/ } ] } };
配置文件中主要有以下几个大的选项:entry、mode、output、devtool、resolve、module。
entry 是你的项目主要入口文件,webpack 将从这个文件开始进行打包处理。mode 是你这个配置文件适用于哪一种环境,如开发环境和生产环境。在开发环境中我们使用 devtool,即 sourcemaps 方便我们控制台调试代码,而生产环境中就不需要这个东西。
output 是我们的文件最终产生在哪个文件夹内,resolve 我只使用了 extensions 这一个配置,这个配置就是处理我们项目里哪些文件。请看这里resolve.extensions - CSDN。
module 这一个配置项就非常的重要了,里面有 rules 数组选项,我们的 loader 就全部配置在这里。
module: { rules: [ { test: /\.tsx?$/, loader: "ts-loader", exclude: /(node_modules|bower_components)/ } ] }
module: { rules: [ { test: /\.tsx?$/, loader: "ts-loader", exclude: /(node_modules|bower_components)/ }, { test: /\.ts$/, use: { loader: "babel-loader", options: { presets: [ [ "@babel/preset-env", { targets: { "chrome": "58", "ie": "11" } } ], [ "@babel/preset-typescript" ] ], plugins: [ "@babel/transform-runtime" ] } }, exclude: /(node_modules|bower_components)/ }, { test: /\.js$/, loader: "source-map-loader", exclude: /(node_modules|bower_components)/ } ] }
注意看第二个 loader 的配置,使用了 use 字段。其中一共有三个配置项:loader、options、plugins。loader 毫无疑问是 babel-loader。
options 下有一个预设 presets,是一个数组,第一个数组中有两个值,@babel/preset-env
和@babel/preset-typescript
。
babel 把高于 ES5 的语法转换成 ES5 以下的语法,因此需要 @babel/preset-env
预设。预设的执行顺序是逆向的执行的,按道理来说先执行 typescript 的预设,然后再把 js 文件的语法转换到低版本的语法。
plugins,即 babel 的插件,请直接查看 Webpack 官方文档的解释:babel-loader。
我们随便写两个 ts 函数,试一试这个项目是否成功运行。package.json 添加运行脚本"build": "webpack --config webpack.config.pro.js"
:
function entry(msg: string, onEntry: (msg: string) => void): void { onEntry(msg); } entry("Hello World!", (e) => { console.log(e); }); interface OnEnter { (msg: string): void; } function enter(msg: string, onEnter: OnEnter) { onEnter(msg); } enter("Hello World!", (e) => { console.log(e); });
console.log("Hello World!"),function(o,l){var e;e="Hello World!",console.log(e)}();
如果不想自己配置,可以基于我的模板仓库,根据自己的需求再加以改造: