【原創】webpack如何優化vue項目

前言javascript

平常開發中,Vue框架一般都會使用Webpack進行構建,隨着項目不斷迭代,項目逐漸變得龐大,然而項目的構建速度隨之變得緩慢,因而對Webpack構建進行優化變得刻不容緩。經過適當的方法優化後,項目的構建速度提升了50%。現將相關優化方法進行總結分享。css

一.優化loader配置html

因爲Loader對文件的轉換操做很耗時,因此須要讓儘量少的文件被Loader處理。咱們能夠經過如下3方面優化Loader配置:(1)優化正則匹配(2)經過cacheDirectory選項開啓緩存(3)經過include、exclude來減小被處理的文件。實踐以下:前端

項目原配置:vue

{
  test: /\.js$/,
  loader: 'babel-loader',
  include: [resolve('src'), resolve('test')]
},複製代碼

優化後配置:
java

{
  // 1、若是項目源碼中只有js文件,就不要寫成/\.jsx?$/,以提高正則表達式的性能
  test: /\.js$/,
  // 2、babel-loader支持緩存轉換出的結果,經過cacheDirectory選項開啓
  loader: 'babel-loader?cacheDirectory',
  // 3、只對項目根目錄下的src 目錄中的文件採用 babel-loader
  include: [resolve('src')]
},複製代碼

二.優化UglifyJS插件node

webpack默認提供了UglifyJS插件來壓縮JS代碼,可是它使用的是單線程壓縮代碼,也就是說多個js文件須要被壓縮,它須要一個個文件進行壓縮。因此說在正式環境打包壓縮代碼速度很是慢(由於壓縮JS代碼須要先把代碼解析成用Object抽象表示的AST語法樹,再去應用各類規則分析和處理AST,致使這個過程耗時很是大)。webpack

所以咱們須要能夠並行處理多個子任務,多個子任務完成後,再將結果發到主進程中,有了這個思想後,所以 ParallelUglifyPlugin 插件就產生了,當webpack有多個JS文件須要輸出和壓縮時候,原來會使用UglifyJS去一個個壓縮而且輸出,可是ParallelUglifyPlugin插件則會開啓多個子進程,把對多個文件壓縮的工做分別給多個子進程去完成,可是每一個子進程仍是經過UglifyJS去壓縮代碼。無非就是變成了並行處理該壓縮了,並行處理多個子任務,效率會更加的提升。ios

安裝 webpack-parallel-uglify-plugin 插件web

而後在webpack.config.js 配置代碼以下:

// 引入 ParallelUglifyPlugin 插件const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');​module.exports = {  plugins: [    // 使用 ParallelUglifyPlugin 並行壓縮輸出JS代碼    new ParallelUglifyPlugin({      // 傳遞給 UglifyJS的參數以下:      uglifyJS: {        output: {          /*           是否輸出可讀性較強的代碼,即會保留空格和製表符,默認爲輸出,爲了達到更好的壓縮效果,           能夠設置爲false          */          beautify: false,          /*           是否保留代碼中的註釋,默認爲保留,爲了達到更好的壓縮效果,能夠設置爲false          */          comments: false        },        compress: {          /*           是否在UglifyJS刪除沒有用到的代碼時輸出警告信息,默認爲輸出,能夠設置爲false關閉這些做用           不大的警告          */          warnings: false,          /*           是否刪除代碼中全部的console語句,默認爲不刪除,開啓後,會刪除全部的console語句          */          drop_console: true,          /*           是否內嵌雖然已經定義了,可是隻用到一次的變量,好比將 var x = 1; y = x, 轉換成 y = 5, 默認爲不           轉換,爲了達到更好的壓縮效果,能夠設置爲false          */          collapse_vars: true,          /*           是否提取出現了屢次可是沒有定義成變量去引用的靜態值,好比將 x = 'xxx'; y = 'xxx'  轉換成           var a = 'xxxx'; x = a; y = a; 默認爲不轉換,爲了達到更好的壓縮效果,能夠設置爲false          */          reduce_vars: true        }      }    }),  ]}複製代碼

打包對比基本上大小能相差30%!!!!

三.減小冗餘代碼

