Vue.jsvue

vue-cli3 打包优化

2020-07-13  本文已影响0人  zhudying

本文具体介绍 vue.config.js 配置,以优化打包后 chunk-vendors.js 的大小,不具体介绍代码优化及各类api封装等。

1. 老生常谈的代码层面的优化
  1. 按需引入各类组件库
    详情请见element 官网
    1)element,echarts等
  // element
  import { Button, Input } from 'element-ui';
  Vue.use(Button).use(Input);
  
  // echarts
  //引入基本模板
  let echarts = require('echarts/lib/echarts')

  // 引入折线图等组件
  require('echarts/lib/chart/gauge')
  require('echarts/lib/chart/radar')
  Vue.prototype.$echarts = echarts

.babel.config.js

module.exports = {
  presets: [["@vue/app", { useBuiltIns: "entry" }]],
  plugins: [
    // element官方教程
    [
      "component",
      {
        libraryName: "element-ui",
        styleLibraryName: "theme-chalk"
      }
    ]
  ]
}
  1. v-if 和 v-show选择调用
    1)少使用v-if
    2)绑定key

  2. 细分vuejs组件
    1)组件细分,比如一个组件,可以把整个组件细分成轮播组件、列表组件、分页组件等。

  3. 减少watch的数据
    1)数据大时,系统会出现卡顿,所以减少watch的数据。

  4. 路由懒加载
    1)分割路由,当路由被访问的时候才加载对应的组件。

  const router = new VueRouter({
    routes: [
      { path: '/foo', component:  () => import('./Foo.vue')}
    ]
  })
  1. 内容类系统的图片资源按需加载
    1)图片加载比较多,使用v-lazy之类的懒加载。
  npm install vue-lazyload --save-dev
  import VueLazyload from 'vue-lazyload'
  Vue.use(VueLazyload)

  <img v-lazy="/static/img/1.png">
  1. 手动清除各类事件监听器,定时器及闭包等

  2. SSR(服务端渲染)
    如果项目比较大,首屏无论怎么做优化,都出现闪屏或者一阵黑屏的情况。可以考虑使用SSR(服务端渲染)

2. webpack 打包的优化

查看各类占比 npm run build --report
在 dist 文件里,report.html 在浏览器打开即可

  1. 开启gzip压缩
// 下载
npm install compression-webpack-plugin --save-dev
const isProduction = ["production", "prod"].includes(process.env.NODE_ENV);
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i;

configureWebpack: config => {
    const plugins = [];
    if (isProduction) {
       plugins.push(
              new CompressionWebpackPlugin({
              filename: "[path].gz[query]",
              algorithm: "gzip",
              test: productionGzipExtensions,
              threshold: 10240,
              minRatio: 0.8
           })
       );
    }
  config.plugins = [...config.plugins, ...plugins];
}
  1. splitChunks 单独打包第三方模块
  // webpack配置
  chainWebpack: (config) => {
    if (isProduction) {
      config.optimization.delete("splitChunks");
    }
    return config;
  },
  configureWebpack: config => {
    if (isProduction) {
      // 利用 splitChunks 单独打包第三方模块
      config.optimization = {
        splitChunks: {
          cacheGroups: {
            common: {
              name: "chunk-common",
              chunks: "initial",
              minChunks: 2,
              maxInitialRequests: 5,
              minSize: 0,
              priority: 1,
              reuseExistingChunk: true,
              enforce: true
            },
            vendors: {
              name: "chunk-vendors",
              test: /[\\/]node_modules[\\/]/,
              chunks: "initial",
              priority: 2,
              reuseExistingChunk: true,
              enforce: true
            },
            elementUI: {
              name: "chunk-elementui",
              test: /[\\/]node_modules[\\/]element-ui[\\/]/,
              chunks: "all",
              priority: 3,
              reuseExistingChunk: true,
              enforce: true
            },
            echarts: {
              name: "chunk-echarts",
              test: /[\\/]node_modules[\\/](vue-)?echarts[\\/]/,
              chunks: "all",
              priority: 4,
              reuseExistingChunk: true,
              enforce: true
            }
          }
        }
      };
    }
    config.plugins = [...config.plugins, ...plugins];
  }
  1. 去除consollog
  configureWebpack: config => {
    const plugins = [];
    if (isProduction) {
      // 去除consollog
      plugins.push(
        new UglifyJsPlugin({
          uglifyOptions: {
            compress: {
              warnings: false,   // 打包报错可注掉
              drop_console: true,
              drop_debugger: false,
              pure_funcs: ["console.log"] //移除console
            },
          },
          sourceMap: false,
          parallel: true,
        })
      );
    }
    config.plugins = [...config.plugins, ...plugins];
  }

