記一次vue-cli 3.0 build包太大致使首屏過長的解決方案

前端弟中弟,問題都是項目中遇到的,因此記錄了下來。javascript

我的博客css

目前學習Flutter還原豆瓣 ,以此深刻了解Flutter,求大佬們給個Star   ❤   ❀html

github.com/jahnli/flut…前端

只總結了親測效果明顯的幾種方案,解決方案大多來自於平常總結及各路大佬,若有不足,請大佬補充~vue

一、路由懶加載

在 Webpack  中,咱們可使用動態 import語法來定義代碼分塊點 (split point): import('./Foo.vue') // 返回 Promise

若是您使用的是 Babel,你將須要添加 syntax-dynamic-import 插件,才能使 Babel 能夠正確地解析語法。

結合這二者,這就是如何定義一個可以被 Webpack 自動代碼分割的異步組件。

const Foo = () => import('./Foo.vue')

在路由配置中什麼都不須要改變,只須要像往常同樣使用 Foo:

const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})

複製代碼

二、服務器和webpack打包同時配置Gzip

Gzip是GNU zip的縮寫,顧名思義是一種壓縮技術。它將瀏覽器請求的文件先在服務器端進行壓縮,而後傳遞給瀏覽器,瀏覽器解壓以後再進行頁面的解析工做。在服務端開啓Gzip支持後,咱們前端須要提供資源壓縮包,經過Compression-Webpack-Plugin插件build提供壓縮  

// 安裝插件

cnpm i --save-dev compression-webpack-plugin
 
// 在vue-config.js 中加入
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const productionGzipExtensions = ['js', 'css'];
const isProduction = process.env.NODE_ENV === 'production';
 
.....
module.exports = {
....
 // 配置webpack
 configureWebpack: config => {
  if (isProduction) {
   // 開啓gzip壓縮
   config.plugins.push(new CompressionWebpackPlugin({
    algorithm: 'gzip',
    test: /\.js$|\.html$|\.json$|\.css/,
    threshold: 10240,
    minRatio: 0.8
   }))
  }
 }
}
複製代碼

三、優化打包chunk-vendor.js文件體積過大

當咱們運行項目而且打包的時候,會發現chunk-vendors.js這個文件很是大,那是由於webpack將全部的依賴全都壓縮到了這個文件裏面,這時咱們能夠將其拆分,將全部的依賴都打包成單獨的js。
// 在vue-config.js 中加入
.....
module.exports = {
....
 // 配置webpack
 configureWebpack: config => {
  if (isProduction) {
    // 開啓分離js
    config.optimization = {
      runtimeChunk: 'single',
      splitChunks: {
        chunks: 'all',
        maxInitialRequests: Infinity,
        minSize: 20000,
        cacheGroups: {
          vendor: {
            test: /[\\/]node_modules[\\/]/,
            name (module) {
              // get the name. E.g. node_modules/packageName/not/this/part.js
              // or node_modules/packageName
              const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1]
              // npm package names are URL-safe, but some servers don't like @ symbols
              return `npm.${packageName.replace('@', '')}`
            }
          }
        }
      }
    };
  }
 }
}
// 至此,你會發現原先的vender文件沒有了,同時多了好幾個依賴的js文件 
複製代碼

四、啓用CDN加速

用Gzip已把文件的大小減小了三分之二了,但這個仍是得不到知足。那咱們就把那些不太可能改動的代碼或者庫分離出來,繼續減少單個chunk-vendors,而後經過CDN加載進行加速加載資源。
// 修改vue.config.js 分離不經常使用代碼庫
// 若是不配置webpack也可直接在index.html引入
module.exports = {
 configureWebpack: config => {
  if (isProduction) {
   config.externals = {
    'vue': 'Vue',
    'vue-router': 'VueRouter',
    'moment': 'moment'
   }
  }
 }
}
// 在public文件夾的index.html 加載
<!-- CND -->
<script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.runtime.min.js"></script>
<script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
複製代碼

