Webpack 3 - 打包優化

隨著項目復雜程度的增加,代碼打包的耗時也越來越長,于是我想結合實際開發環境提升一下首次打包的速度。
目前項目中使用的打包壓縮工具是webpack默認的UglifyJS插件,它使用的是單線程壓縮代碼,也就是說當多個js文件需要被壓縮時,它需要將文件一個一個進行壓縮。因此在正式環境中打包壓縮代碼就顯得非常慢。最后使用一下幾種方法來優化項目文件(基于webpack3)。

1、使用HappyPack多進程解析和處理文件

  • 由于有大量文件需要解析和處理,所以構建是文件讀寫和計算密集型的操作,特別是當文件數量變多后,Webpack構建慢的問題會顯得更為嚴重。運行在 Node.之上的Webpack是單線程模型的,也就是說Webpack需要一個一個地處理任務,不能同時處理多個任務。Happy Pack ( https://github.com/amireh/happypack )就能讓Webpack做到這一點,它將任務分解給多個子進程去并發執行,子進程處理完后再將結果發送給主進程。
    1)HappyPack插件安裝:
    $ npm install -D happypack
    2)對文件webpack.base.conf.js 引入
    const HappyPack = require('happypack');
    const os = require('os');
    const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
    plugins: [
       new HappyPack({
      // 用id,來代表當前的HappyPack是用來處理一類特定的文件
      id: 'babel',
      // 如何處理.js文件,用法和Loader配置中一樣
      loaders: [{
        path: 'babel-loader',
        cache: true,
      }],
      // include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')],
      threadPool: HappyPackThreadPool,
    }),

    new HappyPack({
      // 用id,來代表當前的HappyPack是用來處理一類特定的文件
      id: 'vue',
      loaders: [
        {
          loader: 'vue-loader',
          options: vueLoaderConfig
        }
      ],
      threadPool: HappyPackThreadPool,
    }),
    ],
    module: {
     rules: [
      {
        test: /\.js$/,
        // 將對.js 文件的處理轉交給 id 為 babel 的HappyPack實例
        use: ['happypack/loader?id=babel'],
        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')],
        // 排除第三方插件
        exclude: path.resolve(__dirname, 'node_modules'),
      },
      {
        test: /\.vue$/,
        use: ['happypack/loader?id=vue'],
      },
      ]
    },

2、使用cdn優化依賴包的體積

  • 日常開發過程中,前端這塊早就已經開始進行工程化和組件化開發了,所以免不了下載各種node包,使得打包后的體積也是非常的龐大,下面使用webpack的一個配置外部擴展就可以解決這類問題
1)  在index.html中引入cdn,可以使用國內的bootcdn服務
    <script src="https://cdn.bootcss.com/vue/2.5.2/vue.min.js"></script>
    <script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>
    <script src="https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js"></script>
    <script src="https://cdn.bootcss.com/axios/0.18.0/axios.min.js"></script>
    <script src="https://cdn.bootcss.com/element-ui/2.11.1/index.js"></script>
2) 在webpack.base.conf.js 配置externals,externals與output同級,屬性是包暴露出的方法名稱,后面的值是你在項目中使用的名稱
    externals: {
    'vue': 'Vue',
    'vue-router': 'VueRouter',
    'vuex': 'Vuex',
    'element-ui': 'ELEMENT',
    'axios': 'axios',
  },
3)在router.js配置,把Vue注釋或者刪除
// import Vue from 'vue';
import VueRouter from 'vue-router';
import index from 'views/index';
// Vue.use(Router);
4)在main.js注釋掉引用的element,可以使用按需引入element
// 按需引入
import {
  Loading,
  Message,
  MessageBox,
  Notification,
} from 'element-ui'
// 按需使用
Vue.use(Loading.directive)
// 掛載到vue實例上面
Vue.prototype.$loading = Loading.service
Vue.prototype.$msgbox = MessageBox
Vue.prototype.$confirm = MessageBox.confirm
Vue.prototype.$alert = MessageBox.alert
Vue.prototype.$prompt = MessageBox.prompt
Vue.prototype.$message = Message
Vue.prototype.$notify = Notification,

3、使用ParallelUglifyPlugin多進程壓縮代碼文件

// 在webpack.prod.conf.js文件配置
// ParallelUglifyPlugin插件安裝:
   $ npm i -D webpack-parallel-uglify-plugin
  const ParallelUglifyPlugin =require('webpack-parallel-uglify-plugin');
  plugins: [
      new ParallelUglifyPlugin({
        cacheDir: '.cache/',
        uglifyJs:{
          compress: {
            warnings: false,
            drop_debugger: true,
            drop_console:true,       // 打包移除console
            pure_funcs: ['console.log']
          },
          sourceMap: config.build.productionSourceMap,
        }
       }),
  ]

4、Gzip壓縮和sourceMap優化

// 在webpack的build文件中,開啟Gzip壓縮功能和禁用資源地圖。打包以后就不會再有sourceMap文件了,也會多了幾個以.js.gz后綴名的文件
module.exports = {
  // ...
  build: {
    productionSourceMap: false,
    productionGzip: true,
  }
}

5、路由異步加載 可以幫助我們根據路由來按需加載。它的原理是使用了import() 而非 import 是因為 import 是靜態編譯,而import() 同 require,是可以進行動態加載的。 但是千萬要注意的是,引用過程中千萬不要使用變量,這會導致編譯通過但是編譯時間長得令人發指又或者直接內存溢出。

// 使用require方法
const example = resolve => require(['../components/index.vue'], resolve);

優化效果

打包時間

  • 打包前


  • 打包后


打包體積

  • 打包前


  • 打包后


到此 進行了部分的webpack優化,剩下的問題,都是根據個人需求來處理。因為是基于webpack3進行優化,有些功能沒有實現。原本設想是升級到 webpack4 的,過程不算太順利,過多的依賴升級錯誤只能放棄,但是升級到 webpack4,嘗試一下說不定就成功,畢竟 webpack4 進行了多處優化,一些存在安全問題的依賴包也得到解決了,后期會升級到webpack4的。最后還需要提醒大家一點,本篇文章中的例子僅供參考學習,切誤將本篇文章中的代碼直接使用在正式項目當中。希望以上代碼對大家有所幫助。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 前言: 我最近需要整理一下 webpack 這個前端構建工具的相關知識,希望對前端工程化的和模塊化有更多的理解,我...
    Joah_l閱讀 6,371評論 0 9
  • 在上篇中搭建了vue的基本腳手架,為了加快腳手架打包項目的構建速度和減少打包代碼的體積,下面在上一篇的基礎上添磚加...
    Evtion閱讀 1,729評論 0 4
  • webpack 優化主要分為兩部分,一是優化構建速度,二是優化輸出質量。所謂優化構建速度,那就是要打包快,優化輸出...
    DJL簫氏閱讀 1,714評論 0 3
  • 今天周五啦!明天可以睡個懶覺。 今天下午照例去了爺爺家,在院子里過了把足球癮,很開心。回到家又去對門找妹妹玩...
    dream11閱讀 85評論 0 0
  • 沒課的時候最忙,所以現在上課是一種休息是一種享受,在圖書館與文學院之間的路上來來去去,最大體會是很多人在該學點東西...
    群玉秉輝閱讀 148評論 0 1