之前讲过webpack4中的runtimeChunk配置:webpack4中的 optimization.runtimeChunk,我们知道了runtimeChunk分离的是运行时的模块,它和业务无关,主要包含webpack的一些定义以及从主模块分离出去模块的信息。它的代码量一般比较小,且比较容易变化,为了优化代码,可以考虑将runtimeChunk做成内联的,也就是将runtimeChunk部分的代码直接写入index.html。

    HtmlWebpackPlugin

    我们先看个普通的vue项目,并且配置了runtimeChunk:

    1. /*---App.vue---*/
    2. <template>
    3.   <div id="app">
    4.     <div id="nav">
    5.       <router-link to="/about">About</router-link>
    6.     </div>
    7.     <router-view/>
    8.   </div>
    9. </template>
    10. /*---About.vue---*/
    11. <template>
    12.   <div class="about">
    13.     <h1>This is an about page</h1>
    14.   </div>
    15. </template>
    16. /*---router.js---*/
    17. Vue.use(VueRouter)
    18. const routes = [
    19.   {
    20.     path: '/about',
    21.     name: 'about',
    22.     component: () => import('../views/About.vue')
    23.   }
    24. ]

    配置vue.config.js:

    1. configureWebpack: {
    2.     optimization: {
    3.         runtimeChunk:{
    4.             name:()=>'aaa'
    5.         },
    6.     },
    7. }

    打包结果如下:

    aaa.***.js是分离出的runtimeChunk,那么如何将它的内容直接写入html中呢?重新配置vue.config.js:

    1. const HtmlWebpackPlugin = require('html-webpack-plugin');
    2. const InlineSourcePlugin = require('html-webpack-inline-source-plugin');
    3. configureWebpack: {
    4.     optimization: {
    5.         runtimeChunk:{
    6.             name:()=>'aaa'
    7.         },
    8.     },
    9.     plugins: [
    10.         new HtmlWebpackPlugin({
    11.             // Inline all files which names start with “aaa” and end with “.js”.
    12.             // That’s the default naming of runtime chunks
    13.             inlineSource: 'aaa.+\\.js',
    14.         }),
    15.         // This plugin enables the “inlineSource” option
    16.         new InlineSourcePlugin(),
    17.     ]
    18. }

    重新打包,我们可以看到runtimeChunk已经写入index.html了:

    1. <!DOCTYPE html>
    2. <html>
    3.     <head>
    4.         <meta charset="UTF-8">
    5.         <title>Webpack App</title>
    6.         <link href="/css/app.7edf2138.css" rel="stylesheet">
    7.     </head>
    8.     <body>
    9.         <script type="text/javascript">
    10.             (function(e) {
    11.     function r(r) {
    12.         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;
    13.         for(in c) Object.prototype.hasOwnProperty.call(c, n) && (e[n] = c[n]);
    14.         p && p(r);
    15.         while(s.length) s.shift()();
    16.         return u.push.apply(u, l || []), t()
    17.     }
    18.     function t() {
    19.         for(var e, r = 0; r < u.length; r++) {
    20.             for(var t = u[r], n = !0, a = 1; a < t.length; a++) {
    21.                 var c = t[a];
    22.                 0 !== o[c] && (= !1)
    23.             }
    24.             n && (u.splice(r--, 1), e = i(i.= t[0]))
    25.         }
    26.         return e
    27.     }
    28.     var n = {},
    29.         o = {
    30.             aaa: 0
    31.         },
    32.         u = [];
    33.     function a(e) {
    34.         return i.+ "js/" + ({
    35.             about: "about"
    36.         }[e] || e) + "." + {
    37.             about: "b55882bc"
    38.         }[e] + ".js"
    39.     }
    40.     function i(r) {
    41.         if(n[r]) return n[r].exports;
    42.         var t = n[r] = {
    43.             i: r,
    44.             l: !1,
    45.             exports: {}
    46.         };
    47.         return e[r].call(t.exports, t, t.exports, i), t.= !0, t.exports
    48.     }
    49.     i.= function(e) {
    50.         var r = [],
    51.             t = o[e];
    52.         if(0 !== t)
    53.             if(t) r.push(t[2]);
    54.             else {
    55.                 var n = new Promise((function(r, n) {
    56.         t = o[e] = [r, n]
    57.                 }));
    58.                 r.push(t[2] = n);
    59.                 var u, c = document.createElement("script");
    60.                 c.charset = "utf-8", c.timeout = 120, i.nc && c.setAttribute("nonce", i.nc), c.src = a(e);
    61.                 var l = new Error;
    62.                 u = function(r) {
    63.         c.onerror = c.onload = null, clearTimeout(f);
    64.         var t = o[e];
    65.         if(0 !== t) {
    66.             if(t) {
    67.                 var n = r && ("load" === r.type ? "missing" : r.type),
    68.                     u = r && r.target && r.target.src;
    69.                 l.message = "Loading chunk " + e + " failed.\n(" + n + ": " + u + ")", l.name = "ChunkLoadError", l.type = n, l.request = u, t[1](l)
    70.             }
    71.             o[e] = void 0
    72.         }
    73.                 };
    74.                 var f = setTimeout((function() {
    75.         u({
    76.             type: "timeout",
    77.             target: c
    78.         })
    79.                 }), 12e4);
    80.                 c.onerror = c.onload = u, document.head.appendChild(c)
    81.             }
    82.         return Promise.all(r)
    83.     }, i.= e, i.= n, i.= function(e, r, t) {
    84.         i.o(e, r) || Object.defineProperty(e, r, {
    85.             enumerable: !0,
    86.             get: t
    87.         })
    88.     }, i.= function(e) {
    89.         "undefined" !== typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, {
    90.             value: "Module"
    91.         }), Object.defineProperty(e, "__esModule", {
    92.             value: !0
    93.         })
    94.     }, i.= function(e, r) {
    95.         if(1 & r && (= i(e)), 8 & r) return e;
    96.         if(4 & r && "object" === typeof e && e && e.__esModule) return e;
    97.         var t = Object.create(null);
    98.         if(i.r(t), Object.defineProperty(t, "default", {
    99.                 enumerable: !0,
    100.                 value: e
    101.             }), 2 & r && "string" != typeof e)
    102.             for(var n in e) i.d(t, n, function(r) {
    103.                 return e[r]
    104.             }.bind(null, n));
    105.         return t
    106.     }, i.= function(e) {
    107.         var r = e && e.__esModule ? function() {
    108.             return e["default"]
    109.         } : function() {
    110.             return e
    111.         };
    112.         return i.d(r, "a", r), r
    113.     }, i.= function(e, r) {
    114.         return Object.prototype.hasOwnProperty.call(e, r)
    115.     }, i.= "/", i.oe = function(e) {
    116.         throw console.error(e), e
    117.     };
    118.     var c = window["webpackJsonp"] = window["webpackJsonp"] || [],
    119.         l = c.push.bind(c);
    120.     c.push = r, c = c.slice();
    121.     for(var f = 0; f < c.length; f++) r(c[f]);
    122.     var p = l;
    123.     t()
    124.             })([]);
    125.             //# sourceMappingURL=/js/aaa.d6f2d2a1.js.map
    126.         </script>
    127.         <script type="text/javascript" src="/js/chunk-vendors.13cf26cb.js"></script>
    128.         <script type="text/javascript" src="/js/app.fb7ad43f.js"></script>
    129.     </body>
    130. </html>

    ManifestPlugin

    上面那种是通过webpack打包工具直接打包到index.html,还有一种更适合后端的,我们可以将打包的后的文件生成一个清单,重新设置vue.config.js:

    1. const ManifestPlugin = require('webpack-manifest-plugin');
    2. configureWebpack: {
    3.     optimization: {
    4.         runtimeChunk:{
    5.             name:()=>'aaa'
    6.         },
    7.     },
    8.     plugins: [
    9.             new ManifestPlugin()
    10.     ]
    11. }

    打包,我们得到了manifest.json:

    1. {
    2.   "aaa.js": "/js/aaa.a9193722.js",
    3.   "aaa.js.map": "/js/aaa.a9193722.js.map",
    4.   "about.js": "/js/about.eeb8a4cc.js",
    5.   "about.js.map": "/js/about.eeb8a4cc.js.map",
    6.   "app.css": "/css/app.7edf2138.css",
    7.   "app.js": "/js/app.b5ae3d68.js",
    8.   "app.css.map": "/css/app.7edf2138.css.map",
    9.   "app.js.map": "/js/app.b5ae3d68.js.map",
    10.   "chunk-vendors.js": "/js/chunk-vendors.13cf26cb.js",
    11.   "chunk-vendors.js.map": "/js/chunk-vendors.13cf26cb.js.map",
    12.   "favicon.ico": "/favicon.ico",
    13.   "img/logo.png": "/img/logo.82b9c7a5.png",
    14.   "index.html": "/index.html"
    15. }

    manifest.json文件目录如下:

    有了这份清单,我们就可以得到文件的真实名称了(含hash),下面代码可以参考,如何在服务端得到文件内容,并渲染到index.html:

    1. // server.js
    2. const fs = require('fs');
    3. const manifest = require('./manifest.json');
    4. const runtimeContent = fs.readFileSync(manifest['runtime~main.js'], 'utf-8');
    5. app.get('/', (req, res) => {
    6.   res.send(`
    7.     …
    8.     <script>${runtimeContent}</script>
    9.     …
    10.   `);
    11. });
    回到顶部
    我要评论

    所有评论

      相关文章