[vue]優化並加快vue cli打包的速度

  • 1955
  • 0
  • vue
  • 2018-08-20

[vue]優化並加快vue cli打包的速度

前言

相信大部份使用vue single file做開發的人,幾乎都是使用vue cli的方式,但隨著專案越來越大,依賴的第三方越來越多,速度也就越來越慢了,此篇則是筆者爬了很多文章之後,最後自己成功實做,也確實加快了不少速度,所以筆記下來也供各個讀者參考看看。

導覽

  1. 用ParallelUglifyPlugin來取代UglifyJsPlugin
  2. 把一些不常改變的第三方Library另外獨立出來編譯
  3. 指定Babel做快取
  4. 使用HappyPack來做並行任務

用ParallelUglifyPlugin來取代UglifyJsPlugin

我們都知道javascript或node.js是單線程的,所以cli預設用的就是單線程的Uglify,那我們可以去下載第三方的來加快一點點速度

npm i webpack-parallel-uglify-plugin --D

接著我們到webpack.prod.config.js,修改一下把原本的Uglify改掉,把原本程式碼註解改成如下

 // new webpack.optimize.UglifyJsPlugin({
 //   compress: {
 //     warnings: false
 //   },
 //   sourceMap: true
 // }),
 new ParallelUglifyPlugin({
   cacheDir: '.cache/',
   uglifyJS: {
     output: { comments: false },
     compress: { warnings: false }
   }
 }),

把一些不常改變的第三方Library另外獨立出來編譯

這部份則需要去自定哪些第三方的package在webpack打包的時候,不要加入編譯的部份,如果我們想要編譯第三方的話,我們則需要另下指令,自行去打包這些第三方的library,首先新增一支webpack.dll.config.js,並輸入如下內容

const path = require("path")
const webpack = require("webpack")
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin')


module.exports = {
  entry: {
    vendor: ['vue/dist/vue.esm.js', 'axios', 'element-ui', 'idb', 'jquery', 'jquery-ui', 'lodash', 'moment',
      'vuedraggable', 'vuex']
  },
  output: {
    path: path.join(__dirname, '../static/js'),
    filename: '[name].dll.js',
    library: '[name]_library'
  },
  plugins: [
    new webpack.DllPlugin({
      path: path.join(__dirname, '.', '[name]-manifest.json'),
      name: '[name]_library',
      context: __dirname
    }),
    new ParallelUglifyPlugin({
      cacheDir: '.cache/',
      uglifyJS: {
        output: { comments: false },
        compress: { warnings: false }
      }
    })
  ]
}

接著我們去package.json,新增dll的指令如下

 "dll": "webpack --config ./build/webpack.dll.config.js",

此時我們輸入npm run dll的話,就應該會編出一支預先編好的dll,在此我們需得把此檔案放在index.html的所有js的上面就行了,接著我們在webpack.dev.config.js和webpack.prod.config.js加入下面內容

new webpack.DllReferencePlugin({
      context: __dirname,
      manifest: require('./vendor-manifest.json')
    }),

緊接著執行就可以感受到變快了許多了。

指定Babel做快取

這個也是很簡單,我們使用babel的時候,如果可以做個快取,下次就不會每次都要從無到有的去編譯,這樣也會加快一點點速度,我們只需要在使用babel-loader加入options就行了,請到webpack.base.config.js改成如下

 {
   test: /\.js$/,
   exclude:'/node_modules',
   loader: 'babel-loader',
   options: {
     cacheDirectory: true
   },
   include: [resolve('src'), resolve('test')]
 },

使用HappyPack來做並行任務

這步其實也能加快很多,廢話不多說就是貼上程式碼示例,但是這邊得特別注意一下,就是url-loader無法支援哦。

'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
const HappyPack = require('happypack')

function resolve(dir) {
  return path.join(__dirname, '..', dir)
}

module.exports = {
  entry: {
    app: process.env.NODE_ENV === 'development' ? './src/main.js' : './src/main.build.js'
  },
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
      "pages": resolve('src/pages'),
      "components": resolve('src/components'),
      "services": resolve('src/services/'),
      "utilitys": resolve('src/utilitys'),
      "images": resolve('src/assets/images')
    }
  },
  plugins: [
    new HappyPack({
      id: 'babel-loader',
      loaders: [{
        loader: 'babel-loader',
        options: {
          cacheDirectory: true
        }
      }]
    }),
    new HappyPack({
      id: 'vue-loader',
      loaders: [{
        loader: 'vue-loader'
      }]
    }),
    new HappyPack({
      loaders: [{
        path: 'vue-loader',
        query: {
          vueLoaderConfig
        }
      }]
    }),
    new HappyPack({
      id: 'eslint-loader',
      loaders: [{
        loader: 'eslint-loader',
        options: {
          formatter: require('eslint-friendly-formatter')
        }
      }]
    })
  ],
  module: {
    rules: [
      {
        test: /\.(js|vue)$/,
        loader: 'happypack/loader?id=eslint-loader',
        enforce: 'pre',
        include: [resolve('src'), resolve('test')],
        exclude: '/node_modules'
      },
      {
        test: /\.vue$/,
        loader: 'happypack/loader?id=vue-loader',
        exclude: '/node_modules',
        options: vueLoaderConfig
      },
      {
        test: /\.js$/,
        exclude: '/node_modules',
        loader: 'happypack/loader?id=babel-loader',
        include: [resolve('src'), resolve('test')]
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[ext]')
        }
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('media/[name].[ext]')
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('fonts/[name].[ext]')
        }
      }
    ]
  }
}

最後來比較一下優化前和優化後時間的差別吧。

優化前

優化後

結論

經過優化之後增加了不少速度,雖然程式碼也變得複雜了一點點,但是還在控制範圍裡面,如果各位讀者有任何更好的建議,再請告知筆者哦。