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的示例,并且覆盖相关的配置
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(),
],
转化前:
转化后:
注意事项:这个插件内部原理其实是依赖于esmodule的静态分析的
esmodule对模块进行解析时,会进行静态分析,在静态分析的时候,这个插件可以分析出来哪些代码可以做作用域提升
如果一个模块被多个模块所引入了不可能每个模块都复制一份代码,这个时候不做作用域提升了
推荐在开发过程中,推荐使用esmodule
如果你在项目中使用了第三方模块,那么第三方模块中可能使用esmodule或者commonjs,那么当我们使用import语句导入模块的时候它指向的是main字段指向的入口文件(package.json中的main属性指向的文件)
我们可以进行配置:
resolve.mainFields 4.1.3 优化 resolve.mainFields 配置 - 简书 (jianshu.com)