vue項目性能優(yōu)化方案

背景
項目采用vue cli3搭建逛漫,集成前端組件以及地圖效果黑低,導致項目打包后資源包文件特別大,打包速度慢酌毡,首屏渲染耗時長克握,甚至出現(xiàn)左右界面圖表數(shù)據(jù)不渲染的問題。

優(yōu)化前準備
首先我們需要先排查影響性能枷踏、導致打包資源文件過大的原因菩暗,以及代碼的使用率

  • webpack-bundle-analyzer:
npm install webpack-bundle-analyzer

// vue.config.js文件(vue cli3根目錄下的文件,如果沒有旭蠕,可創(chuàng)建此文件停团,用于webpack配置)

module.exports = {
    chainWebpack: config => {
        /* 添加分析工具 */
        if (process.env.NODE_ENV === 'production') {
            if (process.env.npm_config_report) {
                config
                    .plugin('webpack-bundle-analyzer')
                    // eslint-disable-next-line global-require
                    .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
                    .end();
                config.plugins.delete('prefetch');
            }
        }
    },
};

通過命令 npm run build --report 會在打包完成后本地啟動一個服務,自動打開127.0.0.1:8888網(wǎng)頁掏熬,可以查看打包后各個依賴包占用的資源大小佑稠,我們可以針對各個依賴包的相關大小作出體積的優(yōu)化,如果開源庫過大可以考慮按需引入旗芬,不要全部引入舌胶,如果是自己公司封裝的私有組件庫、類庫疮丛,可以排查哪部分占用文件過大幔嫂,打包進行優(yōu)化處理,如下圖:

在這里插入圖片描述

在這里插入圖片描述
  • coverage:
    通過打開控制臺(F12)誊薄,ctrl+shift+p履恩,搜索coverage,然后選中暇屋,然后點擊開始錄制似袁,之后做一些操作洞辣,比如刷新界面咐刨,開始錄制昙衅,查看我們代碼的實際使用率,也可以點擊文件查看這個文件中具體未使用的那段代碼(紅色部分)


    在這里插入圖片描述
    在這里插入圖片描述

    優(yōu)化方案:

  • gzip壓縮:gzip壓縮可以特別明顯的提高我們的代碼加載效果定鸟,提升效率5-6倍左右而涉,它會把諸如js、css等文件進行壓縮联予,并且讓我們在加載時去請求那些gz文件而提升請求效率啼县,這部分可以參考博主的另一篇文章 gzip壓縮方案

  • 路由懶加載:實際來說,我們在首頁就不需要加載其他路由的文件以及數(shù)據(jù)沸久,而當我們執(zhí)行到某個具體路由季眷,再去加載當前路由的才是最正確的方案,所以路由懶加載是我們必須要做的卷胯,使用方法如下:

這里拿home路由舉例子刮,博主每個頁面都是分為左、右窑睁、中上挺峡、中下四個模塊的,所以每個路由中都有四個組件担钮,當然橱赠,路由懶加載寫法是一樣的,通過箭頭函數(shù)返回一個組件箫津,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,
            },
        },
]

開啟路由懶加載后,vue cli3項目還需要在vue.config.js文件中配置如下

// vue.config.js文件(vue cli3根目錄下的文件暖眼,如果沒有惕耕,可創(chuàng)建此文件,用于webpack配置)
module.exports = {
    chainWebpack: config => {
        // 移除 prefetch 插件(避免會預先加載模塊/路由)
        config.plugins.delete('prefetch');
    },
};

(注:之前博主遇到個小坑诫肠,項目中有個文件夾司澎,里面寫了一些全局封裝并且全局注冊的組件供其他頁面使用,而有些組件中使用了require去動態(tài)加載圖片導致打包后路由懶加載不生效沒有生成對應路由的文件栋豫,大家留意一下即可挤安,如果遇到此問題,可以找博主提供解決思路)

  • 組件庫按需引入:這一點不需要過多贅述了丧鸯,使用了諸如element ui等組件庫的話蛤铜,官網(wǎng)都有很詳細的介紹如何按需加載
  • 圖片壓縮:安裝此插件的時候有可能出現(xiàn)部分依賴安裝失敗,導致壓縮失敗,可以先卸載此插件然后用cnpm或淘寶源重新安裝
npm install image-webpack-loader

