基於Webpack4的Vue移動端開發環境-優化篇

序言

本文章上接搭建篇,由於篇幅緣由,我把優化單獨放一篇文章來說。css

基於Webpack4的Vue移動端開發環境-搭建篇html

代碼我都上傳到了github,有須要的自取。Webpack-Vue-Mobilevue

大佬繞路輕噴node

不少時候作開發都會使用UI組件庫,這些組件庫通常都會有按需加載的功能,這裏我選擇vant組件庫來測試。手頭暫時沒有能夠演示的項目,可能有點純理論感受,可是應該能你們一個優化的思路。我會在測試項目裏面寫一些測試頁面,到時上傳到github供你們參考!webpack

  • 注意: 通過我前面的一些實踐,這兒有事情須要告知ios

    • 一、若是開發環境和生產環境都使用插件把CSS分離出來成爲單獨的文件,那麼你在開發過程當中會發現熱更新對CSS不生效,因此解決方法就是分離CSS僅配置在生產環境。給你們埋了個坑!

開始

一、組件庫按需加載

安裝vantgit

npm install vant
複製代碼

安裝完畢後,咱們先使用官網的全局導入全部組件github

  • 全局導入全部組件
import Vant from 'vant';
import 'vant/lib/index.css';

Vue.use(Vant);
複製代碼

而後你到頁面使用幾個組件,好比Button,Dialog這些,運行npm run dev命令,這時發現報錯了,說Module parse failed: Unexpected character '@',這是由於咱們引入vant時,引入了css文件,可是咱們的webpack並無配置處理css的loader,因此加上便可:web

{
  test: /\.css$/,
  // 這兒組件庫的css通常都是處理過的,咱們使用通常的loader便可
  use: [
    {
      loader: 'style-loader',
    },
    {
      loader: 'css-loader',
    }
  ]
}
複製代碼

這樣咱們就能運行並加入相關組件了,這裏咱們不演示組件使用,而是直接打包展現結果分析圖:正則表達式

1.png

咱們能夠看見那個碩大的index.css,也就是說你沒用到的組件它也把樣式這些都弄進來了。

  • 按需加載 使用按需加載須要使用到一個插件叫babel-plugin-import。
npm install babel-plugin-import -D
複製代碼

安裝完畢後在babel.config.js裏面配置:

// 按需加載vant組件
plugins: [
  ["import", {
    libraryName: 'vant',
    libraryDirectory: 'es',
    style: true
  }, 'vant']
]
複製代碼

這樣你在main.js裏面這樣引入便可:

// 按需註冊vant組件
import { Button } from 'vant';
Vue.use(Button);
複製代碼

你使用了什麼組件就註冊什麼組件,目前社區上的許多ui組件庫都是支持按需加載的,有的話必定要使用這種方式。

2.png

這下看下,比剛纔所有引入好多了,額。。main.js碩大應該是未分離全部東西打包到一塊兒的緣由-_-!。

二、路由懶加載

使用路由懶加載,在頁面訪問到是再加載對應的資源,提高首頁訪問的速度。 在這以前,咱們還須要一個babel插件來實現這個功能

npm install @babel/plugin-syntax-dynamic-import -D
複製代碼

安裝完畢後,在webpack裏面babel-loader配置加上如下代碼:

{
  test: /\.jsx?$/,
  exclude: /node_modules/,
  use: [
    {
      loader: 'babel-loader',
      options: {
        // 使用vue官方的懶加載語法並結合babel需使用這個插件,否則會報錯
        plugins: ["@babel/plugin-syntax-dynamic-import"]
      }
    }	
  ]
}
複製代碼

而後咱們現有的路由裏面引入組件的寫法須要改變下,好比你如今是這麼寫的:

import Home from '../views/Home.vue';
import RouterTest from '../views/RouterTest.vue';
import VantTest from '../views/VantTest.vue';
複製代碼

改爲下面的寫法:

//官方的懶加載方案,須要在webpack.config.js中配置@babel/plugin-syntax-dynamic-import這個插件,不然babel不支持如下語法會報錯。
//下面的註釋語法是打包生成的js的文件名,若是你想某幾個組件打包到同一個文件,那麼它們的註釋語法的webpackChunkName的名字相同便可
const MainPage = () =>
  import(/* webpackChunkName: "group-foo" */ "./views/MainPage.vue");
const ComOne = () =>
  import(/* webpackChunkName: "group-foo" */ "./views/ComOne.vue");
const ComTwo = () =>
  import(/* webpackChunkName: "group-foo" */ "./views/ComTwo.vue");
複製代碼

這樣處理後你會發現你在切換路由時會加載額外的js文件,這樣咱們就分離了出來按需加載,打包分析圖以下:

3.png

這裏能夠發現一個問題,咱們不少包都重複打了,接下來就是去除重複打包。因此咱們要提取公共代碼。

三、提取公共代碼

在webpack3的時候,咱們能夠藉助CommonsChunkPlugin來實現,webpack4已經移除了這個插件,在webpack4中能夠用splitChunks。

