中高級前端須要瞭解的vue-cli優化技巧

1、前言

閱讀完該文章大概須要2.5min。html

  • 讀完該篇文章你能學到前端

    1. vue-cli默認作了哪些優化?
    2. 在cli的基礎上咱們又能作哪些優化?
    3. vue.config.js中如何配置一些經常使用的pluginloader
  • vue-cli的出現,讓咱們省掉了配置webpack的時間。也就是說,一個不懂webpack的人,也能直接上手開發。好比file-loader, url-loader會提早爲咱們配置好。vue

  • 性能方面vue-cli也默認儘量多的幫咱們作了優化,好比cache-loader會在項目中預先作了配置。咱們能夠在控制檯輸入vue inspect > webpack.config.js,便可在webpack.config.js文件中查看cli預先定義好的基礎配置。咱們今天就在vue-cli搭建好的項目基礎上聊一聊可優化的點。node

2、項目源碼

本文所用到的項目源碼jquery

3、量化指標

1. build時間

speed-measure-webpack-plugin插件能夠在build的時候看到webpack的loader和plugin所用的時間,配置很是簡單。以下:

// vue.config.js
module.exports = {
chainWebpackconfig => {
   config.plugin('speed')
   .use(SpeedMeasureWebpackPlugin)
 }
}
複製代碼

順便看一下效果

屏幕快照 2021-07-31 下午4.57.58.png

2.build後包的大小以及包的多少

webpack-bundle-analyzer插件能夠幫咱們可視化的展現build時的每一個包的大小以及依賴。vue-cli也幫咱們作了默認的配置,我只須要在build的後面加一個參數--report便可。

// package.json
{
  "name""dll-vue",
  "version""0.1.0",
  "private"true,
  "scripts": {
    "serve""vue-cli-service serve",
    "build""vue-cli-service build",
    "report""vue-cli-service build --report",
  }
}
複製代碼

npm run report 以後,dist目錄下就多了一個report.html文件,咱們用瀏覽器打開這個文件看一下,右上角那個小藍塊是咱們的vue代碼,接下來咱們主要來優化小藍塊以外的代碼

屏幕快照 2021-07-31 下午9.51.03.png

4、開始優化

1. include/exclude

咱們一般配置include和exclude,來達到使loader僅僅處理匹配到的文件,像這樣webpack

// webpack.config.js
module.exports = {
  module: { 
      rules: [ 
          { 
              test: /\.js[x]?$/, 
              use: ['babel-loader'], 
              include: [path.resolve(__dirname, 'src')] 
          }
         ] 
  },
}
複製代碼

而vue的transpileDependencies屬性默認狀況下 babel-loader 會忽略全部 node_modules 中的文件,其實已經知足了咱們大部分需求。git

2. resolve

resolve: 配置 webpack如何尋找模塊所對應的文件,好比import * from 'xxx',xxx模塊應該優先從node_modules中找,咱們經過vue inspect > webpack.config.js導出的文件中在modules字段中能夠清晰的看到已經將node_modules設置爲優先尋找的模塊

resolve: {
    // ...
    modules: [
      'node_modules',
      ...
    ]
    // ...
 }
複製代碼

3. happypack-plugin/thread-loader

通常來講,咱們能夠經過happack-plugin或者thread-loader開啓多線程打包。vue-cli的parallel屬性的含義是:是否爲 Babel 或 TypeScript 使用 thread-loader,默認值爲cpu的內核數,也就是說若是你係統是3核cpu,則build的時候,會自動在babel-loader和ts-loader執行時候開啓3個線程。若是你想試着本身的配置一下,能夠像下面這樣。(不過我試着本身配置了以後,彷佛沒什麼效果。也許是我配置的不對,歡迎你們來指正)

config.module.rule('vue')
          .use('thread-loader')
          .loader('thread-loader')
          .before('vue-loader')
複製代碼

4. noParse

若是一些第三方模塊沒有AMD/CommonJS規範版本,可使用 noParse 來標識這個模塊,這樣 Webpack 會引入這些模塊,可是不進行轉化和解析,從而提高 Webpack 的構建性能 ,例如:jquery 、lodash,vue.config.js中能夠這樣配置:

// vue.config.js
module.exports = {
   //...
   configureWebpack:{
    module: {
      noParse: /^(lodash|moment)$/
    }
  }
  //...
}
複製代碼

5. ContextReplacementPlugin

一些依賴,咱們也許只是用到了一部分,不必所有解析,好比moment中的語言包,咱們通常只用中文包就夠了,因此能夠這樣配置:

// vue.config.js
module.exports = {
   //...
   configureWebpack:{
       plugins: [
           new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /zh-cn/)
       ]
  }
  //...
}
複製代碼

咱們經過一張圖片來體驗一下, 左邊爲去掉語言包的效果

moment.png

6. externals

通常來講像jQuery這些第三方的包,咱們採用CDN的方式來引入,像這樣

<-- public/index.html -->
<script src="https://code.jquery.com/jquery-3.6.0.min.> js"></script> 複製代碼

在使用的時候,咱們但願經過import的方式引入,像這樣

// App.vue\
import $ from 'jquery'
$('.today').text = 'today'
複製代碼

