vue-cli3 dist包体积过大的解决办法

742 阅读2分钟

背景:项目打包后的dist包体积过大,达到了35m以上比较沉重了,需要给它瘦身减肥。

1. 使用路由懒加载
{
  path: '/login',
  name: '登录页',
  component: () => import(/* webpackChunkName: "page" */ '@/page/login/index'),
}
2. 安装插件

借助webpack插件"webpack-bundle-analyzer"生成代码分析报告

npm install --save-dev webpack-bundle-analyzer

vue-cli3:配置vue.config.js文件

var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
 
module.exports = {
    configureWebpack: (config) => {
           config.plugins.push(
               new BundleAnalyzerPlugin({
                    openAnalyzer: false, // 在默认浏览器中是否自动打开报告,默认 true
                })
           )
    }
}

详细配置:

module.exports = {
    configureWebpack: (config) => {
            config.plugins.push(
                new BundleAnalyzerPlugin({
                    analyzerMode:'server', // 可以是 server、static、json、disabled。在server模式下,分析器将启动HTTP服务器来显示软件包报告。在“静态”模式下,会生成带有报告的单个HTML文件。在disabled模式下,你可以使用这个插件来将generateStatsFile设置为true来生成Webpack Stats JSON文件。
                    analyzerHost: '127.0.0.1', // 将在“服务器”模式下使用的端口启动HTTP服务器
                    analyzerPort: 8888, // 端口号
                    reportFilename: 'report.html', // 路径捆绑,将在static模式下生成的报告文件。相对于捆绑输出目录
                    defaultSizes: 'parsed', // 默认显示在报告中的模块大小匹配方式。应该是stat,parsed或者gzip中的一个
                    openAnalyzer: false, // 在默认浏览器中是否自动打开报告,默认 true
                    generateStatsFile: false, // 如果为true,则Webpack Stats JSON文件将在bundle输出目录中生成
                    statsFilename: 'stats.json', // 相对于捆绑输出目录
                    statsOptions: null, //stats.toJson()方法的选项。例如,您可以使用source:false选项排除统计文件中模块的来源。在这里查看更多选项:https://github.com/webpack/webpack/blob/webpack-1/lib/Stats.js#L21
                    logLevel: 'info', // 日志级别,可以是info, warn, error, silent
                    excludeAssets:null, // 用于排除分析一些文件
                })
            )
    }
};
plugins: [
	
]

在执行nom run dev 或 npm run build命令,生成分析报告

image.png

3. gzip压缩

下载插件 compression-webpack-plugin (注意版本:可能会版本不匹配而报错)

npm install --save-dev compression-webpack-plugin@1.1.12
const CompressionWebpackPlugin = require('compression-webpack-plugin')
const productionGzipExtensions = ['js','css'] ;

module.exports = {
    configureWebpack: (config) => {
           config.plugins.push(
               new CompressionWebpackPlugin({
                    filename: '[path].gz[query]',
                    algorithm: 'gzip',
                    test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
                    threshold: 10240,
                    minRatio: 0.8,
                    deleteOriginalAssets: true
                }),
           )
           config.output.filename = `system/[name].js`  //打包生成的文件(可以改变路径用于分类)
           config.output.chunkFilename = `system/[name].js`
    }
}

分类后的效果:

image.png

4. 公共文件CDN

需要在两个地方配置:vue.config.js、index.html

vue.config.js文件中编辑配置,externals指的是排除以下依赖包的打包。vue等依赖包是公共基础。
注意引入后变量的使用,注意externals对象中值的书写规则,如element-ui,必须使用大写的ELEMENT变量来引用

可以上官网自己找自己项目需要的:www.bootcdn.cn/

module.exports = {
    configureWebpack: (config) => {
           config.externals = { 
                vue: 'Vue',
                'vue-router': 'VueRouter',
                axios: 'axios',
                "element-ui": "ELEMENT",
                "moment": "moment",
                'vuex': 'Vuex',
                'echarts': 'echarts'
            }
    }
}
<!DOCTYPE html>
<html lang="en">

<head>
</head>

<body>
    <div id="app"></div>
    //可以进行判断
    <% if (NODE_ENV === 'xxx') { %>
      <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.min.js"></script>
      <script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.5.1/vue-router.min.js"></script>
      <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
      <script src="https://cdn.bootcdn.net/ajax/libs/vuex/3.6.2/vuex.min.js"></script>
      <script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.1/index.js"></script>
      <script src="https://cdn.bootcdn.net/ajax/libs/echarts/4.9.0-rc.1/echarts.min.js"></script>
    <% } %> 
</body>

</html>

image.png

