随着项目的复杂度增加,babel 的配置也随之变的复杂,因此我们需要把 babel 相关的配置提取成一个单独的文件进行配置方便管理,也就是我们工程目录下的 .babelrc 文件。
.babelrc { "presets":[ ["@babel/preset-env",{ "useBuiltIns": "usage" }], ["@babel/preset-react"] ] }[注意] babel-laoder 执行 presets 配置顺序是数组的后到前,与同时使用多个 loader 的执行顺序是一样的。
也就是把 webpack.config.js 中的 babel-loader 中的 options 对象提取成一个单独文件。
通过编译记录,我们可以发现一个问题就是打包后的 bundle.js 文件足足有 1M 大,那是因为 react 以及 react-dom 都被打包进来了。
Tree ShakingTree shaking 的本质是消除无用的 JavaScript 代码。
import { forEach } from "lodash" forEach([1,2,3],(item)=>{ console.log(item); })在项目中引入了 lodash 库,只使用了其中的 forEach 方法,在 jquery 时代我们只能引入整个 lodash 文件。但通过 import 引入则支持 Tree Shaking ,下面让我们一起来配置它。
webpack.config.js
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = { mode: 'production', devServer: { contentBase: './dist', // 服务器启动根目录设置为dist open: true, // 自动打开浏览器 port: 8081, // 配置服务启动端口,默认是8080 }, entry: { // 入口文件 main:'./src/index.js' }, output: { // 出口文件 publicPath:"", filename: 'bundle.js', path: path.resolve(__dirname,'dist') }, module:{ // loader 配置 rules:[ { test: /\.js$/, // 正则匹配js文件 exclude: /node_modules/, // 排除 node_modules 文件夹 loader: "babel-loader", // 使用 babel-loader } ] }, plugins: [ new HtmlWebpackPlugin({ template: 'src/index.html' // 使用模板文件 }), new CleanWebpackPlugin() ] }只需要配置 mode: 'production' 生成环境下会默认 Tree Shaking 。
打包后依然有 72kb 大小,显然 Tree Shaking 失败了,这是为什么呢?
Tree Shaing 执行的前提是:必须是使用 import export ESModule 语法的类库才能被 Tree Shaking , lodash 也提供了相应的库给我们使用 lodash-es 。
修改业务代码: src/index.js
import { forEach } from "lodash-es"; forEach([1,2,3],(item)=>{ console.log(item); })再次执行打包:
打包后的大小只有 5.55Kb ,说明 Tree Shaking 生效了。
为什么要 ESModule前面说了必须要使用 ES6 提供的模块化语法才可以实现 Tree Shaking ,使用 CommonJs 的语法能实现 Tree Shaking 吗?答案肯定是不能的。
CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。所谓静态分析就是不执行代码,从字面量上对代码进行分析。
拿上面代码分析:我们引入了 lodash-es 中的 forEach ,在静态分析阶段就可以知道,我们只使用了 forEach 一个函数,因此没有必要把整个 lodash-es 中所有的函数都引入,这个时候就剔除了那些没有用的代码,只保留 forEach 。
sideEffects在配置 Tree Shaking 时必须要配置 sideEffects
package.json
{ "sideEffects": false }"sideEffects": false 表示 webpack 它可以安全地删除未用到的 export;
"sideEffects": ["*.css"] 表示 *.css 的引入不做 Tree Shaking 处理。
为什么需要对 css 做处理呢?因为我们经常这样引入全局 css:
import "xxx.css"