设置完后,打包后可以看到 .gz 结尾的文件,在http请求的Request Headers 中能看到 Accept-Encoding:gzip。
要使服务器返回.gz文件,还需要对服务器进行配置,根据Request Headers的Accept-Encoding标签进行鉴别,如果支持gzip就返回.gz文件。

完整vue.config.js
const path = require('path');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i;
// 生产环境名称
const isProduction = ["production", "prod"].includes(process.env.NODE_ENV);
const resolve = dir => path.join(__dirname, dir);
module.exports = {
  publicPath: '/',    // 公共路径
  runtimeCompiler: true, // 是否使用包含运行时编译器的 Vue 构建版本
  outputDir: process.env.NODE_ENV === "development" ? 'devdist' : 'dist', // 不同的环境打不同包名
  pluginOptions: {
    "style-resources-loader": {
      preProcessor: "less",
      patterns: [
        // 这个是加上自己的路径,
        // 注意:试过不能使用别名路径
        path.resolve(__dirname, "./src/assets/css/variable.less")
      ]
    }
  },
  lintOnSave: false,  // 关闭eslint
  productionSourceMap: false,  // 清楚 .map 文件
  devServer: {   // 配置服务器
    port: 8111,
    open: true,
    https: false,
    proxy: {
      '/api/*': {
        target: process.env.VUE_APP_URL,    // 目标 API 地址
        ws: true,                               // 是否代理 websockets
        changOrigin: true,                      // 跨域配置
        pathRewrite: {
          '^/api': '/'
        }
      }
    }
  },
  // webpack配置
  chainWebpack: (config) => {
    // 别名路径
    config.resolve.alias
      .set('@', resolve('src'))
      .set('@i', resolve('src/assets/image'))
      .set('@s', resolve('src/assets/css'))
      .set('@j', resolve('src/assets/js'))
    if (isProduction) {
      config.optimization.delete("splitChunks");
    }
    return config;
  },
  // 配置webpack
  configureWebpack: config => {
    const plugins = [];
    if (isProduction) {
      // 开启gzip压缩
      plugins.push(
        new CompressionWebpackPlugin({
          filename: "[path].gz[query]",
          algorithm: "gzip",
          test: productionGzipExtensions,
          threshold: 10240,
          minRatio: 0.8
        })
      );
      // 利用 splitChunks 单独打包第三方模块
      config.optimization = {
        splitChunks: {
          cacheGroups: {
            common: {
              name: "chunk-common",
              chunks: "initial",
              minChunks: 2,
              maxInitialRequests: 5,
              minSize: 0,
              priority: 1,
              reuseExistingChunk: true,
              enforce: true
            },
            vendors: {
              name: "chunk-vendors",
              test: /[\\/]node_modules[\\/]/,
              chunks: "initial",
              priority: 2,
              reuseExistingChunk: true,
              enforce: true
            },
            elementUI: {
              name: "chunk-elementui",
              test: /[\\/]node_modules[\\/]element-ui[\\/]/,
              chunks: "all",
              priority: 3,
              reuseExistingChunk: true,
              enforce: true
            },
            echarts: {
              name: "chunk-echarts",
              test: /[\\/]node_modules[\\/](vue-)?echarts[\\/]/,
              chunks: "all",
              priority: 4,
              reuseExistingChunk: true,
              enforce: true
            }
          }
        }
      };
      // 去除consollog
      plugins.push(
        new UglifyJsPlugin({
          uglifyOptions: {
            compress: {
              // warnings: false,
              drop_console: true,
              drop_debugger: false,
              pure_funcs: ["console.log"] //移除console
            },
          },
          sourceMap: false,
          parallel: true,
        })
      );
      config.externals = {
      }
    }
    config.plugins = [...config.plugins, ...plugins];
  }
}
上一篇 下一篇

猜你喜欢

热点阅读