這就形成一個問題,build的時候就會將jquery再打包一次 咱們能夠配置externals來達到build時忽略掉指定的依賴

// vue.config.js
module.exports = {
   //...
   configureWebpack:{
    config.externals = {
      jquery: 'jQuery'
    }
  }
  //...
}
複製代碼

7. uglifyjs-webpack-plugin

在build的時候能夠壓縮代碼的大小,有幾個經常使用的配置能夠單獨提一下,好比去掉console.log,好比進行多進程壓縮。能夠這樣:

// vue.config.js
module.exports = {
   //...
   configureWebpack:{
    config.optimization.minimizer = [
      new UglifyJsPlugin({
       uglifyOptions: {
        compress: {
         drop_console: true, // 去掉console
        }
        parallel: true, //默認併發運行數:os.cpus().length - 1
       }
      })
     ]
  }
  //...
}
複製代碼

8. compression-webpack-plugin

咱們能夠將代碼壓縮爲.gz文件,瀏覽器也是能夠識別的。能夠這樣配置

//vue.config.js
module.exports = {
   //...
   configureWebpack:{
    plugins: [
        new CompressionWebpackPlugin()
    ]
  }
  //...
}
複製代碼

9. DllPlugin 和 DllReferencePlugin

  • 對於變化概率很小的一些第三方包,其實不必build的時候都要打包一次, 能夠把這些第三方包單獨抽離出來,提早打包好。
  • webpack自己是要體現出模塊間的依賴關係,當咱們將一些包抽離出來後,維護以前的依賴關係就須要manifest.json這個文件。讓咱們從接下來的實戰中來學習它。

<1> 新建一個配置文件webpack.dll.config.js

// webpack.dll.config.js
module.exports = {
  mode'production',
  entry: {
    vue_vendor: ['vue/dist/vue.runtime.esm.js''vuex',  'vue-router''element-ui'],
    other_vendor: ['lodash''moment']
  },
  output: {
    filename'[name].dll.js',
    path: path.resolve(__dirname, './public/dll'),
    library'[name]_[hash]'
  },\
  plugins: [
    new webpack.DllPlugin({
      name'[name]_[hash]',
      path: path.resolve(__dirname, '[name].manifest.json')
    })
  ]
}
複製代碼

<2> 爲了方便,咱們將讀取該配置文件的命令寫到package.json文件中,像這樣。(須要安裝webpack-cli)

// package.json
{
  .....
  "scripts": {
    .....
    "dll""webpack --config ./webpack.dll.config.js"
  }
  .....
}
複製代碼

<3> 執行npm run dll後能夠看到生成兩個manifest文件,像這樣

屏幕快照 2021-08-02 下午8.06.25.png

<4> 修改vue.config.js,引入依賴文件,並自動將dll下的文件插入到index.html中(這裏咱們引入一個插件add-asset-html-webpack-plugin

module.exports = {
  chainWebpackconfig => {
    // 多個manifest.json文件就須要寫屢次
    config.plugin('vendorDll1')
    .use(webpack.DllReferencePlugin, [
      {
        context: __dirname,
        manifestrequire('./public/manifest/other_vendor.manifest.json')
      }
    ])

    config.plugin('vendorDll2')
    .use(webpack.DllReferencePlugin, [
      {
        context: __dirname,
        manifestrequire('./public/manifest/vue_vendor.manifest.json')
      }
    ])

    // 將dll下的文件自動插入到index.html中
    config.plugin('asset')
    .use(AddAssetHtmlWebpackPlugin, [
      [
        {
          filepath: path.resolve(__dirname, 'public/dll/vue_vendor.dll.js'),
          outputPath'dll',
          publicPath'/dll'
        },
        {
          filepath: path.resolve(__dirname, 'public/dll/other_vendor.dll.js'),
          outputPath'dll',
          publicPath'/dll'
        }
      ]
    ])
  }
}
複製代碼

10. optimization.splitChunks

抽離公共代碼,經過配置splitChunks可抽離公共的代碼,防止重複,我沒有在本身的項目中用,

//vue.config.js
module.exports = {
   //...
   chainWebpack: config => {
      config.optimization.splitChunks({
          chunks: 'all',
          cacheGroups: {}
      })
   }
  //...
}
複製代碼

5、效果展現

section1.png

section2.png

all.png

6、補充幾個不須要配置的優化點

1. extensions

當咱們導入模塊時,假如沒有指定後綴,指望優先匹配的文件格式,咱們直接看vue-cli默認的配置extensions: ['.mjs', '.js', '.jsx', '.vue', '.json', '.wasm']

2. tree-shaking

咱們經過import方式引入,webpack會自動移除掉沒有用到的模塊代碼

3. Scope hosting

做用域提高:好比

let a = 1
let b = 2
let c = a + b

// webpack自動優化爲
c = 3
複製代碼

4. 路由懶加載

經過() => import('xxx')方式引入,可達到路由懶加載的效果

6、總結

  • 該文章爲最近優化團隊項目webpack打包速度,作的總結。github

  • 若是有不對的地方歡迎你們在討論區糾正web

  • 歡迎關注公衆號:前端小卡vue-router

  • 若是以爲有用,歡迎點個贊啦

相關文章
相關標籤/搜索