Webpack:代码分割

您所在的位置:网站首页 webpack打包好处 Webpack:代码分割

Webpack:代码分割

2023-10-08 21:55| 来源: 网络整理| 查看: 265

webpack 版本:4.35.0

webpack-cli 版本:3.3.5

为什么需要代码分割

在当前的前端项目中,常常使用 gulp、webpack、Browserify 等将多个文件压缩合并成一个。这个过程称为打包。 打包是一个将文件引入并合并到一个单独文件的过程,最终形成一个 “bundle”。接着在页面上引入该 bundle,整个应用即可一次性加载。

打包是个非常棒的技术,但随着你的应用增长,你的代码包也将随之增长。尤其是在整合了体积巨大的第三方库的情况下。你需要关注你代码包中所包含的代码,以避免因体积过大而导致加载时间过长。

为了避免搞出大体积的代码包,在前期就思考该问题并对代码包进行分割是个不错的选择。代码分割是由诸如 Webpack(代码分割)和 Browserify(factor-bundle)这类打包器支持的一项技术,能够创建多个包并在运行时动态加载。

对应用进行代码分割能够帮助你“懒加载”当前用户所需要的内容,能够显著地提高你的应用性能。尽管并没有减少应用整体的代码体积,但你可以避免加载用户永远不需要的代码,并在初始加载的时候减少所需加载的代码量。

关键点

打包解决了项目中依赖文件过多,而导致 http 请求过多的问题

代码分割则是解决打包的副作用——单文件过大,导致加载时间过长。

因此代码分割的关键点在于,如何控制分割粒度:

分割文件多少 文件大小 分割方法

有三种常用的代码分离方法:

入口起点:使用 entry 配置手动地分离代码。 动态导入:通过模块的内联函数调用来分离代码。 使用插件手动分离 entry

每个 entry 都会在最后的打包中输出一个对应的文件。因此可以显示地进行代码分割:

module.exports = { entry: { app: './src/index.js', print: './src/print.js' }, // ... output: { filename: '[name].[chunkhash].js', path: path.resolve(__dirname, './dist') } }

进行打包构建后会在 dist 文件夹输出:

app.f7badf83cc90de106d41.js print.e00bba994e917cc7fc59.js 动态导入

动态导入也可以达到代码分割的效果:

import _ from 'lodash'; function component() { var element = document.createElement('div'); // Lodash(目前通过一个 script 脚本引入)对于执行这一行是必需的 element.innerHTML = _.join(['你好呀', 'webpack'], ' '); element.onclick = (e) => import(/* webpackChunkName: "print" */ './print').then((Print) => { }) return element; } document.body.appendChild(component());

webpackChunkName 设置了输出包的名字。

module.exports = { entry: { app: './src/index.js' }, // ... output: { filename: '[name].[chunkhash].js', chunkFilename: '[name].[chunkhash].js', path: path.resolve(__dirname, './dist') } }

output 的 chunkFilename 决定了非入口(non-entry) chunk 文件的名称。这里的 chunk 是通过代码分割产生的,因此这里通过此选项来设置文件的名字。

运行打包:

app.73efde30ee057cb8c817.js print.e4408db3b4e5072295de.js 插件 CommonsChunkPlugin

在 webpack 4 之前,使用 CommonsChunkPlugin 进行公共 chunk 抽取。

module.exports = { entry: './src/index.js', entry: { main: './src/index.js', vendor: [ 'lodash' ] }, plugins: [ new CleanWebpackPlugin(['dist']), new HtmlWebpackPlugin({ title: 'Caching' }), new webpack.optimize.CommonsChunkPlugin({ name: 'vendor' }), new webpack.optimize.CommonsChunkPlugin({ name: 'manifest' }) ], output: { filename: '[name].[chunkhash].js', path: path.resolve(__dirname, 'dist') } };

这里有两点值得注意:

entry 中的 vendor:显式引用 lodash,由于 index.js 也导入了 lodash,因此它就变成了一个公共的模块。 使用 new webpack.optimize.CommonsChunkPlugin 抽取这些公共模块 SplitChunksPlugin

webpack 4 之后 CommonsChunkPlugin 被弃用了,使用 SplitChunksPlugin 代替。 SplitChunksPlugin 是开箱即用的,只需要在 module.exports 中进行配置:

module.exports = { //... optimization: { splitChunks: { // 该选项将用于配置 SplitChunksPlugin 插件 cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, name: 'vendor', chunks: 'initial', minChunks: 2 } } } }, output: { filename: '[name].[chunkhash].js', chunkFilename: '[name].[chunkhash].js', path: path.resolve(__dirname, './dist') } };

上面的配置会将 node_modules 下引用的所有模块都使用 vendor 这个作为 chunk 名以 output 中 chunkFilename 设置的格式打包到 dist 文件夹中。

SplitChunksPlugin 的选项:

cacheGroups 中每一项都接收如下参数:

filename: 重写 chunk 命名方式

vendors: { test: /[\\/]node_modules[\\/]/, name: 'vendor', filename:'[name].bundle.js' chunks: 'initial', minChunks: 2, }

最后会生成名字为 vendor.bundle.js 的文件

关于 SplitChunksPlugin 插件的配置,请参见 SplitChunksPlugin 解析

分割内容

代码分割的关键点在于控制分割粒度:

分割文件多少 文件大小

如果在不考虑大小的情况下,最后会打包出包含所有代码的单个文件。我们可以 optimization.splitChunks.maxSize 来控制 chunk 的大小以达到分割成多文件的目的。

只通过大小来控制代码分割拥有如下弊端:

入口文件大小未得到最大的优化

不能使用缓存。

在项目中,有些引入的工具的更新频率是非常低的,这时候

表现和结构未进行分离。

浏览器进行渲染的时候,表现和结构是基于不同的算法进行解析的。并且,样式代码也会增加请求的响应时间。

三方库

在项目中,常常会引入一些三方的工具库或者 polyfill 等,比如 lodash,babel-polyfill。这些代码在项目中改动很少,因此建议将这些代码提取到一个单独的文件中。

这样做有几个好处:

可以进行缓存 优化入口文件大小 进行关注点分离 CSS

在项目中可以使用 ExtractTextWebpackPlugin 插件将 CSS 文件抽取到单独的 bundle 中。

entry: { polyfill: './src/utils/polyfill.js', main: './src/main.js', app: './src/index.js' }, 参考链接

代码分离

缓存

加载-polyfills

ExtractTextWebpackPlugin



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3