// vue.config.js文件(vue cli3根目錄下的文件围肥,如果沒有剿干,可創(chuàng)建此文件,用于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打包后會把依賴包都打包到app.js文件里朵锣,這樣會導致單文件過大谬盐,請求耗時,加載緩慢诚些,所以可以考慮把各依賴單獨拆分打包设褐,實現(xiàn)多個小文件請求加載的方式,代碼如下:
// vue.config.js文件(vue cli3根目錄下的文件泣刹,如果沒有助析,可創(chuàng)建此文件,用于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掀泳,命名可以自定義雪隧。

  • 重復引用依賴包:封裝了一個公共組件庫(可通過npm下載),但是臨時為了省事項目中也封裝了一些組件單獨放在一個文件夾中员舵,最終一些相同的依賴就會被重復引用脑沿,比如組件庫中用了amcharts圖表,而項目中又安裝使用了這個圖表庫马僻,會導致此依賴被重復引用庄拇,解決方案:把項目中的組件挪到組件庫中,這樣同一份依賴就只會被使用一次韭邓。(不過我記得webpack有配置可以針對同一依賴多次引用的處理措近,把依賴進行緩存,避免被多次引用女淑,感興趣的童鞋可以去查閱下相關資料)
  • fps:之前項目中封裝了一個方法瞭郑,針對數(shù)據(jù)請求多的情況,做了fps處理鸭你,如果fps小于30就先不執(zhí)行數(shù)據(jù)請求屈张,先等現(xiàn)有數(shù)據(jù)擒权、界面、地圖等渲染完畢阁谆,fps穩(wěn)定后再去執(zhí)行下一部分數(shù)據(jù)請求碳抄、界面渲染,本身是為了能更好更流暢的渲染笛厦,但是如果電腦性能本身就很差纳鼎,fps本身就很低俺夕,會導致一直數(shù)據(jù)不渲染(哈哈哈裳凸,給自己埋了個坑),最終定位問題后發(fā)現(xiàn)了這段不合理的處理劝贸。大家寫代碼也要多注意這些情況姨谷。

完整的vue.config.js配置:

const fs = require('fs');
const CompressionPlugin = require('compression-webpack-plugin');

let devServer = {};
if (fs.existsSync('./dev-config.js')) {
    // eslint-disable-next-line global-require
    devServer = require('./dev-config');
} else {
    console.error('!!!please create the dev-config.js file from dev-config-template.js');
}

module.exports = {
    lintOnSave: true,
    productionSourceMap: true,
    chainWebpack: config => {
        // 移除 prefetch 插件(避免會預先加載模塊/路由)
        config.plugins.delete('prefetch');
        // Loader
        config.module
            .rule('svg')
            .test(/\.(swf|ttf|eot|svg|woff(2))(\?[a-z0-9]+)?$/)
            .use('file-loader')
            .loader('file-loader')
            .end();
        // 開啟圖片壓縮
        // config.module
        //     .rule('images')
        //     .test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
        //     .use('image-webpack-loader')
        //     .loader('image-webpack-loader')
        //     .options({ bypassOnDebug: true });
        /* 添加分析工具 */
        if (process.env.NODE_ENV === 'production') {
            if (process.env.npm_config_report) {
                config
                    .plugin('webpack-bundle-analyzer')
                    // eslint-disable-next-line global-require
                    .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
                    .end();
                config.plugins.delete('prefetch');
            }
        }
    },
    devServer,
    configureWebpack: {
        resolve: {
            alias: {
                src: '@',
                components: '@/components',
                views: '@/views',
            },
        },
        plugins: [
            new CompressionPlugin({
                algorithm: 'gzip', // 使用gzip壓縮
                test: /\.js$|\.html$|\.css$/, // 匹配文件名
                filename: '[path].gz[query]', // 壓縮后的文件名(保持原文件名,后綴加.gz)
                minRatio: 1, // 壓縮率小于1才會壓縮
                threshold: 10240, // 對超過10k的數(shù)據(jù)壓縮
                deleteOriginalAssets: false, // 是否刪除未壓縮的源文件映九,謹慎設置梦湘,如果希望提供非gzip的資源,可不設置或者設置為false(比如刪除打包后的gz后還可以加載到原始資源文件)
            }),
        ],
        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('@', '')}`;
                        },
                    },
                },
            },
        },
    },
};

好了件甥,以上就是博主自身項目中關于性能優(yōu)化的一些處理捌议,大家可以參考下。

如有問題引有,請指出瓣颅,接收批評。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末譬正,一起剝皮案震驚了整個濱河市宫补,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌曾我,老刑警劉巖粉怕,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異抒巢,居然都是意外死亡贫贝,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門蛉谜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來平酿,“玉大人,你說我怎么就攤上這事悦陋◎诒耍” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵俺驶,是天一觀的道長幸逆。 經(jīng)常有香客問我棍辕,道長,這世上最難降的妖魔是什么还绘? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任楚昭,我火速辦了婚禮,結果婚禮上拍顷,老公的妹妹穿的比我還像新娘抚太。我一直安慰自己,他們只是感情好昔案,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布尿贫。 她就那樣靜靜地躺著,像睡著了一般踏揣。 火紅的嫁衣襯著肌膚如雪庆亡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天捞稿,我揣著相機與錄音又谋,去河邊找鬼。 笑死娱局,一個胖子當著我的面吹牛彰亥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播衰齐,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼任斋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了娇斩?” 一聲冷哼從身側響起仁卷,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎犬第,沒想到半個月后锦积,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡歉嗓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年丰介,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鉴分。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡哮幢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出志珍,到底是詐尸還是另有隱情橙垢,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布伦糯,位于F島的核電站柜某,受9級特大地震影響嗽元,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜喂击,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一剂癌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧翰绊,春花似錦佩谷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至秤茅,卻和暖如春稚补,著一層夾襖步出監(jiān)牢的瞬間童叠,已是汗流浹背框喳。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留厦坛,地道東北人五垮。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像杜秸,于是被迫代替她去往敵國和親放仗。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容