Bootstrap

解决vue项目打包后文件过大导致首屏加载30s+的问题

依赖

vue v2.6
axios+tailwindcss+element-ui+...

文件打包情况

  File                                      Size             Gzipped

dist/js/chunk-vendors.fb40d429.js         1205.36 KiB      337.06 KiB
dist/js/album~articleAdd~articleEdit.84528c7c.js    69.05 KiB        23.07 KiB
dist/js/articleReplices.97fd5e5f.js       15.29 KiB        4.83 KiB
dist/js/album.9c381f9e.js                 14.08 KiB        4.03 KiB
dist/js/app.976ad1f5.js                   14.07 KiB        4.81 KiB
dist/js/article.81034e7e.js               9.77 KiB         3.83 KiB
dist/css/app.81735294.css                 2224.75 KiB      205.37 KiB
dist/css/chunk-vendors.fd94e02a.css       441.91 KiB       112.52 KiB
dist/css/album.790777ae.css               7.36 KiB         1.20 KiB
dist/css/articleReplices.a69cc70c.css     6.82 KiB         1.12 KiB
dist/css/chunk-b5d7d804.a912b24b.css      4.78 KiB         0.98 KiB

问题分析

1.vendorsjs文件过大,是由于所有的第三方库js文件都打包在这个文件下。

2.vendorcss文件过大,主要原因tailwindcss,element-uicss文件过大导致。

3.以上文件过大问题导致在线访问需要30s+。

解决方案

解决文件过大问题方案:

1.第三方文件库拆分打包;

参考:webpack SplitChunksPlugin实用指南

2.CDN引入依赖库;

参考:使用externals解决chunk-vendors.js过大问题

3.gzip压缩文件;

参考:vue-cli3项目开启gzip压缩

方案选择

方案1和方案2都是解决第三方库的问题,由于当前的项目比较简单,暂时不考虑以后项目升级维护等问题,所以虽然方案2将第三方库剥离项目,但还是选择方案2。第三个压缩文件是个可选方案,不与其他方案冲突,也可以同时使用。本着追求更高更快更强的精神,我们就选择方案2和方案3的结合;

实施

1.css文件问题解决

tailwindcss无用样式过滤,根据官网
删除未使用的CSS

// tailwind.config.js
module.exports = {
  purge: [
    './src/**/*.html',
    './src/**/*.vue',
    './src/**/*.jsx',
  ],
  theme: {},
  variants: {},
  plugins: [],
}

2.cdn引入vue, element-ui css和js问题解决

```	
// vue.config.js
module.exports = {
    chainWebpack(config) {
        const cdn = {
            css: [
                // element-ui css
                'https://unpkg.com/element-ui/lib/theme-chalk/index.css'
            ],
            js: [
                // vue must at first!
                'https://unpkg.com/vue/dist/vue.js',
                // element-ui js
                'https://unpkg.com/element-ui/lib/index.js'
            ]
        }
        config.plugin('html')
            .tap(args => {
                args[0].cdn = cdn
                return args
            })
    }
}


// /public/index.html
<!-- 引入样式 -->
<% for(var css of htmlWebpackPlugin.options.cdn.css) { %>
  <link rel="stylesheet" href="<%=css%>">
<% } %>  
<!-- 引入JS -->
<% for(var js of htmlWebpackPlugin.options.cdn.js) { %>
  <script src="<%=js%>"></script>
<% } %>

3.gzip压缩

使用webpack插件compression-webpack-plugin,打包后dist文件中*.gz文件为压缩文件

// vue.config.js
const CompressionPlugin = require("compression-webpack-plugin");

module.exports = {
    configureWebpack: config => {
        if (process.env.NODE_ENV === 'production') {
            return {
                plugins: [
                    new CompressionPlugin({
                        test: /\.(js|css)$/,// 匹配文件名
                    }),
                ]
            }
        }
    },
}

nginx配置

#开启gzip功能
gzip on;
# 是否在http header中添加Vary: Accept-Encoding,给CDN和代理服务器使用,针对相同url,可以根据头信息返回压缩和非压缩副本
gzip_vary on;
#开启gzip静态压缩功能,开启nginx_static后,对于任何文件都会先查找是否有对应的gz文件
gzip_static on;
#gzip 压缩类型
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

效果

优化后打包

File                                      Size             Gzipped

  dist/js/chunk-vendors.510dc93b.js         418.56 KiB       129.36 KiB
  dist/js/articleAdd~articleEdit~c-album    69.05 KiB        23.08 KiB
  .9f45d364.js
  dist/js/articleReplices.e86f355e.js       15.29 KiB        4.83 KiB
  dist/js/app.a18348b2.js                   14.68 KiB        4.92 KiB
  dist/js/c-album.f68189a0.js               13.66 KiB        3.97 KiB
  dist/js/article.df529f47.js               9.77 KiB         3.83 KiB
  dist/css/chunk-vendors.fd94e02a.css       441.91 KiB       112.52 KiB
  dist/css/app.c56487ee.css                 12.66 KiB        3.21 KiB
  dist/css/c-album.790777ae.css             7.36 KiB         1.20 KiB

优化后在线访问

62 requests
672 kB transferred
2.1 MB resources
Finish: 3.59 s
DOMContentLoaded: 2.33 s
Load: 2.51 s
;