本篇文章给大家带来的内容是关于Webpack的Bundle Split和Code Split有什么区别?(详解)有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
本篇文章给大家带来的内容是关于Webpack的Bundle Split和Code Split有什么区别?(详解)有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 话说之前也是对 chunk 这个概念有些模糊,并且很多时候网上的文章大部分在将代码分离动态加载之类的。写这篇文章的目的也是想让其他那些跟我一样曾经对这个概念不是很清楚的童鞋有个清晰的认识。废话不多说,撸起袖子直接干! Let's pe in! Webpack 文件分离包括两个部分,一个是 Bundle 的分离,一个是 Code 代码的分离:
准备工作 在进行文件分离之前的准备工作,我们先写一些代码: 入口文件 src/index.js: const { getData } = require('./main') const { findMaxIndex } = require('./math') let arr = [1,2,123,21,3,21,321,1] findMaxIndex(arr) getData('./index.html') 两个依赖模块: src/main.js: const axios = require('axios') const getData = url => { axios.get(url).then(d => { console.log(d.status) console.log(d.data.length) }) } module.exports = { getData } src/math.js: const _ = require('lodash') const findMaxIndex = arr => { let x = _.max(arr) let r = Array.prototype.indexOf.call(arr, x) console.log(r); } module.exports = { findMaxIndex } 增加一个 webpack 配置文件 webpack.config.js: const path = require('path') module.exports = { mode: 'development', entry: path.resolve(__dirname, 'src/index.js'), output: { path: path.resolve(__dirname, 'dist'), filename: '[name].[contenthash].js' }, } 文件分离之前打包需要的时间 在 bundle split 和 code split 操作之前,我们先看一下当前默认打包的效果: 全部依赖都被打包到 main.xxx.js 中去,大小是 609k 开始分离操作 Bundle Split Bundle Split 的主要任务是将多个引用的包和模块进行分离,避免全部依赖打包到一个文件下 基本用法 Webpack 4 中需要使用到 optimization.splitChunks 的配置: const path = require('path') module.exports = { mode: 'development', entry: path.resolve(__dirname, 'src/index.js'), output: { path: path.resolve(__dirname, 'dist'), filename: '[name].[contenthash].js' }, optimization: { splitChunks: { chunks: 'all' } } } optimization.splitChunks 的意思是将所有来自 增加了 splitChunks 的配置,我们第三方模块都被打包到了 vendors~main.xxx.js 中去了,这个文件大小有 604k,而入口文件 main.xxx.js 则只有 7k 虽然说这样将第三方模块单独打包出去能够减小入口文件的大小,但这样仍然是个不小的文件;这个小的测试项目中我们使用到了 axios 和 lodash 这两个第三方模块,因此我们希望的应该是将这两个模块单独分离出来两个文件,而不是全部放到一个 vendors 中去,那么我们继续配置 webpack.config.js: 将每个 npm 包单独分离出来这里我们需要使用到 参考官方文档 直接上代码: const path = require('path') const webpack = require('webpack') module.exports = { mode: 'development', entry: path.resolve(__dirname, 'src/index.js'), plugins: [ new webpack.HashedModuleIdsPlugin() // 根据模块的相对路径生成 HASH 作为模块 ID ], output: { path: path.resolve(__dirname, 'dist'), filename: '[name].[contenthash].js' }, optimization: { runtimeChunk: 'single', splitChunks: { chunks: 'all', // 默认 async 可选值 all 和 initial maxInitialRequests: Infinity, // 一个入口最大的并行请求数 minSize: 0, // 避免模块体积过小而被忽略 minChunks: 1, // 默认也是一表示最小引用次数 cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, // 如果需要的依赖特别小,可以直接设置成需要打包的依赖名称 name(module, chunks, chcheGroupKey) { // 可提供布尔值、字符串和函数,如果是函数,可编写自定义返回值 const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1] // 获取模块名称 return `npm.${packageName.replace('@', '')}` // 可选,一般情况下不需要将模块名称 @ 符号去除 } } } } } } 这里我们主要做了几件事: 为了避免每次打包的文件哈希变化,我们可以使用 webpack 内置的 HashedModuleIdsPlugin,这样可以避免每次打包的文件哈希值变化 这样 Bundle Split 的操作基本就完成了,让我们看看效果如何: 所依赖的几个模块都被分离出去了 使用 HtmlWebpackPlugin 这个插件将 js 代码注入 html 文件中 npm i -D html-webpack-plugin 修改 webpack.config.js 文件: // 配置文件引入这个插件 var HtmlWebpackPlugin = require('html-webpack-plugin'); // ... module.exports = { // ... plugins: [ new HtmlWebpackPlugin(), new webpack.HashedModuleIdsPlugin() // 根据模块的相对路径生成 HASH 作为模块 ID ], // ... } 安装 http-server 或使用 vscode 的插件 Live Server 将代码放入一个本地服务器中,打开浏览器的调试窗口进入到 Network 面板: 可以看到我们将模块单独分离出来并行加载,这样比单独加载一个庞大的包要快不少,接下来我们还要进行代码分离,将不必要加载的模块延迟加载 Code Split 代码分离实际上就是只加载用户需要使用到的部分代码,不是必须的就暂时不加载。 这里我们要用到 require.ensure 这个方法去获取依赖,这样 webpack 打包之后将会增加运行时代码,在设定好的条件下才会触发获取这个依赖。 在 ES6 中我们可以用 修改我们的代码: const { getData } = require('./main') let arr = [1,2,123,21,3,21,321,1] getData('./index.html') setTimeout(() => { require.ensure(['./math'], function(require) { const { findMaxIndex } = require('./math') console.log(findMaxIndex(arr)) }) }, 3000) 我们设定了一个定时器,只有在 3000 毫秒以后,浏览器才会去请求这个 math 模块 编译之后,打开调试面板刷新浏览器: 在页面刚加载完毕后,浏览器会尝试获取上述这么几个模块,因为模块都很小很快就加载完成了 在 3500ms 左右,浏览器才会去获取 requie.ensure 方法定义的 math 模块,因 math 模块又包含依赖 lodash,因此这个 lodash 第三方模块也会被按需加载。 这样我们就完成了代码分离的操作,这样做的优势就是不需要第一时间加载的模块,可以推迟加载,以页面的加载速度。当然,上面的 timeout 定时器完全可以换成其他诸如按钮点击之类的事件来触发。 以上就是Webpack的Bundle Split和Code Split有什么区别?(详解)的详细内容,更多请关注模板之家(www.mb5.com.cn)其它相关文章! |