babel-plugin-transform-runtime 是Babel官方提供的一個插件,做用是減小冗餘的代碼 。 Babel在將ES6代碼轉換成ES5代碼時,一般須要一些由ES5編寫的輔助函數來完成新語法的實現,例如在轉換 class extent 語法時會在轉換後的 ES5 代碼裏注入 extent 輔助函數用於實現繼承。babel-plugin-transform-runtime會將相關輔助函數進行替換成導入語句,從而減少babel編譯出來的代碼的文件大小

四.DllPlugin分包

經過DllPlugin插件分離出第三方包

  • 新建webpack.dll.conf.js

const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require("clean-webpack-plugin");

module.exports = {
  entry: {
    vendor: [
      'vue',
      'vue-router',
      'vuex',
      'axios',
      'element-ui',
      'echarts'
    ]
  },
  output: {
    filename: '[name]_dll_[hash:6].js', // 產生的文件名
    path: path.resolve(__dirname, '../static/dll'),
    library: '[name]_dll_[hash:6]'
  },
  plugins: [
    new CleanWebpackPlugin({
      root: path.resolve(__dirname, '../static/dll'),
      dry: false // 啓用刪除文件
    }),
    new webpack.DllPlugin({
      name: '[name]_dll_[hash:6]',
      path: path.resolve(__dirname, '../static/dll', '[name].dll.manifest.json')
    })
  ]
};複製代碼
  • 修改webpack.prod.conf.js

使用add-asset-html-webpack-plugin動態添加dll.jshtml

須要注意

  1. add-asset-html-webpack-plugin要在HtmlWebpackPlugin後引入;

  2. html-webpack-plugin依賴包版本4.0.0-alpha會出個問題,添加上去的路徑會變成undefined須要是3.2.0版本

const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
...
plugins: [
  // 插入dll json
  new webpack.DllReferencePlugin({
    context: path.join(__dirname),
    manifest: require('../static/dll/vendor.dll.manifest.json')
  }),
  new HtmlWebpackPlugin(),
  // 插入 dll js
  new AddAssetHtmlPlugin([{
    publicPath: config.build.assetsPublicPath + 'static/dll/',  // 注入到html中的路徑
    outputPath: 'static/dll/', // 輸出文件目錄
    filepath: resolve('static/dll/*.js'), // 文件路徑
    includeSourcemap: false,
    typeOfAsset: "js"
  }])
]複製代碼

五.按需加載代碼

經過vue寫的單頁應用時,可能會有不少的路由引入。當打包構建的時候,javascript包會變得很是大,影響加載。若是咱們能把不一樣路由對應的組件分割成不一樣的代碼塊,而後當路由被訪問的時候才加載對應的組件,這樣就更加高效了。這樣會大大提升首屏顯示的速度,可是可能其餘的頁面的速度就會降下來。
項目中路由按需加載(懶加載)的配置:

const Foo = () => import('./Foo.vue')
const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})複製代碼

六.提取公共代碼

若是每一個頁面的代碼都將這些公共的部分包含進去,則會形成如下問題 :
• 相同的資源被重複加載,浪費用戶的流量和服務器的成本。
• 每一個頁面須要加載的資源太大,致使網頁首屏加載緩慢,影響用戶體驗。
若是將多個頁面的公共代碼抽離成單獨的文件,就能優化以上問題 。Webpack內置了專門用於提取多個Chunk中的公共部分的插件CommonsChunkPlugin。
項目中CommonsChunkPlugin的配置:
// 全部在 package.json 裏面依賴的包,都會被打包進 vendor.js 這個文件中。

new webpack.optimize.CommonsChunkPlugin({
  name: 'vendor',
  minChunks: function(module, count) {
    return (
      module.resource &&
      /\.js$/.test(module.resource) &&
      module.resource.indexOf(
        path.join(__dirname, '../node_modules')
      ) === 0
    );
  }
}),
// 抽取出代碼模塊的映射關係
new webpack.optimize.CommonsChunkPlugin({
  name: 'manifest',
  chunks: ['vendor']
}),複製代碼

總結:

在現實項目中,項目上線後無疑就會要進行優化,特別是使用webpack打包後的項目,若是沒有進行優化,僅靠通常的腳手架搭建默認的配置,打包出來的項目性能堪憂,最直接體現的就是首屏加載速度,也是前端面試中常常考驗的哦,不慌,通過本文以上六種(包括但不限於)優化,打包從30分鐘,到2分鐘不到,總體還有優化空間,可使用其餘cdn等再進行優化方式,快去試試吧!

------------------------------------------------------------------------------------------------

相關文章
相關標籤/搜索