五、完整vue.config.js代碼

const path = require('path')

// 在vue-config.js 中加入
// 開啓gzip壓縮
const CompressionWebpackPlugin = require('compression-webpack-plugin');
// 判斷開發環境
const isProduction = process.env.NODE_ENV === 'production';

const resolve = dir => {
  return path.join(__dirname, dir)
}

// 項目部署基礎
// 默認狀況下,咱們假設你的應用將被部署在域的根目錄下,
// 例如:https://www.my-app.com/
// 默認:'/'
// 若是您的應用程序部署在子路徑中,則須要在這指定子路徑
// 例如:https://www.foobar.com/my-app/
// 須要將它改成'/my-app/'
// iview-admin線上演示打包路徑: https://file.iviewui.com/admin-dist/
const BASE_URL = process.env.NODE_ENV === 'production'
  ? '/'
  : '/'

module.exports = {
  //webpack配置
  configureWebpack:config => {
    // 開啓gzip壓縮
    if (isProduction) {
      config.plugins.push(new CompressionWebpackPlugin({
        algorithm: 'gzip',
        test: /\.js$|\.html$|\.json$|\.css/,
        threshold: 10240,
        minRatio: 0.8
      }));
      // 開啓分離js
      config.optimization = {
        runtimeChunk: 'single',
        splitChunks: {
          chunks: 'all',
          maxInitialRequests: Infinity,
          minSize: 20000,
          cacheGroups: {
            vendor: {
              test: /[\\/]node_modules[\\/]/,
              name (module) {
                // get the name. E.g. node_modules/packageName/not/this/part.js
                // or node_modules/packageName
                const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1]
                // npm package names are URL-safe, but some servers don't like @ symbols
                return `npm.${packageName.replace('@', '')}`
              }
            }
          }
        }
      };
      // 取消webpack警告的性能提示
      config.performance = {
        hints:'warning',
            //入口起點的最大致積
            maxEntrypointSize: 50000000,
            //生成文件的最大致積
            maxAssetSize: 30000000,
            //只給出 js 文件的性能提示
            assetFilter: function(assetFilename) {
          return assetFilename.endsWith('.js');
        }
      }
    }
  },
  // Project deployment base
  // By default we assume your app will be deployed at the root of a domain,
  // e.g. https://www.my-app.com/
  // If your app is deployed at a sub-path, you will need to specify that
  // sub-path here. For example, if your app is deployed at
  // https://www.foobar.com/my-app/
  // then change this to '/my-app/'
  publicPath: BASE_URL,
  // tweak internal webpack configuration.
  // see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
  devServer: {
    host: 'localhost',
    port: 8080, // 端口號
    hotOnly: false,
    https: false, // https:{type:Boolean}
    open: true, //配置自動啓動瀏覽器
    proxy:null // 配置跨域處理,只有一個代理

  },
  // 若是你不須要使用eslint,把lintOnSave設爲false便可
  lintOnSave: true,
  css:{
    loaderOptions:{
      less:{
        javascriptEnabled:true
      }
    },
    extract: true,// 是否使用css分離插件 ExtractTextPlugin
    sourceMap: false,// 開啓 CSS source maps
    modules: false// 啓用 CSS modules for all css / pre-processor files.
  },
  chainWebpack: config => {
    config.resolve.alias
      .set('@', resolve('src')) // key,value自行定義,好比.set('@@', resolve('src/components'))
      .set('@c', resolve('src/components'))
  },
  // 打包時不生成.map文件
  productionSourceMap: false
  // 這裏寫你調用接口的基礎路徑,來解決跨域,若是設置了代理,那你本地開發環境的axios的baseUrl要寫爲 '' ,即空字符串
  // devServer: {
  // proxy: 'localhost:3000'
  // }
}
複製代碼
相關文章
相關標籤/搜索