也可以自己下载cdn到自己的项目中,例如我放在了public/static/cdn文件夹下:

image.png

<!DOCTYPE html>
<html lang="en">

<head>
</head>

<body>
    <div id="app"></div>
    //可以进行判断
    <% if (NODE_ENV === 'xxx') { %>
     <script src="/static/cdn/vue.min.js"></script>
      <script src="/static/cdn/vue-router.min.js"></script>
      <script src="/static/cdn/axios.min.js"></script>
      <script src="/static/cdn/vuex.min.js"></script>
      <script src="/static/cdn/element-index.js"></script>
      <script src="/static/cdn/echarts.min.js"></script>
    <% } %> 
</body>

</html>
5. html-webpack-plugin压缩html代码

将 webpack中entry配置的相关入口chunk 和 extract-text-webpack-plugin抽取的css样式 插入到该插件提供的template或者templateContent配置项指定的内容基础上生成一个html文件,具体插入方式是将样式link插入到head元素中,script插入到head或者body

下载插件:

npm install html-webpack-plugin@4.5.0 -D

如果没有具体配置可以不进行配置

const HtmlPlugin =require('html-webpack-plugin') ; 
 
module.exports = {
    configureWebpack: (config) => {
           config.plugins.push(
                new HtmlPlugin({
                    // template:'./src/index.html', //指定源文件的存放路径
                    // filename: './html/index.html', //指定生成文件的存放路径
                    //template: path.join(__dirname, 'default_index.ejs'),
                    //filename: 'index.html', 
                    //hash: false, 
                    //inject: true, 
                    //compile: true, 
                    //favicon: false, 
                    //minify: false, 
                    //cache: true, 
                    //showErrors: true, 
                    //chunks: 'all', 
                    //excludeChunks: [], 
                    //title: 'Webpack App', 
                    //xhtml: false
                }),
           )
    }
}

image.png

最后附上全部代码:

vue.config.js文件

const CompressionWebpackPlugin = require('compression-webpack-plugin') // npm install --save-dev compression-webpack-plugin@1.1.12 npm下载
const productionGzipExtensions = ['js','css'] ;
const HtmlPlugin =require('html-webpack-plugin') ; 
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;


module.exports = {
    publicPath: "./",
    assetsDir: './static',
    productionSourceMap: false,
    devServer: {
        open: true,
        disableHostCheck: false,
        host: "0.0.0.0",
        port: 3002,
        https: false,
        hotOnly: true,
    },
    configureWebpack: (config) => {
        // 在这里配置后,减少了压缩的包内容,需要在public/index.html通过cdn方式再引入,注意对应的版本
        if (process.env.NODE_ENV === 'qa') {
            config.plugins.push(
                new CompressionWebpackPlugin({
                    filename: '[path].gz[query]',
                    algorithm: 'gzip',
                    test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
                    threshold: 10240,
                    minRatio: 0.8,
                    deleteOriginalAssets: true
                }),
                new HtmlPlugin({}),
                new BundleAnalyzerPlugin()
            )
            config.output.filename = `system/[name].js`  //打包生成的文件
            config.output.chunkFilename = `system/[name].js`
            config.externals = { 
                vue: 'Vue',
                'vue-router': 'VueRouter',
                axios: 'axios',
                "element-ui": "ELEMENT",
                "moment": "moment",
                'vuex': 'Vuex',
                'echarts': 'echarts'
            }
        }
    }
};

index.html文件

<!DOCTYPE html>
<html lang="en">

<head>
</head>

<body>
    <div id="app"></div>
    //可以进行判断
    <% if (NODE_ENV === 'qa') { %>
     <script src="/static/cdn/vue.min.js"></script>
      <script src="/static/cdn/vue-router.min.js"></script>
      <script src="/static/cdn/axios.min.js"></script>
      <script src="/static/cdn/vuex.min.js"></script>
      <script src="/static/cdn/element-index.js"></script>
      <script src="/static/cdn/echarts.min.js"></script>
    <% } %> 
</body>

</html>

打包完生成.gz文件

记得在nginx修改配置

#gzip on;
gzip on;
gzip_static on; # 开启静态文件压缩
gzip_buffers 32 4K;
gzip_comp_level 6;
gzip_min_length 100;
gzip_types application/javascript text/css text/xml;
gzip_disable “MSIE [1-6].”; #配置禁用gzip条件,支持正则。此处表示ie6及以下不启用gzip(因为ie低版本不支持)
gzip_vary on;

gzip_static on; 很重要一定要加上

至此,dist包的瘦身计划已经完成,dist包从35m降到了2m内;因为已经达到了项目的要求,所以就这样了。有问题的话欢迎大家在评论区讨论。