vue-cli3多頁應用構建優化

接續前篇多頁應用改造,優化改造後的項目打包效果。javascript

效果對比

階段 磁盤佔用空間 打包時間 備註
原始 9.9M - 5.20版
架構改造(SPA->MPA) 7.1M - 5.27版
樣式整合 7.0M - 5.30版
公共組件&工具類整合 6.9M - 6.4版
圖片壓縮 6.0M 20.767s -
UglifyJs 5.9M 23.391s -
合併小文件 5.3M 55.469s -
代碼分割splitChunks 5.1M 73.730s -
gzip 6.3M 89.204s -

優化前

優化前打包

優化後

優化後打包

優化過程

壓縮圖片

chainWebpack: config => {
  config.module
    .rule("image-webpack-loader")
    .test(/\.(gif|png|jpe?g|svg)$/i)
    .use("file-loader")
    .loader("image-webpack-loader")
    .tap(() => ({
      disable: process.env.NODE_ENV !== "production"
    }))
    .end()
};

添加UglifyJs,移除console

const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
configureWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
      const plugins = []
      plugins.push(
        new UglifyJsPlugin({
          uglifyOptions: {
            compress: {
              drop_console: true,
              drop_debugger: true
            }
          },
          cache: true, // 啓用文件緩存
          parallel: true // 使用多進程並行運行來提升構建速度
          // sourceMap: false // 映射錯誤信息到模塊
        })
      )
      config.plugins = [
        ...config.plugins,
        ...plugins
      ]
    }
  }

動態導入合併小文件webpackChunkName

原來打包出來的文件,快上百個了,還有好些0.29KB的,須要合併下。此處使用webpackChunkNamecss

首先按照業務含義合併,以service爲例html

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

const routes = [
  {
    path: '/service',
    component: () => import(/* webpackChunkName: "service-index" */ '@service/components/page-layout/TwoColLayout.vue'),
    redirect: { name: 'Detail' },
    children: [
      {
        path: 'detail',
        name: 'Detail',
        component: () => import(/* webpackChunkName: "service-index" */ '@service/views/detail/index.vue')
      },
      /**
       * 接口申請(指標)
       */
      {
        path: 'api-apply',
        name: 'ApiApply',
        component: () => import(/* webpackChunkName: "service-api-apply" */ '@service/views/detail/views/apply-api/index.vue')
      },
      {
        path: 'api-apply-form',
        name: 'ApiApplyForm',
        component: () => import(/* webpackChunkName: "service-api-apply" */ '@service/views/detail/views/apply-api/api-apply-form.vue')
      },
      /**
       * 接口管理
       */
      {
        path: 'manage',
        name: 'Manage',
        component: () => import(/* webpackChunkName: "service-manage" */ '@service/views/manage/index.vue')
      },
      { // 接口管理 - 新建/修改
        path: 'manage/upsert',
        name: 'ManageUpsert',
        component: () => import(/* webpackChunkName: "service-manage" */ '@service/views/manage/module/upsert/index.vue')
      }]
  },
  {
    path: '*',
    redirect: '/service'
  }
]

const router = new Router({ mode: 'history', routes })

export default router

service合併後
看起來都比較小,過小的獨立文件單佔鏈接數不是很合適。那就service-manage保留(業務上此處只有管理員能訪問的管理頁會調用,通常人看不到,不用和其餘邏輯一塊兒加載,仍是保持獨立),
其餘的再統一合併成service-main。這裏合併的宗旨是文件不超過250K。vue

...
此處省略處理各個產品打包合併過程。java

代碼分割splitChunks

chunk-vendors-xxx.js空間分析
從打包目錄看,chunk-vendors-xxx.js已達1.7M,須要拆分。node

參考文章: 一步一步的瞭解webpack4的splitChunk插件webpack

這裏根據實際狀況優化,具體你們可經過vue-cli-service build --report生成 report.html分析包內容
圖片描述git

首先拆出公用的element-uigithub

configureWebpack: config => {
    if (IS_PROD) {
      config.optimization = {
        splitChunks: {
          cacheGroups: {
            element: {
              name: 'vendors-element-ui',
              test: /[\\/]node_modules[\\/]element-ui[\\/]/,
              chunks: 'initial',
              reuseExistingChunk: true,
              enforce: true,
              priority: 3
            },
          }
        }
      }
    }
  }

而後把全部node_modlues下的引用合併到vendorsweb

...
cacheGroups: {
        vendors: {
          name: 'vendors',
          test: /[\\/]node_modules[\\/]/,
          chunks: 'all',
          priority: 2
        }
}
...

再將全部模塊中被不一樣的 chunk 引入超過 1 次的抽取爲 common

...
cacheGroups: {
        common: {
          name: 'common',
          chunks: 'initial',
          minChunks: 2,
          maxInitialRequests: 5,
          priority: 1
        }
}
...

啓用gzip

const CompressionWebpackPlugin = require('compression-webpack-plugin')
  configureWebpack: config => {
    if (IS_PROD) {
      const plugins = []
      plugins.push(
        new CompressionWebpackPlugin({
          filename: '[path].gz[query]',
          algorithm: 'gzip',
          test: /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i,
          threshold: 10240,
          minRatio: 0.8
        })
      )
      config.plugins = [
        ...config.plugins,
        ...plugins
      ]
    }
  }

css根據入口文件打包

圖片描述
到這裏,打包出來的css文件都很小,單獨放到一個資源文件去請求挺浪費鏈接數的,因此嘗試合併css。

參考:Extracting CSS based on entry

目前暫未成功,可能與上述webpackChunkName方式衝突,合併後的css正常,但根據webpackChunkName以後的css依舊會打包出來,暫時沒找到更好的解決辦法。待更新~

警告處理

[mini-css-extract-plugin] Conflicting

圖片描述

參考issue reported on Github

兩種解決方法:

  1. 調整import順序
  2. 配置忽略警告

選用方法1解決。

相關文章
相關標籤/搜索