笔者最近在整理关于 webpack
相关的知识点,一方面是由于本身掌握的知识点比较零碎、不够系统,有时候碰到问题不知从何下手,另一方面 webpack5.0
已经在路上了,这的确是一个让人头秃的消息。javascript
因此这就促使了我去系统性的回顾了一遍 webpack4.0
的全部知识点,包括 webpack
的由来,各类配置的使用、性能优化、Webpack
的底层原理、相关脚手架的配置分析,都回顾了一波,大体目录以下图:css
笔者把系列的文章都扔在了这个仓库:webpack 学习整理文档,有兴趣的同窗能够去看一波。html
今天这篇文章也是笔者就学习文档中的性能优化这一块内容作的整理与回顾。前端
文章中使用到的案例代码连接放在了最底部,你们自取。
先来讲说为何要优化?固然若是你的项目很小,构建很快,其实不须要特别关注性能方面的问题。java
可是随着项目涉及到的页面愈来愈多,功能和业务代码也会愈来愈多,相应的 webpack
的构建时间也会愈来愈久,这个时候咱们就不得不考虑性能优化的事情了。node
由于这个构建时间与咱们的平常开发是密切相关,当咱们本地开发启动 devServer
或者 build
的时候,若是时间过长,会大大下降咱们的工做效率。react
试想一个场景,咱们忽然碰到一个紧急 bug
,项目启动须要花费 3/4
分钟,改完后项目 build
上线也要 3/4
分钟,这个时候脑瓜是否是 duang
、duang
、duang
...webpack
那接下来咱们看一下如何优化 webpack
的性能,提高 webpack
的构建速度。git
在动手优化以前,咱们须要有一个量化的指标,得知道影响构建时间的问题究竟出在哪里,是某个 chunk
文件太大了,仍是哪个 loader
或者 plugin
耗时过久了等等。github
咱们能够对经过一些工具对项目进行相应的 体积 和 速度 分析, 而后对症下药。
能够经过官方提供的 stat.json
文件帮助咱们分析打包结果,stat.json
文件能够经过下面语句快速生成:
webpack --profile --json > stats.json
接着咱们经过官网提供的 stats.json 分析工具 进行分析,上传 stats.json
文件以后,就能够获得以下图所示分析结果:
其中包括 webpack
的版本、打包时间、打包过程的 hash
值、模块数量( modules
)、chunk
数量、打包生层的静态文件 assets
以及打包的警告和错误数。
咱们能够分析其提供的内容,进行大体问题的定位。
webpack-bundle-analyzer 是打包分析神器,它的界面我的以为很好看,并且能很直观的给出每个打包出来的文件的大小以及各自的依赖,可以更加方便的帮助咱们对项目进行分析。
使用以下:
// config/webpack.common.js const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); const commonConfig = { // ... plugins: [ new BundleAnalyzerPlugin({ analyzerPort: 8889, // 指定端口号 openAnalyzer: false, }), ] // ... }
webpack-bundle-analyzer
其底层也是依赖stat.json
文件的,经过对stat.json
的分析,得出最后的分析页面
经过分析工具的分析,咱们能够知道哪些文件耗时比较多,打包出来的体积比较大,从而对有问题的文件进行优化。
咱们能够经过 speed-measure-webpack-plugin 这个插件帮助咱们分析整个打包的总耗时,以及每个loader
和每个 plugins
构建所耗费的时间,从而帮助咱们快速定位到能够优化 Webpack
的配置。
如上图,耗时比较长的会以红色标出。
引入此插件,建立一个 plugins
实例 smp
包裹 webpack
配置文件便可,咱们修改一下 webpack
的公共配置文件 webpack.common.js
:
// config/webpack.common.js const SpeedMeasurePlugin = require("speed-measure-webpack-plugin"); const smp = new SpeedMeasurePlugin(); // ... module.exports = (production) => { if (production) { const endProdConfig = merge(commonConfig, prodConfig); return smp.wrap(endProdConfig); } else { const endDevConfig = merge(commonConfig, devConfig); return smp.wrap(endDevConfig); } };
笔者文章演示的代码配置文件分为三个,分别为 开发环境配置文件,生产环境配置文件,以及前两者共用的公共配置文件,以下:
webpack.dev.js
:开发环境使用的配置文件webpack.prod.js
:生产环境使用的配置文件webpack.common.js
:公共配置文件
执行打包以后,能够看到以下效果图:
注意:speed-measure-webpack-plugin
对于webpack
的升级还不够完善,暂时还没法与你本身编写的挂载在html-webpack-plugin
提供的hooks
上的自定义Plugin
(add-asset-html-webpack-plugin
就是此类)共存,有人已经在 github 上提了 issue 了,可是貌似仍是没有解决。
通过相应的体积分析和速度分析以后,咱们即可以着手进行优化了。
这个是 webpack
性能优化的万能膏药,升级版本一定能带来性能提高,并且提高很明显。
咱们能够看一张对比图:
从上图中咱们能够看到,webpack4.0
的构建速度远远快于webpack3.0
,官方也说升级以后,升级版本以后,构建时间能够下降60% - 98%
左右。
在每个版本的更新,webpack
内部确定会作不少优化,而 webpack
是依赖 Node
的 js
运行环境,升级他们对应的版本,webpack
的速度确定也可以得到提高。
说不定在webpack5.0
出来以后,咱们今天讲到的大部分性能优化方法都会被集成到webpack
自身中去,咱们只须要经过几个简单的配置就能完成性能配置。
同时新版本的包管理工具(Npm
、Yarn
)也能够更快的帮助咱们分析一些包的依赖和引入,从而提升打包速度。
v8
引擎带来的优化(for of
替代 forEach
、Map
和 Set
替代 Object
、includes
替代 indexOf
)md4 hash
算法webpack AST
能够直接从 loader
传递给 AST
,减小解析时间咱们能够在 github
上的 webpack
库的 releases 版本迭代 页面中查看其带来的性能优化:
v8
性能优化例子:咱们能够来看一个例子,比较使用 includes
替代 indexOf
以后带来的速度提高,建立 compare-includes-indexof.js
文件,在这个文件中建一个 10000000
长度的数组,记录两个函数分别消耗的时间:
const ARR_SIZE = 10000000; const hugeArr = new Array(ARR_SIZE).fill(1); // includes const includesTest = () => { const arrCopy = []; console.time('includes') let i = 0; while (i < hugeArr.length) { arrCopy.includes(i++); } console.timeEnd('includes'); } // indexOf const indexOfTest = () => { const arrCopy = []; console.time('indexOf'); for (let item of hugeArr) { arrCopy.indexOf(item); } console.timeEnd('indexOf'); } includesTest(); indexOfTest();
能够发现 includes
的速度远远快于 indexOf
:
includes
:12.224ms
indexOf
:147.638ms
因此在项目上尽量使用比较新的 webpack
、Node
、Npm
、Yarn
版本,是咱们提高打包速度的第一步。
webpack
是个项目打包工具,通常项目打完包之后,须要发布到服务器上供用户使用,为了用户体验,咱们的项目体积须要越小越好,因此 webpack
中打包的体积是 webpack
中重要的一环。
webpack4.0
默认在生产环境的时候是支持代码压缩的,即 mode=production
模式下。
实际上 webpack4.0
默认是使用 terser-webpack-plugin 这个压缩插件,在此以前是使用 uglifyjs-webpack-plugin,二者的区别是后者对 ES6 的压缩不是很好,同时咱们能够开启 parallel
参数,使用多进程压缩,加快压缩。
// config/webpack.common.js const TerserPlugin = require('terser-webpack-plugin'); // ... const commonConfig = { // ... optimization: { minimize: true, minimizer: [ new TerserPlugin({ parallel: 4, // 开启几个进程来处理压缩,默认是 os.cpus().length - 1 }), ], }, // ... }
咱们能够借助 optimize-css-assets-webpack-plugin
插件来压缩 css
,其默认使用的压缩引擎是 cssnano
。 具体使用以下:
// config/webpack.prod.js const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); // ... const prodConfig = { // ... optimization: { minimizer: [ new OptimizeCSSAssetsPlugin({ assetNameRegExp: /\.optimize\.css$/g, cssProcessor: require('cssnano'), cssProcessorPluginOptions: { preset: ['default', { discardComments: { removeAll: true } }], }, canPrint: true, }) ] }, }
CSS
使用 PurgeCSS
来完成对无用 css
的擦除,它须要和 mini-css-extract-plugin
配合使用。
// config/webpack.common.js const PurgecssPlugin = require('purgecss-webpack-plugin'); // ... const PATHS = { src: path.join(__dirname, './src') }; const commonConfig = { // ... plugins: [ // ... new PurgecssPlugin({ paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }), }), ] // ... }
在未使用此插件以前,好比咱们只用到了 navcontact
这个类,其余的都没有用到,咱们在未引入以前打包一下,发现未用到的 css
仍是会被打包进去:
引入插件后,从新进行打包,发现没有用到的 css
都被擦除了:
更多使用你们可参考 PurgeCSS 文档。
通常来讲在打包以后,一些图片文件的大小是远远要比 js
或者 css
文件要来的大,因此咱们首先要作的就是对于图片的优化,咱们能够手动的去经过线上的图片压缩工具,如 tiny png 帮咱们来压缩图片。
可是这个比较繁琐,在项目中咱们但愿可以更加自动化一点,自动帮咱们作好图片压缩,这个时候咱们就能够借助 image-webpack-loader 帮助咱们来实现。它是基于 imagemin 这个 Node 库来实现图片压缩的。
使用很简单,咱们只要在 file-loader
以后加入 image-webpack-loader
便可:
// config/webpack.common.js // ... module: { rules: [ { test: /\.(png|jpg|gif)$/, use: [ { loader: 'file-loader', options: { name: '[name]_[hash].[ext]', outputPath: 'images/', } }, { loader: 'image-webpack-loader', options: { // 压缩 jpeg 的配置 mozjpeg: { progressive: true, quality: 65 }, // 使用 imagemin**-optipng 压缩 png,enable: false 为关闭 optipng: { enabled: false, }, // 使用 imagemin-pngquant 压缩 png pngquant: { quality: '65-90', speed: 4 }, // 压缩 gif 的配置 gifsicle: { interlaced: false, }, // 开启 webp,会把 jpg 和 png 图片压缩为 webp 格式 webp: { quality: 75 } } } ] }, ] } // ...
咱们先不使用这个 loader
打包一下,图片大小是 2.1MB
:
使用 image-webpack-loader
以后,图片大小是 666KB
:
压缩的效果仍是很明显的。
有时候咱们写的某些模块根本没有使用,可是仍是被打包了,这样实际上会拖累 webpack
的打包速度,并且也会增长打包文件的体积,因此咱们可使用 tree-shaking
将这些代码剔除掉。
或者也可使用 splitChunksPlugin
把一个大的文件分割成几个小的文件,这样也能够有效的提高 webpack
的打包速度,详细的配置介绍你们能够看笔者写的 配置 SplitChunksPlugin,里面详细介绍了怎么配置 splitChunks
,以及各参数的用法与意义,在这里就不展开讲了。
讲完打包体积的优化,咱们来看一下在速度方面的优化。
通常来讲在项目开发中,咱们会区分开发和生产环境两套配置,各司其职。
在开发阶段:咱们须要 webpack-dev-server
来帮咱们进行快速的开发,同时须要 HMR 热更新 帮咱们进行页面的无刷新改动,而这些在 生产环境 中都是不须要的。
在生产阶段:咱们须要进行 代码压缩、目录清理、计算 hash、提取 CSS 等等;
实现起来很简单,咱们前面也提到过,就新建三个 webpack
的配置文件就行:
webpack.dev.js
:开发环境的配置文件webpack.prod.js
:生产环境的配置文件webpack.common.js
:公共配置文件经过 webpack-merge
来整合两个配置文件共同的配置 webpack.common.js
,具体能够参照源码。
对 webpack
的 resolve
参数进行合理配置,使用 resolve
字段告诉 webpack
怎么去搜索文件。
resolve.extensions
在导入语句没带文件后缀时,webpack
会自动带上后缀后去尝试询问文件是否存在,查询的顺序是按照咱们配置 的 resolve.extensions
顺序从前到后查找,webpack
默认支持的后缀是 js
与 json
。
举个🌰:若是咱们配置 resolve.extensions= ['js', 'json']
,那么 webpack
会先找 xxx.js
若是没有则再查找 xxx.json
,因此咱们应该把经常使用到的文件后缀写在前面,或者 咱们导入模块时,尽可能带上文件后缀名。
虽然
extensions
会优先查找数组内的值,可是咱们不要一古脑儿的把全部后缀都往里面塞,这会调用屡次文件的查找,这样就会减慢打包速度。
resolve.modules
这个属性告诉 webpack
解析模块时应该搜索的目录,绝对路径和相对路径都能使用。使用绝对路径以后,将只在给定目录中搜索,从而减小模块的搜索层级:
// config/webpack.common.js // ... const commonConfig = { // ... resolve: { extensions: ['.js', '.jsx'], mainFiles: ['index', 'list'], alias: { alias: path.resolve(__dirname, '../src/alias'), }, modules: [ path.resolve(__dirname, 'node_modules'), // 指定当前目录下的 node_modules 优先查找 'node_modules', // 将默认写法放在后面 ] }, // ... } // ...
resolve.alias
减小查找过程alias
的意思为 别名,能把原导入路径映射成一个新的导入路径。
好比咱们项目中可能会有一些相对路径的写法,就可使用 alias
配置来减小查找过程;
还好比咱们常用的 react
库,其实咱们能够直接使用其 dist
目录下打包好的 react.min.js
,这样就能跳过耗时的模块解析,具体示例配置以下:
// config/webpack.common.js // ... const commonConfig = { // ... resolve: { // ... alias: { react: path.resolve(__dirname, './node_modules/react/dist/react.min.js'), @alias: path.resolve(__dirname, '../src/alias'), }, }, // ... } // ...
这个笔者在实际项目中没有尝试过,不过也是一个思路,你们有机会能够尝试一波。
排除 Webpack
不须要解析的模块,即便用 loader
的时候,在尽可能少的模块中去使用。
咱们能够借助 include
和 exclude
这两个参数,规定 loader
只在那些模块应用和在哪些模块不该用。
咱们修改公共配置文件 webpack.common.js
:
// config/webpack.common.js // ... const commonConfig = { // ... module: { rules: [ { test: /\.js|jsx$/, exclude: /node_modules/, include: path.resolve(__dirname, '../src'), use: ['babel-loader'] }, // ... ] }, } // ...
首先咱们不加 exclude
和 include
两个参数,打包一下 npm run build
,打包时间 3350ms
左右:
接着咱们加上这两个参数,意思分别是:
exclude: /node_modules/
:排除 node_modules
下面的文件include: path.resolve(__dirname, '../src')
:只对 src
下面的文件使用从新打包一下,打包时间变成了 1400ms
左右:
因为运行在 Node.js
之上的 webpack
是单线程模型的,因此 webpack
须要处理的事情须要一件一件的作,不能多件事一块儿作。
若是 webpack
能同一时间处理多个任务,发挥多核 CPU
电脑的威力,那么对其打包速度的提高确定是有很大的做用的。
HappyPack
原理:每次 webapck
解析一个模块,HappyPack
会将它及它的依赖分配给 worker
线程中。处理完成以后,再将处理好的资源返回给 HappyPack
的主进程,从而加快打包速度。
在webpack4.0
中使用happypack
须要使用其5.0
版本。
咱们将 HappyPack
引入公共配置文件,他的用法就是将相应的 loader
替换成 happypack/loader
,同时将替换的 loader
放入其插件的 loaders
选项,咱们暂且替换一下 babel-loader
:
// config/webpack.common.js // ... const makePlugins = (configs) => { const plugins = [ // ... new HappyPack({ loaders: ['babel-loader'] }), ]; // ... return plugins; } // ... const commonConfig = { entry: { main: "./src/index.js", entry2: "./src/entry2.js", entry3: "./src/entry3.js", entry4: "./src/entry4.js", entry5: "./src/entry5.js", entry6: "./src/entry6.js", }, // ... module: { rules: [{ test: /\.jsx?$/, // exclude: /node_modules/, // include: path.resolve(__dirname, '../src'), use: [ 'happypack/loader' // 'babel-loader' ] }] }, // ... } // ...
为了让效果更加明显一点,咱们在项目下多增长几个入口文件,在不使用 happypack
的状况下,进行一次打包,时间差很少是 8s
多:
开启 happypack
以后,咱们能够从控制台中看到,happypack
默认帮咱们开启了 3
个进程,打包时间变成了6.5s
左右:
注意:HappyPack
的做者如今基本上也不维护这个插件了,由于做者对此项目的兴趣正在减弱。他也推荐咱们使用webpack
官方 thread-loader。
更多参数你们能够参考 HappyPack 官网
thread-loader
webpack
官方推出的一个多进程方案,用来替代 HappyPack
。
原理和 HappyPack
相似,webpack
每次解析一个模块,thread-loader
会将它及它的依赖分配给 worker
线程中,从而达到多进程打包的目的。
使用很简单,直接在咱们使用的 loader
以前加上 thread-loader
就行,咱们须要先注释掉 HappyPack
代码:
// config/webpack.common.js // ... const commonConfig = { // ... module: { rules: [{ test: /\.jsx?$/, // exclude: /node_modules/, // include: path.resolve(__dirname, '../src'), use: [ { loader: 'thread-loader', options: { workers: 3, // 开启几个 worker 进程来处理打包,默认是 os.cpus().length - 1 } }, 'babel-loader' ] }] }, // ... } // ...
咱们从新运行一下,也是差很少 6.5s
左右:
咱们在打包的时候,通常来讲第三方模块是不会变化的,因此咱们想只要在第一次打包的时候去打包一下第三方模块,并将第三方模块打包到一个特定的文件中,当第二次 webpack
进行打包的时候,就不须要去 node_modules
中去引入第三方模块,而是直接使用咱们第一次打包的第三方模块的文件就行。
webpack.DllPlugin
就是来解决这个问题的插件,使用它能够在第一次编译打包后就生成一份不变的代码供其余模块引用,这样下一次构建的时候就能够节省开发时编译打包的时间。
咱们在配置文件目录 config
下新建一个 webpack.dll.js
,此文件用于将咱们的第三方包文件打包到 dll
文件夹中去:
// config/webpack.dll.js const path = require('path'); const webpack = require('webpack'); module.exports = { mode: 'production', // 环境 entry: { vendors: ['lodash'], // 将 lodash 打包到 vendors.js 下 react: ['react', 'react-dom'], // 将 react 和 react-dom 打包到 react.js 下 }, output: { filename: '[name].dll.js', // 输出的名字 path: path.resolve(__dirname, '../dll'), // 输出的文件目录 library: '[name]' // 将咱们打包出来的文件以所有变量的形式暴露,能够在浏览器变量的名字进行访问 }, plugins: [ // 对生成的库文件进行分析,生成库文件与业务文件的映射关系,将结果放在 mainfest.json 文件中 new webpack.DllPlugin({ name: '[name]', // 和上面的 library 输出的名字要相同 path: path.resolve(__dirname, '../dll/[name].manifest.json'), }) ] }
library
的意思其实就是将 dll
文件以一个全局变量的形式导出出去,便于接下来引用,以下图:mainfest.json
文件是一个映射关系,它的做用就是帮助 webpack
使用咱们以前打包好的 ***.dll.js
文件,而不是从新再去 node_modules
中去寻找。咱们在命令行中打包一下 dll
文件,能够看到根目录生成了一个 dll
文件夹,而且在下面生成了相应的文件,而且 loader
打包到了 vendor.dll.js
中,react
和 react-dom
打包到了 react.dll.js
中了:
接着咱们须要去修改公共配置文件 webpack.common.js
,将咱们以前生成的 dll
文件导入到 html
中去,若是咱们不想本身手动向 html
文件去添加 dll
文件的时候,咱们能够借助一个插件 add-asset-html-webpack-plugin
,此插件顾名思义,就是将一些文件加到 html
中去。
同时咱们须要使用 webpack
自带的 DllReferencePlugin
插件对 mainfest.json
映射文件进行分析。
// config/webpack.common.js const webpack = require('webpack'); const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin'); // ... const commonConfig = { // ... plugins: [ // ... new AddAssetHtmlWebpackPlugin({ filepath: path.resolve(__dirname, '../dll/vendors.dll.js') }), new AddAssetHtmlWebpackPlugin({ filepath: path.resolve(__dirname, '../dll/react.dll.js') }), new webpack.DllReferencePlugin({ manifest: require(path.resolve(__dirname, '../dll/vendors.dll.mainfest.json')) }), new webpack.DllReferencePlugin({ manifest: require(path.resolve(__dirname, '../dll/react.dll.mainfest.json')) }), ], // ... } // ...
这里的代码还能够优化,具体你们能够参考笔者整理的笔记中 dll优化 这一节。
咱们进行一次打包,能够看到打包耗时为 1450ms
左右,同时能够看到库文件打包到的 vendors.chunk.js
为 1.22MB
。
咱们注释掉对 dll
的引用分析以后,从新打包,打包耗时为 1950ms
左右,同时能够看到 vendors.chunk.js
为 5.28MB
。
咱们能够开启相应 loader
或者 plugin
的缓存,来提高二次构建的速度。通常咱们能够经过下面几项来完成:
babel-loader
开启缓存terser-webpack-plugin
开启缓存cache-loader
或者 hard-source-webpack-plugin 若是项目中有缓存的话,在 node_modules
下会有相应的 .cache
目录来存放相应的缓存。
babel-loader
首先咱们开启 babel-loader
的缓存,咱们修改 babel-loader
的参数,将参数 cacheDirectory
设置为 true
:
// config/webpack.common.js // ... module: { rules: [ { test: /\.jsx?$/, // exclude: /node_modules/, // include: path.resolve(__dirname, '../src'), use: [ { loader: 'babel-loader', options: { cacheDirectory: true, } }, ] }, ] } // ...
首次打包时间为 8.5s
左右,打包完成以后,咱们能够发如今 node_modules
下生成了一个 .cache
目录,里面存放了 babel
的缓存文件:
咱们从新打包一次,会发现时间变成了 6s
左右:
TerserPlugin
咱们经过将 TerserPlugin
中的 cache
设为 true
,就能够开启缓存:
// config/webpack.common.js const TerserPlugin = require('terser-webpack-plugin'); // ... const commonConfig = { // ... optimization: { minimize: true, minimizer: [ new TerserPlugin({ parallel: 4, // 开启几个进程来处理压缩,默认是 os.cpus().length - 1 cache: true, }), ], }, // ... }
首次打包时间为 8-9s
左右,同时在 .cache
目录下生成了 terser-webpack-plugin
缓存目录:
咱们从新打包一次,会发现时间变成了 5s
左右:
HardSourceWebpackPlugin
这个插件其实就是用于给模块提供一个中间的缓存。
使用以下,咱们直接在插件中引入就 ok 了:
// config/webpack.common.js const HardSourceWebpackPlugin = require('hard-source-webpack-plugin'); // ... const plugins = [ // ... new HardSourceWebpackPlugin(), ]; // ...
咱们打包一下,能够看到在第一次打包的时候 HardSourceWebpackPlugin
就帮咱们开始生成打包文件了,同时在 .cache
目录生成了 hard-source
目录,第一次打包耗时 6.6s
左右:
咱们从新打包一次,会发现时间变成了 2.7s
左右:
以前咱们有讲过,以前咱们打包生成 sourceMap
的时候,若是信息越详细,打包速度就会越慢
因此咱们要在代码打包过程当中的时候,在对应的环境使用对应的 sourceMap
很重要。
除了上述咱们提到的一些经常使用方法,还有其余的一些方法,好比:
ES6 Modules
语法,以保证 Tree-Shaking
起做用由于tree-shaking
只对ES6 Modules
静态引入生效,对于相似于CommonJs
的动态引入方式是无效的
Ployfill
若是咱们对于引入的polyfill
不作处理的话,Webpack
会把全部的Polyfill
都加载进来,致使产出文件过大。推荐使用@babel/preset-env
的useBuiltIns='usage'
方案,此配置项会根据浏览器的兼容性帮助咱们按需引入所需的垫片;此外咱们也可使用动态polyfill
服务,每次根据浏览器的User Agent
,下发不一样的Polyfill
,具体能够参考polyfill.io
。
webpackPrefetch
使用
webpackPrefetch
来提早预加载一些资源,意思就是
未来可能须要一些模块资源,在核心代码加载完成以后带宽空闲的时候再去加载须要用到的模块代码。
icon
类图片使用 css Sprite
来合并图片
若是
icon
类图片太多的话,就使用雪碧图合成一张图片,减小网络请求,或者使用字体文件。
html-webpack-externals-plugin
此插件能够将一些公用包提取出来使用cdn
引入,不打入bundle
中,从而减小打包文件大小,加快打包速度。
chunk
的哈希值在生产环境打包,必定要配置文件的hash
,这样有助于浏览器缓存咱们的文件,当咱们的代码文件没变化的时候,用户就只须要读取浏览器缓存的文件便可。 通常来讲javascript
文件使用[chunkhash]
、css
文件使用[contenthash]
、其余资源(例如图片、字体等)使用[hash]
。
更多性能优化方法笔者就再也不一一列举了,由于关于 webpack
性能优化的方法实在是太多了,你们能够根据实际遇到的问题制定相关的优化方案。
今天这篇文章介绍了 webpack
打包的一些优化方案,从项目体积再到对项目速度,咱们提出了一些优化方案,你们能够在具体的项目中去进行实践。
固然我还要提一嘴,若是你的项目自己构建就比较快,那么你其实就不须要使用文章中提到的方法去对项目进行优化,可能效果会拔苗助长。
对于文章中有些一笔带过的内容,你们能够在个人 webpack 学习整理文档 找到相应的介绍。
实不相瞒,想要个赞!
示例代码能够看这里: