vue項目打包優化之happypack

HappyPack經過並行轉換文件使得初始webpack構建更快。這句話可不是我說的,是npm官網中happypack的readme的開場白。

我在前幾天的《vue項目打包優化之webpack-parallel-uglify-plugin》一文中提到過happypack,我說它有些雞肋,爲何這麼說呢,若是項目較小,可能打包時間優化的並非太好,甚至可能還會延長打包時間。不過在公司項目中我再使用webpack-parallel-uglify-plugin以後項目打包時間大概在3分鐘左右,在此基礎上使用happypack優化以後,時間縮短了將近一分鐘。javascript

如今我將happypack配置作個記錄和說明,以本身的demo爲例。項目是用vuecli腳手架搭建。css

首先咱們先了解一下happypack的一些參數

  1. id: String 用惟一的標識符 id。加載程序使用它來知道它應該與哪一個插件進行通.
  2. loaders: Array 用法和 webpack Loader 配置中同樣.
  3. threads: Number 表明開啓幾個子進程去處理這一類型的文件。默認爲:3
  4. verbose: Boolean 啓用此選項可將狀態消息從HappyPack記錄到STDOUT,默認是 true。
  5. threadPool: HappyThreadPool 表明共享進程池,即多個 HappyPack 實例都使用同一個共享進程池中的子進程去處理任務,以防止資源佔用過多。默認爲:null
  6. verboseWhenProfiling: Boolean 若是您但願HappyPack即便在webpack --profile運行時仍能生成其輸出,請啓用此選項。默認爲:false
  7. debug: Boolean 啓用此選項可將診斷消息從HappyPack記錄到STDOUT。用於故障排除。默認 false

接下來是demo中的配置

第一步,安裝happypack

npm i happypack -D複製代碼

//"happypack": "^5.0.1",demo中happypack版本
//"webpack": "^3.6.0",demo中webpack版本複製代碼

第二步,配置happypack

一、修改webpack.base.conf.js文件vue

const HappyPack = require('happypack');
const os = require('os');
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });複製代碼

提示:因爲HappyPack 對file-loader、url-loader 支持的不友好,因此沒修改相應loader使用。
module.exports = {
  context: path.resolve(__dirname, '../'),
  entry: {
    app: './src/main.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'),
    }
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'happypack/loader?id=vueLoader',
      },
      {
        test: /\.js$/,
        loader: 'happypack/loader?id=babelLoader',
        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('media/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
        }
      }
    ]
  },
  node: {
    // prevent webpack from injecting useless setImmediate polyfill because Vue
    // source contains it (although only uses it if it's native).
    setImmediate: false,
    // prevent webpack from injecting mocks to Node native modules
    // that does not make sense for the client
    dgram: 'empty',
    fs: 'empty',
    net: 'empty',
    tls: 'empty',
    child_process: 'empty'
  },
  plugins:[
    new HappyPack({
      //用id來標識 happypack處理那裏類文件
      id: 'vueLoader',
      //如何處理 用法和loader 的配置同樣
      loaders: [
        {
          loader:'vue-loader',
          options: vueLoaderConfig
        }
      ],
      //共享進程池
      threadPool: happyThreadPool,
      //容許 HappyPack 輸出日誌
      verbose: true,
    }),
    new HappyPack({
      //用id來標識 happypack處理那裏類文件
      id: 'babelLoader',
      //如何處理 用法和loader 的配置同樣
      loaders: [
        {
          loader:'babel-loader',
        }
      ],
      //共享進程池
      threadPool: happyThreadPool, 
     //容許 HappyPack 輸出日誌
      verbose: true,
    })
  ]}複製代碼

二、修改utils.js文件java

const HappyPack = require('happypack');
const os = require('os');
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });複製代碼

提示:因爲HappyPack 對less-loader、sass-loader、stylus-loader支持的不友好,因此沒修改相應loader使用。

exports.styleLoaders = function (options) {
  const output = []
  const plugins = []
  const loaders = exports.cssLoaders(options)
  for (const extension in loaders) {
    const loader = loaders[extension]
    if(extension!='less'&&extension!='sass'&&extension!='scss'&&extension!='stylus'&&extension!='styl'){
      output.push({
        test: new RegExp('\\.' + extension + '$'),
        use: [`happypack/loader?id=${extension}Loader`]
      })
      plugins.push(
        new HappyPack({
          //用id來標識 happypack處理那裏類文件
          id: `${extension}Loader`,
          //如何處理 用法和loader 的配置同樣
          loaders: loader,
          //共享進程池
          threadPool: happyThreadPool,
          //容許 HappyPack 輸出日誌
          verbose: true,
        })
      )
    }else{
      output.push({
        test: new RegExp('\\.' + extension + '$'),
        use: loader
      })
    }
   }
  return {output,plugins}
}複製代碼

因爲更改了css的規則,因此須要修改相關引用處的配置node

三、修改webpack.dev.conf.js文件webpack

const styleLoaders= utils.styleLoaders({ sourceMap: config.dev.cssSourceMap,
 usePostCSS: true
})複製代碼

const devWebpackConfig = merge(baseWebpackConfig, {plugins:styleLoaders.plugins},{
  module: {
    rules: styleLoaders.output
  },
  // cheap-module-eval-source-map is faster for development
  devtool: config.dev.devtool,
  ...
})
複製代碼

四、修改webpack.prod.conf.js文件web

const styleLoaders= utils.styleLoaders({
  sourceMap: config.build.productionSourceMap,
  extract: true,
  usePostCSS: true
})複製代碼

const webpackConfig = merge(baseWebpackConfig, {plugins:styleLoaders.plugins},{
  module: {
    rules: styleLoaders.output
  },
  devtool: config.build.productionSourceMap ? config.build.devtool : false,
 ...
})複製代碼

TIME!npm

相關文章
相關標籤/搜索