本文主要从两个方面进行优化:1 .优化开发体验2。优化输出质量。
优化开发体验

提高效率
优化施工速度
优化体验
优化输出质量
需要优化网上发布的代码,减少用户可以感知的加载时间。
提高代码性能,性能好,执行快。
以下优化基于webpack4。
缩件范围 Loader优化装载机配置
测试、包含和排除三个配置项,以缩小加载器的处理范围。
建议包括
include: path.resolve,复制代码优化前的构建时间:
时间:2429毫秒
进行修改代码优化:
rules: [ {test: /.css$/, include: path.resolve,use: ["style-loader", "css-loader"], }, {test: /.less$/, include: path.resolve,use: [// "style-loader", MiniCssExtractPlugin.loader, {loader: "css-loader",options: {//css modules 开启modules: true, }, }, {loader: "postcss-loader", },"less-loader", ], }, {test: /.$/, include: path.resolve,use: {loader: "url-loader",options: {name: "[name]_[hash:6].[ext]",outputPath: "images/",//推荐使用url-loader 因为url-loader支持limit//推荐小体积的图片资源转成base64limit: 12 * 1024, //单位是字节 1024=1kb }, }, }, {test: /.js$/, include: path.resolve,exclude: /node_modules/, use: {loader: "babel-loader", }, }, ],复制代码以下时间后优化构建时间:
时间:2110毫秒
少了319ms。
优化resolve.modulesResolve.modules用于配置webpack将在哪些目录中查找第三方模块。默认值为['node_modules']。要查找第三方,默认是在当前项目目录下的node_modules中查找。如果没有找到,它将转到上一级目录../node_modules,然后它将转到../../node_modules等等,非常类似Node.js的模块查找机制
如果我们所有的第三个模块都安装在根目录下,我们可以直接指明这个路径。
module.exports={resolve:{modules: [path.resolve] }}复制代码以下时间后优化构建时间:
时间:1532毫秒
减少了578毫秒。
优化resolve.aliasresolve.alias配置通过别名将原始导联路径映射到新的导联路径。以react为例。我们引用的react库一般有两组代码:
西南政法大学司法研究中心
采用commonJS规范的模块化代码
通用媒体光碟
打包的完整代码,无需模块化,可以直接执行。
默认情况下,webpack将递归解析和处理组件中的依赖组件。/节点模块/bin/react/index。我们可以直接指定零件,从而避免这种耗时。
resolve: {//查找第三方优化modules: [path.resolve],alias: {"@": path.join,react: path.resolve,"react-dom": path.resolve }, },复制代码以下时间后优化构建时间:
时间:1362毫秒
少了170ms。
优化resolve.extensions当前导语句没有后缀时,webpack将尝试查找后缀是否存在。
默认值:
extensions:['.js','.json','.jsx','.ts']复制代码尽可能多地尝试后缀列表。
这个陈述应该尽可能加后缀。
如果要优化到极致,不建议使用extensionx,因为会消耗一些性能。虽然能带来一些便利。
使externals优化cdn静态资源我们可以在CDN上存储一些JS的片段,在index.html通过标签引用,比如:
document根
复制代码我们希望在使用的时候,仍然可以用导入公式来引用,也希望webpack不要打包,这样就可以配置externals了。
//webpack.config.jsmodule.exports = {//...externals: {//jquery通过script引之后,全局中即有了 jQuery 变量'jquery': 'jQuery' }}复制代码使用静态资源路径publicPath通过在全球部署CDN资源,用户可以就近访问资源,加快访问速度。要连接CDN,需要将网页的静态资源上传到CDN服务。当访问这些资源时,使用CDN服务提供的URL。
##webpack.config.jsoutput:{publicPath: '//cdnURL.com', //指定存放JS件的CDN地址}复制代码使用条件:
公司必须有一个cdn服务器地址
确保静态资源片段是否上传。
借助MiniCssExtractPlugin完成抽离cssnpm install mini-css-extract-plugin -D复制代码const MiniCssExtractPlugin = require; {test: /.less$/, use: [// "style-loader", // 不再需要style-loader,MiniCssExtractPlugin.loader代替 MiniCssExtractPlugin.loader,"css-loader", // 编译css"postcss-loader","less-loader" // 编译less ] },plugins: [new MiniCssExtractPlugin ]复制代码压缩css借助优化-CSS-资产-web包-插件
使用cssnano
首先安装:
npm install cssnano -Dnpm i optimize-css-assets-webpack-plugin -D复制代码const OptimizeCSSAssetsPlugin = require;new OptimizeCSSAssetsPlugin, //引cssnano配置压缩选项cssProcessorOptions: {discardComments: { removeAll: true } }})复制代码压缩HTML在html-webpack-plugin的帮助下
new htmlWebpackPlugin,复制代码development vs Production模式区分打包首先安装
npm install webpack-merge -D复制代码创建webapck.dev.js文件
const {merge} = requireconst commonConfig = requireconst devConfig = { ...}module.exports = merge复制代码创建webpack.prod.js文件
const {merge} = requireconst commonConfig = requireconst prodConfig = { ...}module.exports = merge复制代码package.js
"scripts":{"dev":"webpack-dev-server --config ./webpack.dev.js","build":"webpack --config ./webpack.prod.js"}复制代码基于环境变量区分使用跨环境
npm i cross-env -D复制代码包配置命令脚本,传递参数
"test:build": "cross-env NODE_ENV=production webpack --config ./webpack.test.config.js","test:dev": "webpack-dev-server --config ./webpack.test.config.js"复制代码获取webpack.config.test.js中的参数进行判断。
const baseConfig = require;const devConfig = require;const prodConfig = require;const {merge} = require;console.logmodule.exports = =>{if{return merge }else{return merge } }复制代码tree ShakingWebpack2.x开始抱着树摇的概念。顾名思义,“摇树”就是清除无用的CSS和JS。
死代码具有以下特征:
代码将不被执行,不可达。
代码执行的结果不会发送到。
代码只影响死变量。

Js树摇只持有ES模块的参数!!!!
Css tree shakingnpm i glob-all purify-css purifycss-webpack --save-dev复制代码const PurifyCSS = requireconst glob = requireplugins:[new PurifyCSS,// 同样需要对html文件进行tree shaking path.resolve ]) }),]复制代码JS tree shaking仅导入报价,不导入常用报价。
案例:添加expo.js文件
//expo.jsexport const add = => {return a + b;};export const minus = => {return a - b;};复制代码//index.jsimport { add } from "./expo";add;复制代码//webpack.config.jsoptimization: {usedExports: true // 哪些导出的模块被使了,再做打包}复制代码只要模式是生产就行,模式是develpoment的摇树,但是不行,因为webpack是为了方便你调试而设计的。
你可以检查打包的代码注释,看看是否有效。
生产模式不需要配置,默认情况下是打开的。
sideEffects 处理副作用//package.json"sideEffects":false //正常对所有模块进tree shaking , 仅产模式有效,需要配合usedExports复制代码或者从阵列中排除不需要树摇动的模块。
"sideEffects":['*.css','@babel/polyfill']复制代码代码分割 code Splitting单应spa:打包后,所有东西都变成了一个包
代码量变化,不利于下载。
对浏览器资源没有合理的兴趣。
多应mpa:如果引入了几个常用模块,可以将这些常用模块单独提取出来打包。公共代码只需要下载一次就可以缓存,避免了重复下载。
如果我们引入第三个库,卷是1mb,我们的业务逻辑代码也是1mb,那么打包的卷就是2mb,这就导致了问题:
文件量,加载时间。
业务逻辑会变,第三库不会变,所以业务逻辑会变,第三库也会变。
例如,我们使用第三方库lodash:
import _ from "lodash";console.log)复制代码其实代码拆分的概念和webpack没有直接关系,但是webpack为我们实现代码拆分提供了一个更方便的方法。
基于webpack.js.org/plugins/spl...
optimization: {splitChunks: {chunks: "all", // 所有的 chunks 代码公共的部分分离出来成为个单独的件 }, },复制代码打包后,dist目录下多了一个文件vendors~main.js,就是分开的lodash。
splitChunks的其他可配置项目:
optimization: {splitChunks: {chunks: "async", //对同步 initial,异步 async,所有的模块有效 allminSize: 30000, //最尺,当模块于30kbmaxSize: 0, //对模块进次分割时使,不推荐使minChunks: 1, //打包成的chunk件最少有个chunk引了这个模块maxAsyncRequests: 5, //最异步请求数,默认5maxInitialRequests: 3, //最初始化请求书,件同步请求,默认3automaticNameDelimiter: "-", //打包分割符号name: true, //打包后的名称,除了布尔值,还可以接收个函数functioncacheGroups: {//缓存组vendors: {test: /[/]node_modules[/]/, name: "vendor", // 要缓存的 分隔出来的 chunk 名称priority: -10, //缓存组优先级 数字越,优先级越 },other: {chunks: "initial", // 必须三选:"initial" | "all" | "async"test: /react|lodash/, // 正则规则验证,如果符合就提取 chunk, name: "other",minSize: 30000,minChunks: 1, },default: {minChunks: 2,priority: -20,reuseExistingChunk: true, //可设置是否重该chunk }, }, }, }复制代码我们可以配置缓存组。
splitChunks: {chunks: "all", // 所有的 chunks 代码公共的部分分离出来成为个单独的件automaticNameDelimiter: '-',//打包分割符号cacheGroups: {lodash: {test:/lodash/, name: "lodash" },react: {test: /react|react-dom/, name: "react" } } },复制代码包装后
一般配置可以是:
optimization:{//帮我们动做代码分割splitChunks:{chunks:"all",//默认是持异步,我们使all } }复制代码Scope Hoisting域提升是指webpack通过对ES6语法的静态分析,分析模块之间的依赖关系,尽可能将模块放在同一个函数中。通过下面的代码示例了解:
新建hello.js
export default 'Hello, Webpack';复制代码创建新index.js
import str from './hello.js';console.log;复制代码打包后hello.js和index.js的内容会分开。
我们通过配置优化来打开scope housing。concatenate modules = true。
// webpack.config.jsmodule.exports = {optimization: {concatenateModules: true }};复制代码我们发现hello.js的内容和index.js的内容合并了!
所以通过范围提升的功能,Webpack打包的代码片可以越来越快。
使具量化Speed-measure-webpack-plugin:可以测量每个插件和加载器所花费的时间:
npm i speed-measure-webpack-plugin -D复制代码//webpack.config.jsconst SpeedMeasurePlugin = require;const smp = new SpeedMeasurePlugin;const config = {//...webpack配置}module.exports = smp.wrap;复制代码包装后
Webpack-bundle-analyzer:分析Webpack打包后的模块依赖关系;
npm install webpack-bundle-analyzer -D复制代码//webpack.config.jsconst BundleAnalyzerPlugin = require.BundleAnalyzerPlugin;//.... plugins: [//...new BundleAnalyzerPlugin, ]复制代码当您启动webpack构建时,windows将默认打开。
DllPlugin插件打包第三类库 优化构建性能Dll实际上是一个缓存。
。dll称为动态链接库,在windows系统中经常见到。百科全书:baike.baidu.com/item/.dll/2…
中引入了许多第三库,这些库将很长一段时间不会更新。包装时,它们被分开包装,以加快包装速度。DllPlugin动态链接库插件的原理是提取依赖的基本模块,打包成dll。当一个dll中存在需要导入的模块时,这个模块就不再打包,而是从dll中获取。
动态链接库只需要编译次。第三个模块从物品到物品,版本相对稳定的,比如React和React-DOM,只要不需要升级就可以使用。
Webpack内置了对动态链接库的支持:
DllPlugin:将单个动态链接库打包在。
DllReferencePlugin:主要配置部分带有DllPlugin插件的动态链接库包。
创建一个新的webpack.dll.config.js片段并打包基本模块。
我们在index.js中做了第三个库react和react-dom接下来,我们先把这两个库提前打包。
const path = require;const { DllPlugin } = require;module.exports = {mode: "development",entry: {react: ["react", "react-dom"] },output: {path: path.resolve,filename: "[name].dll.js",library: "react" },plugins: [new DllPlugin,// 定义打包的公共vendor件对外暴露的函数名name: "react" }) ]}复制代码Add in package.json
"dev:dll": "webpack --config ./webpack.dll.config.js"复制代码运输
npm run dev:dll复制代码您会发现一个额外的dll文件夹,旁边有dll.js,因此我们已经单独打包了React:
Dll包含数量模块的代码,这些代码存储在一个数组中。数组的索引号为ID,在window.xxx中通过暴露全局中的变量可以访问其中的模块。
Manifest.json描述了哪些模块包含在其对应的dll.js中,以及ID和路径。
下一步是什么?
要为web项目构建动态链接库,您需要完成以下工作:
把依赖的基本模块抽出来,打包成一个单独的动态链接库,可以包含多个模块。
当要导入的模块存在于一个动态链接库中时,就不要再打包了,直接使用已经构建好的动态链接库即可。
##webpack.dev.config.jsconst { DllReferencePlugin } = require;new DllReferencePlugin}),复制代码需要加载依赖的所有动态链接库。
建议让add-asset-html-webpack-plugin插件帮助我们做到这一点。
安装依赖于NPM I add-asset-html-web pack-plugin,它会将我们打包的dll.js注入到我们的index.html中,并在webpack.base.config.js中进行更改
const AddAssetHtmlWebpackPlugin = require;new AddAssetHtmlWebpackPlugin // 对应的 dll 件路径 }),复制代码这很容易理解,但是很难操作。好在Webpack5中已经没有了,不过是HardSourceWebpackPlugin的那种优化效果,不过极其简单。
提供中间缓存工作
二级建筑变化不大。

将节省第二次构建的时间。
我们在webpack4中使用hard-source-webpack-plugin:
const HardSourceWebpackPlugin = requireconst plugins = [new HardSourceWebpackPlugin]复制代码使happypack并发执任务Node.js之上的Webpack是单线程模型,这意味着Webpack需要单独处理任务,不能同时处理多个任务。Happy Pack可以让Webpack做到这一点。它将任务分解成多个进程并发执行,然后在进程处理完毕后将结果发送给主进程。充分发挥多核CPU电脑的威力。
主要用在施工时间长,工程复杂的时候。
npm i -D happypackconst HappyPack = require;//构造出一个共享进程池,在进程池中包含5个子进程var happyThreadPool = HappyPack.ThreadPool;// webpack.config.jsrules: [ {test: /.jsx $/, exclude: /node_modules/, use: [ {// 个loader对应个idloader: "happypack/loader id=babel", }, ], }, {test: /.css$/, include: path.resolve,use: ["happypack/loader id=css"], }, ]//在plugins中增加plugins:[new HappyPack,new HappyPack,]复制代码转自:file/tupian/20220929/6951297954770583565

