Vue性能优化

作者: 老鼠AI大米_Java全栈 | 来源:发表于2021-03-04 10:23 被阅读0次

    使用vuecli打包项目,有一些文件会较大,在互联网上加载会很慢,下面分享一些优化心得。

    打包文件分析

    使用chrome控制台查看

    使用chrome控制台查看加载文件时长及大小,文件越大加载时间越长。


    image.png

    从这里可以清楚看到加载的文件,大小,时间等。
    接着,咱们分析下这个文件变大的原因,其实开发的代码并不大。

    文件分析

    使用插件webpack-bundle-analyzer分析打包文件中的具体文件组成。

    npm install webpack-bundle-analyzer
    // vue.config.js文件(vue cli3根目录下的文件,如果没有,可创建此文件,用于webpack配置)
    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
    module.exports = {
        configureWebpack: config =>{
            let plugins = [
                new CompressionWebpackPlugin({
                    algorithm: 'gzip', //压缩方式
                    test: productionGzipExtensions, //匹配压缩文件
                    threshold: 2048  //对大于10k压缩
                }),
                new BundleAnalyzerPlugin()
            ]
            if (process.env.NODE_ENV === 'production') {
                config.mode = "production";
                config.plugins = [...config.plugins, ...plugins]
            }else{
                config.mode = "development"
            }
            Object.assign(config, {
                externals: {
                    vue: 'Vue',  //import的名字
                    element: 'ElementUI',  //import的名字  在main.js中把相关引入注释掉(注释与否都可以)
                    'element-ui': 'element-ui',
                    "mavon-editor": "MavonEditor",
                    axios: 'axios',
                    echarts: 'echarts',
                    'vue-router':'VueRouter',
                    vuex: 'Vuex',
                    'crypto-js': 'CryptoJS'
                }
            })
        }
    };
    
    

    通过命令 npm run build 会在打包完成后本地启动一个服务,自动打开127.0.0.1:8888网页,可以查看打包后各个依赖包占用的资源大小,我们可以针对各个依赖包的相关大小作出体积的优化,如果开源库过大可以考虑按需引入,不要全部引入,如果是自己公司封装的私有组件库、类库,可以排查哪部分占用文件过大,打包进行优化处理,如下图:

    image.png

    优化方案

    gzip压缩

    gzip压缩可以特别明显的提高我们的代码加载效果,提升效率5-6倍左右,它会把诸如js、css等文件进行压缩,并且让我们在加载时去请求那些gz文件而提升请求效率。

    const CompressionPlugin = require('compression-webpack-plugin');
    ...
    plugins: [
                new CompressionPlugin({
                    algorithm: 'gzip', // 使用gzip压缩
                    test: /\.js$|\.html$|\.css$/, // 匹配文件名
                    filename: '[path].gz[query]', // 压缩后的文件名(保持原文件名,后缀加.gz)
                    minRatio: 1, // 压缩率小于1才会压缩
                    threshold: 10240, // 对超过10k的数据压缩
                    deleteOriginalAssets: false, // 是否删除未压缩的源文件,谨慎设置,如果希望提供非gzip的资源,可不设置或者设置为false(比如删除打包后的gz后还可以加载到原始资源文件)
                }),
            ],
    

    路由懒加载

    实际来说,我们在首页就不需要加载其他路由的文件以及数据,而当我们执行到某个具体路由,再去加载当前路由的才是最正确的方案,所以路由懒加载是我们必须要做的,使用方法如下:

    这里拿home路由举例,博主每个页面都是分为左、右、中上、中下四个模块的,所以每个路由中都有四个组件,当然,路由懒加载写法是一样的,通过箭头函数返回一个组件,webpackChunkName就是最早的打包后的文件名,同一路由可以写同一个名字,推荐写路由名,方便我们知道是哪个路由下的。

    const MainLeft = () => import(/* webpackChunkName: "Home" */ '../components/Home/MainLeft.vue');
    const MainRight = () => import(/* webpackChunkName: "Home" */ '../components/Home/MainRight.vue');
    const MainCenterTop = () => import(/* webpackChunkName: "Home" */ '../components/Home/MainCenterTop.vue');
    const MainCenterBottom = () => import(/* webpackChunkName: "Home" */ '../components/Home/MainCenterBottom.vue');
    

    而在router.js里就是正常写法:

    routes: [
            {
                path: '/',
                name: 'Home',
                title: '首页',
                components: {
                    routerLeft: Home.MainLeft,
                    routerRight: Home.MainRight,
                    routerCenterTop: Home.MainCenterTop,
                    // routerCenterBottom: Home.MainCenterBottom,
                },
            },
    ]
    

    图片压缩

    npm install image-webpack-loader
    
    // vue.config.js文件(vue cli3根目录下的文件,如果没有,可创建此文件,用于webpack配置)
    module.exports = {
        chainWebpack: config => {
            // 开启图片压缩
            config.module
                 .rule('images')
                 .test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
                 .use('image-webpack-loader')
                 .loader('image-webpack-loader')
                 .options({ bypassOnDebug: true });
        },
    };
    

    关闭map映射文件

    vue打包会保留源文件的map映射,方便我们打包部署后依然可以通过控制台的source查看搜索源文件的代码,方便定位问题,但是多生成map文件会导致打包文件过大,所以仁者见仁智者见智,看各位是否需要打包部署后方便定位问题吧,不需要的话可以考虑不生成map文件。

    module.exports = {
        productionSourceMap: true,
    }
    

    拆分三方包

    将一些三方包拆出来,如vue,echarts等都很大,拆出来后直接在页面加载更利于缓存。

    configureWebpack: config =>{
            let plugins = [
                new CompressionWebpackPlugin({
                    algorithm: 'gzip', //压缩方式
                    test: productionGzipExtensions, //匹配压缩文件
                    threshold: 2048  //对大于10k压缩
                })
            ]
            if (process.env.NODE_ENV === 'production') {
                config.mode = "production";
                config.plugins = [...config.plugins, ...plugins]
            }else{
                config.mode = "development"
            }
            Object.assign(config, {
                externals: {
                    vue: 'Vue',  
                    element: 'ElementUI', 
                    echarts: 'echarts'
                }
            })
        }
    

    拆出这些三方包后,打包文件会明显变小,但需要在html页面上显示引入三方包,如下:

    <!-- 生产环境版本,优化了尺寸和速度 -->
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    

    分包加载

    vue打包后会把依赖包都打包到app.js文件里,这样会导致单文件过大,请求耗时,加载缓慢,所以可以考虑把各依赖单独拆分打包,实现多个小文件请求加载的方式,代码如下:

    // vue.config.js文件(vue cli3根目录下的文件,如果没有,可创建此文件,用于webpack配置)
    module.exports = {
        configureWebpack: {
            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('@', '')}`;
                            },
                        },
                    },
                },
            },
        },
    };
    

    上述代码会把所有的包括异步请求的模块分割,针对大于20000k的文件,最终命名方式是npm.依赖包.js文件,比如npm.echarts.js,命名可以自定义。

    以上就是一些常用的优化方案,希望对大家有帮助。

    相关文章

      网友评论

        本文标题:Vue性能优化

        本文链接:https://www.haomeiwen.com/subject/ylihqltx.html