Webpack的Bundle Split和Code Split有什麼差別? (詳解)
這篇文章帶給大家的內容是關於Webpack的Bundle Split和Code Split有什麼不同? (詳解)有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
說之前也是對 chunk 這個概念有些模糊,而且很多時候網路上的文章大部分在將程式碼分離動態載入之類的。寫這篇文章的目的也是要讓其他那些像我曾經對這個概念不是很清楚的童鞋有個清晰的認識。廢話不多說,擼起袖子直接乾!
Let's pe in!
Webpack 文件分离包括两个部分,一个是 Bundle 的分离,一个是 Code 代码的分离:
Bundle splitting: 实际上就是创建多个更小的文件,并行加载,以获得更好的缓存效果;主要的作用就是使浏览器并行下载,提高下载速度。并且运用浏览器缓存,只有代码被修改,文件名中的哈希值改变了才会去再次加载。
Code splitting: 只加载用户最需要的部分,其余的代码都遵从懒加载的策略;主要的作用就是加快页面加载速度,不加载不必要加载的东西。
准备工作
在进行文件分离之前的准备工作,我们先写一些代码:
入口文件 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 的意思是将所有来自 node_modules
中的依赖全部打包分离出来,这个时候我们再看打包的文件是个什么样子:
增加了 splitChunks 的配置,我们第三方模块都被打包到了 vendors~main.xxx.js 中去了,这个文件大小有 604k,而入口文件 main.xxx.js 则只有 7k
虽然说这样将第三方模块单独打包出去能够减小入口文件的大小,但这样仍然是个不小的文件;这个小的测试项目中我们使用到了 axios 和 lodash 这两个第三方模块,因此我们希望的应该是将这两个模块单独分离出来两个文件,而不是全部放到一个 vendors 中去,那么我们继续配置 webpack.config.js:
将每个 npm 包单独分离出来
这里我们需要使用到 webpack.HashedModuleIdsPlugin
这个插件
参考官方文档
直接上代码:
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,这样可以避免每次打包的文件哈希值变化首先增加 maxInitialRequests 并设置成 Infinity,指定这个入口文件最大并行请求数
然后将 minSize 和 minChunks 分别设置成 0 和 1,即使模块非常小也将其提取出来,并且这个模块的引用次数只有 1 也要提取
最后配置匹配的依赖以及分离出的文件名格式
另外,我们还将运行时代码分离出来,这块代码还可以配合 InlineManifestWebpackPlugin 直接插入到 HTML 文件中。这里我们将这个配置设置成 single,即将所有chunk的运行代码打包到一个文件中
这样 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 中我们可以用 Dynamic Imports
来替代上述方案,如果使用 ES6 语法那么需要使用到 babel 以及 babel 的插件 plugin-syntax-dynamic-import,在浏览器中为了保证兼容性,还需要安装 promise 的 polyfill,用法大同小异,可直接观摩 webpack 的官方文档
修改我们的代码:
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有什麼差別? (詳解)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

JavaScript是一種廣泛應用於Web開發的程式語言,而WebSocket則是一種用於即時通訊的網路協定。結合二者的強大功能,我們可以打造一個高效率的即時影像處理系統。本文將介紹如何利用JavaScript和WebSocket來實作這個系統,並提供具體的程式碼範例。首先,我們需要明確指出即時影像處理系統的需求和目標。假設我們有一個攝影機設備,可以擷取即時的影像數