若是你在使用webpack4的時候沒有作optimization.splitChunks的配置,那麼它會有一個默認配置,官方文檔的代碼塊:

module.exports = {
  ...
  optimization: {
    splitChunks: {
      chunks: 'async',
      minSize: 30000,
      maxSize: 0,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      automaticNameDelimiter: '~',
      name: true,
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  }
  ...
}
複製代碼

大多數狀況咱們須要本身配置cashGroups這個參數,也就是自定義拆分組,這裏我參考了社區大佬的配置,而後優化了下:

optimization: {
  splitChunks: {
    cacheGroups: {
      // node_modules下的模塊拆分到chunk-vendors.xxxx.js下
      vendors: {
        name: 'chunk-vendors',
        test: /[\\\/]node_modules[\\\/]/,
        priority: -10,
        chunks: 'all'
      },
      // 本身定義的公告組件超過兩次引用的放在chunk-common.xxxx.js下
      common: {
        name: 'chunk-common',
        minChunks: 2,
        priority: -20,
        chunks: 'all',
        reuseExistingChunk: true
      }
    }
  }
}
複製代碼

一開始,chunks的屬性值都是initial,而後咱們看一下打包分析圖:

4.png

能夠看到分離的js文件都打包了一次core.js文件,因此我把chunks參數值改成all,再來看分析圖:

5.png

這樣,就沒有重複打包了。

四、補充splitChunks相關知識

在翻閱了社區上的一些文章後(官方文檔對於我這個菜雞來講看不出來什麼-_-),在此仍是作一個總結。

4.一、參數解釋

  • chunks 有all、async和initial三個值,async表示只從異步加載得模塊(動態加載import())裏面進行拆分 initial表示只從入口模塊進行拆分 all表示以上二者都包括。

  • automaticNameDelimiter 打包拆分出來文件名的鏈接符,通常都是~。

  • maxAsyncRequests 按需加載時的最大並行請求數。

  • maxInitialRequests 入口並行加載的最大請求數。

  • minChunks 當應用次數超過多少次時會打包到單獨的塊,通常都是2。

  • minSize 生成塊的最小大小(以字節爲單位)。

  • maxSize 這個有點複雜,暫時說不清。#手動捂臉

  • name 分割的塊名。

  • cashGroups 緩存組,這個能夠本身來指定你的拆分規則,同時它的參數跟上面同樣,聲明瞭的話就是覆蓋,不然就是繼承,同時它還有幾個獨有的選項

    • test 匹配規則,通常使用正則表達式。
    • priority 權值,默認的優先權值爲0,你能夠設置負值來比默認的權限高。
    • reuseExistingChunk 若是當前塊包含已經從主包中分離出來的模塊,那麼它將被重用,而不是生成一個新的塊。

這裏有幾篇文章供你們參考: 連接1 連接2 連接3

4.2 結合runtimeChunk選項

關於這個參數的做用,我引用思否大佬的一個回答:

優化持久化緩存的, runtime 指的是 webpack 的運行環境(具體做用就是模塊解析, 加載) 和 模塊信息清單, 模塊信息清單在每次有模塊變動(hash 變動)時都會變動, 因此咱們想把這部分代碼單獨打包出來, 配合後端緩存策略, 這樣就不會由於某個模塊的變動致使包含模塊信息的模塊(一般會被包含在最後一個 bundle 中)緩存失效。optimization.runtimeChunk 就是告訴 webpack 是否要把這部分單獨打包出來。連接

就是說呢那些不會常常變的runtime把它單獨提出來,不須要頻繁的產生變化,用來優化後端的緩存策略。

那麼在webpack的配置文件加上這句:

optimization: {
  runtimeChunk: true,
  splitChunks: {
    ......
  }
}
複製代碼

設置好後,咱們打包出來試一試看相比於上面的配置會有哪些區別:

6.png

這下你發現main.js進一步減少了,把裏面的部份內容放到了runtime~main下面。

五、其它優化方法

若是還想進一步減少包的體積,除了你的圖片媒體資源這些使用oss外。你的第三方庫也可使用cdn分發網絡,好比個人公司項目的axios,vue,better-scroll這些都使用了cdn分發的方式,而不是直接導入到包裏面一塊兒打包。 在你的index.html入口頁面下以這種方式加入

<script src="https://static.XXXXXX.com/12static/new/js/vue.min.js"></script>
<script src="https://static.XXXXXX.com/12static/new/js/vue-router.js"></script>
<script src="https://static.XXXXXX.com/12static/new/js/axios.min.js"></script>
<script src="https://static.XXXXXX.com/12static/new/js/bscroll.min.js"></script>
複製代碼

這裏給你們推薦一個開源的第三方cdn分發網絡:BootCDN

最後

暫時到這裏總結就結束了,可是優化的腳步不會停,我這兒的優化都是比較基本的優化,確定還有許多點沒有總結到,後期如有使用到的好的優化方法,會持續更新,若文章有錯誤,還請多多指正!

相關文章
相關標籤/搜索