webpack之optimization.runtimeChunk作用
runtimeChunk,直觀翻譯是運行時的chunk文件,其作用是啥呢,通過調研了解了一波,在此記錄下。
何為運行時代碼?
形如import('abc').then(res=>{})這種異步加載的代碼,在webpack中即為運行時代碼。
在VueCli工程中常見的異步加載路由即為runtime代碼。
搭建工程測試功效
1、搭建簡單的vue項目,使用vuecli新建一個只需要router的項目,腳手架默認路由配置了一個異步加載的about路由,如上圖所示
2、不設置runtimeChunk時,查看打包文件,此時不需要做任何操作,因為其默認是false,直接yarn build,此時生成的主代碼文件的hash值為7d50fa23。
3、接著改變about.vue文件的內容,再次build,查看打包結果,發現app文件的hash值發生了變化。
發現app文件的hash值發生了變化。
設置runtimeChunk是將包含chunks 映射關系的 list單獨從 app.js里提取出來,因為每一個 chunk 的 id 基本都是基于內容 hash 出來的,所以每次改動都會影響它,如果不將它提取出來的話,等于app.js每次都會改變。緩存就失效了。設置runtimeChunk之后,webpack就會生成一個個runtime~xxx.js的文件。
然后每次更改所謂的運行時代碼文件時,打包構建時app.js的hash值是不會改變的。如果每次項目更新都會更改app.js的hash值,那么用戶端瀏覽器每次都需要重新加載變化的app.js,如果項目大切優化分包沒做好的話會導致第一次加載很耗時,導致用戶體驗變差。現在設置了runtimeChunk,就解決了這樣的問題。所以這樣做的目的是避免文件的頻繁變更導致瀏覽器緩存失效,所以其是更好的利用緩存。提升用戶體驗。
4、新建vue.config.js,配置runtimeChunk,第一次打包,然后修改about,在打包一次,查看2次打包之后app文件的hash值的變化。
// vue.config.js module.exports = {productionSourceMap: false,configureWebpack: {runtimeChunk: true} }通過截圖看到2次打包生成的app文件的hash值沒有改變。和上面說的作用一致。
你以為這就完了?
1、查看下runtime~xxx.js文件內容:
function a(e){return i.p+"js/"+({about:"about"}[e]||e)+"."+{about:"3cc6fa76"}[e]+".js"}f發現文件很小,且就是加載chunk的依賴關系的文件。雖然每次構建后app的hash沒有改變,但是runtime~xxx.js會變啊。每次重新構建上線后,瀏覽器每次都需要重新請求它,它的 http 耗時遠大于它的執行時間了,所以建議不要將它單獨拆包,而是將它內聯到我們的 index.html 之中。這邊我們使用script-ext-html-webpack-plugin來實現。(也可使用html-webpack-inline-source-plugin,其不會刪除runtime文件。)
// vue.config.js const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin') module.exports = {productionSourceMap: false,configureWebpack: {optimization: {runtimeChunk: true},plugins: [new ScriptExtHtmlWebpackPlugin({inline: /runtime~.+\.js$/ //正則匹配runtime文件名})]},chainWebpack: config => {config.plugin('preload').tap(args => {args[0].fileBlacklist.push(/runtime~.+\.js$/) //正則匹配runtime文件名,去除該文件的preloadreturn args})} }重新打包,查看index.html文件
<!DOCTYPE html> <html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/favicon.ico><title>runtime-chunk</title><link href=/js/about.cccc71df.js rel=prefetch><link href=/css/app.b087a504.css rel=preload as=style><link href=/js/app.9f1ba6f7.js rel=preload as=script><link href=/css/app.b087a504.css rel=stylesheet> </head><body><noscript><strong>We're sorry but runtime-chunk doesn't work properly without JavaScript enabled. Please enable itto continue.</strong></noscript><div id=app></div><script>(function (e) { function r(r) { for (var n, a, i = r[0], c = r[1], l = r[2], f = 0, s = []; f < i.length; f++)a = i[f], Object.prototype.hasOwnProperty.call(o, a) && o[a] && s.push(o[a][0]), o[a] = 0; for (n in c) Object.prototype.hasOwnProperty.call(c, n) && (e[n] = c[n]); p && p(r); while (s.length) s.shift()(); return u.push.apply(u, l || []), t() } function t() { for (var e, r = 0; r < u.length; r++) { for (var t = u[r], n = !0, a = 1; a < t.length; a++) { var c = t[a]; 0 !== o[c] && (n = !1) } n && (u.splice(r--, 1), e = i(i.s = t[0])) } return e } var n = {}, o = { "runtime~app": 0 }, u = []; function a(e) { return i.p + "js/" + ({ about: "about" }[e] || e) + "." + { about: "cccc71df" }[e] + ".js" } function i(r) { if (n[r]) return n[r].exports; var t = n[r] = { i: r, l: !1, exports: {} }; return e[r].call(t.exports, t, t.exports, i), t.l = !0, t.exports } i.e = function (e) { var r = [], t = o[e]; if (0 !== t) if (t) r.push(t[2]); else { var n = new Promise((function (r, n) { t = o[e] = [r, n] })); r.push(t[2] = n); var u, c = document.createElement("script"); c.charset = "utf-8", c.timeout = 120, i.nc && c.setAttribute("nonce", i.nc), c.src = a(e); var l = new Error; u = function (r) { c.onerror = c.onload = null, clearTimeout(f); var t = o[e]; if (0 !== t) { if (t) { var n = r && ("load" === r.type ? "missing" : r.type), u = r && r.target && r.target.src; l.message = "Loading chunk " + e + " failed.\n(" + n + ": " + u + ")", l.name = "ChunkLoadError", l.type = n, l.request = u, t[1](l) } o[e] = void 0 } }; var f = setTimeout((function () { u({ type: "timeout", target: c }) }), 12e4); c.onerror = c.onload = u, document.head.appendChild(c) } return Promise.all(r) }, i.m = e, i.c = n, i.d = function (e, r, t) { i.o(e, r) || Object.defineProperty(e, r, { enumerable: !0, get: t }) }, i.r = function (e) { "undefined" !== typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }), Object.defineProperty(e, "__esModule", { value: !0 }) }, i.t = function (e, r) { if (1 & r && (e = i(e)), 8 & r) return e; if (4 & r && "object" === typeof e && e && e.__esModule) return e; var t = Object.create(null); if (i.r(t), Object.defineProperty(t, "default", { enumerable: !0, value: e }), 2 & r && "string" != typeof e) for (var n in e) i.d(t, n, function (r) { return e[r] }.bind(null, n)); return t }, i.n = function (e) { var r = e && e.__esModule ? function () { return e["default"] } : function () { return e }; return i.d(r, "a", r), r }, i.o = function (e, r) { return Object.prototype.hasOwnProperty.call(e, r) }, i.p = "/", i.oe = function (e) { throw console.error(e), e }; var c = window["webpackJsonp"] = window["webpackJsonp"] || [], l = c.push.bind(c); c.push = r, c = c.slice(); for (var f = 0; f < c.length; f++)r(c[f]); var p = l; t() })([]);</script><script src=/js/chunk-vendors.1e5c55d3.js></script><script src=/js/app.9f1ba6f7.js></script> </body> </html>index.html中已經沒有對runtime~xxx.js的引用了,而是直接將其代碼寫入到了index.html中,故不會在請求文件,減少http請求。
總結
runtimeChunk作用是為了線上更新版本時,充分利用瀏覽器緩存,使用戶感知的影響到最低。
總結
以上是生活随笔為你收集整理的webpack之optimization.runtimeChunk作用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: webpack从入门到精通(三)生产环境
- 下一篇: Promise和Async-Await的