22_webpack_优化
Terser是一个JS的解析(Parser)、Mangleer(绞肉机)、Compresor(压缩机)的工具
绞肉机
如:一个函数 function functionsWithLongNames(){ } 名称很长,那么打包的文件占用的空间就相对大一些,如果经过工具来对代码进行转化,把函数的名称变成 function a(){} 或者function b(){} 这些较短名称的函数,那么他打包之后的文件占用的体积相对会比较少一些
以前称之为这个过程为丑化,现在变成了绞肉机
压缩机
知道TreeShaking的都知道有些dead code elimination(死代码删除)
如:if(false){console.log('123')}
Terser对JS文件进行解析,对代码进行丑化,压缩的工具集
早期我们是通过uglify-js来压缩、丑化JS代码,但是现在这个库已经不维护了,也不支持ES6以上的语法的
Terser是从uglify-es fork过来的,并且保留它原来的大部分API,以及适配uglify-es和uglify-js@3等;
因为Terser是一个独立的工具,所以我们可以单独安装、使用
安装:npm i terser (默认安装了cli的工具)
使用:npx terser [输入文件] -o [输出文件] [options]
Terser在webpack中配置
真实开发,我们不需要手动的通过terser来处理我们的代码,我们可以直接通过webpack来处理
在webpack中有一个minimizer属性,在production模式下,默认就是使用TerserPlugin来处理我们的代码的
如果我们对默认的配置不满意,也可以自己来创建TerserPlugin的示例,并且覆盖相关的配置
wepback5不需要下载terser-webpack-plugin直接引入
optimization: { minimize: true, minimizer: [ new TerserPlugin({ // 使用多进程并行运行来提高构建速度。默认并发运行次数:。os.cpus().length - 1 parallel: true, // 是否应将注释提取到单独的文件中 extractComments: false, terserOptions: { compress: { arguments: true, }, mangle: true, toplevel: true, keep_classnames: true, keep_fnames: true, }, }), ], },
CSS的压缩
CSS压缩通常是去除无用的空格等(因为很难去修改选择器、属性的名称、值等)
css的压缩我们可以使用另外一个插件:css-minimizer-webpack-plugin
安装:
npm i css-minimizer-webpack-plugin -D
npm i postcss -D 不安装postcss会报错
使用:
const CssMinimizerWebpackPlugin = require("css-minimizer-webpack-plugin"); plugins:[ new CleanWebpackPlugin({}), new MiniCssExtractPlugin({ filename: "css/[name].[contenthash:8].css", }), new CssMinimizerWebpackPlugin(), ],
Scope Hoisting
什么是ScopeHoisting(作用域提升)呢?
scope Hoisting从webpack3开始增加的一个新功能
功能实时对作用域进行提升,并且让webpack打包后的代码更小、运行更快
默认情况下webpack打包会有很多的函数作用域,包括一些(比如最外层的)IIFE
无论是从最开始的代码运行,还是加载一个模块,都需要执行一系列的函数
Scope Hoisting可以将函数合并到一个模块中来运行
使用Scope Hoisting非常的简单,默认这个插件就会启用
在production模式下,默认这个模块就会启用
在development模式下,我们需要自己来打开该模式
development模式下配置:
const webpack = require("webpack"); plugins: [ new webpack.optimize.ModuleConcatenationPlugin(), ],
转化前:
(() => { "use strict"; var e = { "./src/math.js": /*!*********************!*\ !*** ./src/math.js ***! \*********************/ (e, r, _) => { function sum(e, r) { return e + r; } function mul(e, r) { return e * r; } _.r(r), _.d(r, { mul: () => mul, sum: () => sum }); }, }, r = {}; function __webpack_require__(_) { var t = r[_]; if (void 0 !== t) return t.exports; var u = (r[_] = { exports: {} }); return e[_](u, u.exports, __webpack_require__), u.exports; } (__webpack_require__.d = (e, r) => { for (var _ in r) __webpack_require__.o(r, _) && !__webpack_require__.o(e, _) && Object.defineProperty(e, _, { enumerable: !0, get: r[_] }); }), (__webpack_require__.o = (e, r) => Object.prototype.hasOwnProperty.call(e, r)), (__webpack_require__.r = (e) => { "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }), Object.defineProperty(e, "__esModule", { value: !0 }); }); var _ = {}; (() => { /*!*********************!*\ !*** ./src/main.js ***! \*********************/ __webpack_require__.r(_); var e = __webpack_require__(/*! ./math */ "./src/math.js"); console.log((0, e.sum)(20, 30)); })(); })();
转化后:
(() => { "use strict"; var e = { r: (e) => { "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }), Object.defineProperty(e, "__esModule", { value: !0 }); }, }; /*!*********************************!*\ !*** ./src/main.js + 1 modules ***! \*********************************/ e.r({}), console.log( (function sum(e, o) { return e + o; })(20, 30) ); })();
注意事项:这个插件内部原理其实是依赖于esmodule的静态分析的
esmodule对模块进行解析时,会进行静态分析,在静态分析的时候,这个插件可以分析出来哪些代码可以做作用域提升
如果一个模块被多个模块所引入了不可能每个模块都复制一份代码,这个时候不做作用域提升了
推荐在开发过程中,推荐使用esmodule
如果你在项目中使用了第三方模块,那么第三方模块中可能使用esmodule或者commonjs,那么当我们使用import语句导入模块的时候它指向的是main字段指向的入口文件(package.json中的main属性指向的文件)
我们可以进行配置:
resolve.mainFields 4.1.3 优化 resolve.mainFields 配置 - 简书 (jianshu.com)
HTTP压缩
文件太小不会压缩,如果压缩了,返回到客户端还要解压反而影响效率
minRatio: 0.8, //压缩比,对比源文件,只有压缩比能达到0.8的时候才压缩,没有达到0.8的时候就没必要压缩了
inline-chunk-webpack-plugin
当我们吧runtimeChunk设置为true的时候,运行时的文件会单独打包成一个文件,但是其中的代码量非常少,所以我们没有必要让他单独生成一个文件,直接让他嵌入到html中就可以了
npm i react-dev-utils -D
引入
plugin:[ new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime.*\.js/]) ]
图片压缩