webpack打包首頁優化及路由懶加載

前言

最近作了一個小型的vue的h5項目,發如今手機上運行的時候,第一次進去的首頁比較慢,而後同事提了下能夠在生產環境用cdn,因而我嘗試了下javascript

生產環境開啓cdn

一、 在vue.congfig.js裏面加入css

const isProduction = process.env.NODE_ENV == "production";
 configureWebpack: (config) => {
    if (isProduction) {
      config.externals = {
        vue: "Vue",
        "vue-router": "VueRouter",
        vant: "vant",
        _: "lodash",
      };
複製代碼

externals是讓裏面的庫不被webapck打包,也不影響經過import(或者其餘AMD、CMD等)方式引入html

二、 在index.html引入cdn資源前端

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vant@2.8/lib/index.css" />
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
  <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/vant@2.8/lib/vant.min.js"></script>
  <script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.15/lodash.core.min.js"></script> 
複製代碼

三、 優化下寫法vue

// vue.config.js

const cdn = {
  css: ["https://cdn.jsdelivr.net/npm/vant@2.8/lib/index.css"],
  js: [
    "https://cdn.jsdelivr.net/npm/vue@2.6.11",
    "https://unpkg.com/vue-router/dist/vue-router.js",
    "https://cdn.jsdelivr.net/npm/vant@2.8/lib/vant.min.js",
    "https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.15/lodash.core.min.js",
  ],
};


chainWebpack: (config) => {
    if (isProduction) {
      config.plugin("html").tap((args) => {
        args[0].cdn = cdn;
        return args;
      });
    }
  }
 
 // index.html
   <% for(var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css){%>
  <link src="<%= htmlWebpackPlugin.options.cdn.css[i] %>"></link>
  <%}%>
  <% for(var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js){%>
  <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
  <%}%>
複製代碼

優化前 java

優化後

開啓gzip壓縮

cnpm install compression-webpack-plugin --save-dev 

// vue.config.js
const CompressionPlugin = require("compression-webpack-plugin");

 configureWebpack: (config) => {
    if (isProduction) {
      config.externals = {
        vue: "Vue",
        "vue-router": "VueRouter",
        vant: "vant",
        _: "lodash",
      };
      config.plugins.push(
        new CompressionPlugin({
          algorithm: "gzip",
        })
      );
    }
  },
複製代碼

路由懶加載

{
    path: "/index",
    name: "index",
    component: () => import("../views/index.vue"),
    meta: {
      keepAlive: false,
    },
  },
複製代碼

日常當中常常這麼寫,只不過你可能不知道這就是路由懶加載。官網,官網上提到這是因爲異步組件和weback的代碼分割code-splitting功能,每一個異步路由會打包成不一樣的塊,實現按需加載。除了上面的ES2015模塊的寫法,它還有node

{
    path: "/index",
    name: "index",
    component: (resolve) => require(["../views/index.vue"], resolve),
    meta: {
      keepAlive: false,
    },
  },
複製代碼

根據官網提到的,首先建立一個返回Promise的工廠函數webpack

const Index = () => Promise.resolve({ /* 組件定義對象 */ })
複製代碼

而後用動態 import語法定義代碼分塊的分割點git

import ('./Index')
複製代碼

二者結合,就能夠自動分割代碼github

const Index = () => import('../views/index.vue')
複製代碼

先看了下這個code-split

而後去看了下vue-cli的具體配置,路由已是Dynamic Import,如上圖第二點提到. 下面說說針對於chunk-vendors的分割,正如上圖第三點提到,配置splitChunks是了重複數據刪除和分割chunks

optimization(開發和生產都是同樣的)

optimization:{
      splitChunks: {
        cacheGroups: {  // 緩存組,能夠定義多個
          vendors: {     //建立一個 自定義的vendor的chunk
            name: "chunk-vendors",
            test: /[\\\/]node_modules[\\\/]/,  // 匹配node_modules
            priority: -10,  // 理解爲緩存的級別
            chunks: "initial",
        },
          common: {
            name: "chunk-common",
            minChunks: 2,  // 分割以前必須共享模塊的最小chunk數
            priority: -20,
            chunks: "initial",
            reuseExistingChunk: true,  // 是否複用存在的塊
        },
      },
    } 
}
 
複製代碼
  • cacheGroups 緩存組,能夠定義多個
cacheGroups: {
        defaultVendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
複製代碼
  • priority 緩存組的級別

A module can belong to multiple cache groups. The optimization will prefer the cache group with a higher priority. The default groups have a negative priority to allow custom groups to take higher priority (default value is 0 for custom groups)

翻譯過來大概就是一個模塊能夠有多個cash groups,optimization將會選擇優先級更高的cash group, default group 的優先級爲負數,能夠容許custom group有更高的優先級(默認值是0)。 簡而言之,custom group能夠經過priority比default group

  • reuseExistingChunk 是否複用存在的塊

output配置有些不一樣

// 生產
  output: {
    path:"/dist",
    filename: "static/js/[name].[contenthash:8].js",
    publicPath: "/",
    chunkFilename: "static/js/[name].[contenthash:8].js",  // 生成一個8位的hash值
  }
  
 // 開發
   output: {
    path:"/dist",
    filename: "static/js/[name].js",
    publicPath: "/",
    chunkFilename: "static/js/[name].js",
  }
複製代碼

運行打包

生產輸出了css,而開發環境沒有,估計是生產配置了這句

// 生產
    new MiniCssExtractPlugin({
      filename: "static/css/[name].[contenthash:8].css",
      chunkFilename: "static/css/[name].[contenthash:8].css",
    })
複製代碼

那麼問題來了

  • 開發模式打包出來文件的css到底怎麼引入的
  • 打包出來的dist的index.html的link和script標籤引入的文件爲什麼不一樣
  • preload 和 prefetch的區別
// development
<!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.0">
  <link rel="icon" href="/favicon.ico">
  <title>南藍</title>
 
  <link href="/static/js/0.js" rel="prefetch"><link href="/static/js/1.js" rel="prefetch"><link href="/static/js/2.js" rel="prefetch">
  <link href="/static/js/3.js" rel="prefetch">
  <link href="/static/js/app.js" rel="preload" as="script">
  <link href="/static/js/chunk-vendors.js" rel="preload" as="script">
</head>
<body>
  <noscript>
    <strong>We're sorry but f2e-client doesn't work properly without JavaScript enabled.
      Please enable it to continue.</strong>
  </noscript>
  <div id="app"></div>
<script type="text/javascript" src="/static/js/chunk-vendors.js"></script><script type="text/javascript" src="/static/js/app.js"></script></body>

</html>
複製代碼

再來看看生產打包出來的index.html(production)

// production
<!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>鴨嘴獸</title>
   <script src=https://cdn.jsdelivr.net/npm/vant@2.8/lib/index.css></script>
   <script src=https://cdn.jsdelivr.net/npm/vue@2.6.11></script>
   <script src=https://unpkg.com/vue-router/dist/vue-router.js></script>
   <script src=https://cdn.jsdelivr.net/npm/vant@2.8/lib/vant.min.js></script>
   <script src=https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.15/lodash.core.min.js></script>
   <link href=/static/css/chunk-0c3564fc.b3594289.css rel=prefetch>
   <link href=/static/css/chunk-56255d30.c1e34d24.css rel=prefetch>
   <link href=/static/css/chunk-5ba5813d.a56f098f.css rel=prefetch>
   <link href=/static/css/chunk-9945b478.66fcd057.css rel=prefetch>
   <link href=/static/js/chunk-0c3564fc.9d02dfcc.js rel=prefetch>
   <link href=/static/js/chunk-56255d30.d0115acd.js rel=prefetch>
   <link href=/static/js/chunk-5ba5813d.10f75234.js rel=prefetch>
   <link href=/static/js/chunk-9945b478.dc8a4502.js rel=prefetch>
   <link href=/static/css/app.faa29057.css rel=preload as=style>
   <link href=/static/css/chunk-vendors.97c56160.css rel=preload as=style>
   <link href=/static/js/app.5deb2d45.js rel=preload as=script>
   <link href=/static/js/chunk-vendors.158e0179.js rel=preload as=script>
   <link href=/static/css/chunk-vendors.97c56160.css rel=stylesheet>
   <link href=/static/css/app.faa29057.css rel=stylesheet>
</head>

<body>
<noscript><strong>We're sorry but f2e-client doesn't work properly without JavaScript enabled. Please enable it to
           continue.</strong></noscript>
   <div id=app></div>
   <script src=/static/js/chunk-vendors.158e0179.js></script>
   <script src=/static/js/app.5deb2d45.js></script>
</body>

</html>
複製代碼
  • 爲啥有些js用link標籤引入,有些用scipt標籤引入
  • link的as屬性爲啥有時有時無

彈出vue-cli配置webpack設置

開發換環境 npx vue-cli-service inspect --mode development  webpack.config.development.js
生產環境:npx vue-cli-service inspect --mode production  webpack.config.production.js
複製代碼

無論前端輪子怎麼變化,萬變不離其宗,這個宗指的就是htmlcssjs,全部要回歸本質上去,我提出的那些問題,但願下次出篇文章弄懂它,有錯誤或者有建議能夠提出來

相關文章
相關標籤/搜索