tree shaking(摇树优化)
1 个模块可能有多个⽅方法,只要其中的某个方法使用到了,则整个文件都会被打到 bundle 里面去,tree shaking 就是只把用到的方法打入bundle ,没用到的方法会在 uglify 阶段被擦除掉。
使用:webpack 默认⽀支持。
要求:必须是ES6 的语法,CJS 的方式不支持
· production mode的情况下默认开启。
scope hoisting
构建后的代码存在大量闭包代码:
大量作用域包裹代码,导致体积增大(模块越多越明显),运行代码时创建的函数作用域变多,内存开销变大。
打包出来的是一个IIFE ,modules 是一个数组,每⼀项是一个模块初始化函数。__webpack_require ⽤用来加载模块,返回module.exports。通过WEBPACK_REQUIRE_METHOD(0) 启动程序。
原理:将所有模块的代码按照引用顺序放在一个函数作用域里,然后适当的重命名一些变量以防止变量名冲突。
代码分割
对于大的Web 应用来讲,将所有的代码都放在一个文件中显然是不够有效的,特别是当你的 某些代码块是在某些特殊的时候才会被使用到。webpack 有一个功能就是将你的代码库分割成 chunks(语块),当代码运行到需要它们的时候再进行加载。
懒加载JS 脚本的方式
- CommonJS:require.ensure;
- ES6:动态import(目前还没有原生⽀支持,需要babel 转换)。
yarn add @babel/plugin-syntax-dynamic-import --dev
.babelrc配置:
{
"presets": [["@babel/preset-env"], "@babel/preset-react"],
// 支持动态import
"plugins": ["@babel/plugin-syntax-dynamic-import"]
}
产生一个新的js文件,需要的时候才发送http请求这个文件
示例
通过react的click函数动态加载组件:
import { helloWebpack } from "./hello.js";
import React from "react";
import ReactDom from "react-dom";
import ascii from "../image/ascii码表.jpg";
import "./index.less";
export default class Search extends React.Component {
constructor() {
super(...arguments);
this.state = {
Dynamic: null,
};
}
render() {
let { Dynamic } = this.state;
return (
<section>
<h2>react-WDS</h2>
<h2 onClick={this.loadComponent.bind(this)}>{helloWebpack()}</h2>
{Dynamic ? <Dynamic /> : null}
<img src={ascii} />
</section>
);
}
loadComponent() {
// 动态引入
import("./dynamic.js").then((Dynamic) => {
console.log(this, Dynamic.default);
this.setState({
Dynamic: Dynamic.default,
});
});
}
}
ReactDom.render(<Search />, document.getElementById("root"));
dynamic.js文件:
import React from "react";
export default function dynamicIm() {
return <h2>dynamic import</h2>;
}
ESLint检查
使用eslint-loader,构建时检查JS 规范 首先安装 eslint极其依赖:
yarn add eslint babel-eslint eslint-config-airbnb eslint-loader eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react --dev
如果以上npm包安装失败,就请分别安装。
webpack配置:
{
test: /\.js$/,
exclude: /node_modules/,
use: [
"babel-loader",
'eslint-loader'
],
},
新建.eslintrc.js文件,使用airbnb-eslint,输入以下配置:
module.exports = {
parser: "babel-eslint",
extends: "airbnb",
env: {
browser: true,
node: true,
},
rules: {
indent: ["error", 4],
},
};
优化构建时日志显示
构建时展示一大堆日志,很多并不需要开发者关注。
统计信息stats设置
优化命令行的构建日志
使用friendly-errors-webpack-plugin
安装:
yarn add friendly-errors-webpack-plugin --dev
日志提示:
- success: 构建成功的日志提示;
- warning: 构建警告的日志提示
- error: 构建报错的日志提示
stats 设置成errors-only
// 插件里面配置
new FriendlyErrorsWebpackPlugin(),
// 设置统计信息
stats: 'errors-only'
成功时:
警告时:
失败时:
配置后日志非常简短的展示出来。
构建异常和中断处理
webpack4 之前的版本构建失败不会抛出错误码(error code)。
Node.js 中的process.exit 规范
- 0 表示成功完成,回调函数中,err 为null;
- 非0 表示执行失败。
主动捕获并处理构建错误
compiler 在每次构建结束后会触发done 这个hook。process.exit 主动处理构建报错。
plugins: [
function () {
this.hooks.done.tap("done", (stats) => {
if (
stats.compilation.errors &&
stats.compilation.errors.length &&
process.argv.indexOf("--watch") == -1
) {
console.log("build error");
process.exit(1);
}
});
},
];