前言
- 這段時間,本人自己做了一個vue畫面部署到自己的服務器上,發現運行速度慢的的驚人,雖然服務器很渣(本人沒什么錢,只能租最差的服務器,主要是給自己學習用的),但是這樣開發出來的網站簡直不能用,所以就查閱各種資料和網站,一步一步把代碼包優化。這篇文章主要是把我調優的過程記錄下來。
- 項目的基礎框架是通過TypeScript官網取得的。各種基礎框架模版
- 項目的構成 vue + ant-design + mysql + TypeScript
- vue項目地址
- 最后,關於如何在vue里面實現按需加載,請自行查閱相關資料。以及,webpack的基礎知識本文也不做介紹,可以參照我github的 學習筆記
- [原文地址](http://shenxf.top/2019/05/16/20190516-vueSpeedUp/)
調優過程
- 禁用webpack的devtools
- 打包出來的js文件非常大,每個js文件竟然達到了3~4Mbs,這樣的體積對於我的服務帶寬來說根本負擔不起。打開畫面必卡。
- 究其原因,是因為webpack里面啟用了sourceMap,以便於調試。但是這在發布以后就完全沒有用了。
- webpack配置,里面有這句話,把這句話注釋掉。原本3~4Mbs的文件,變成了1Mbs文件。壓縮了3倍以上。
-
// 啟用sourceMap devtool: '#source-map'
- 抽離css樣式等
-
這個雖然對於改善效果不明顯,但是好的分類對於發現問題的本質有很大的幫助。另外,css樣式分離后要自己進行壓縮。
// *************webpack需要引入的包************************* // 抽離css樣式 let MiniCssExtractPlugin = require('mini-css-extract-plugin'); // 用來壓縮分離出來的css樣式 let OptimizeCss = require('optimize-css-assets-webpack-plugin'); // 用來壓縮js let UglifyJsPlugin = require('uglifyjs-webpack-plugin'); // *************webpack相關配置部分************************* module.exports = { optimization: { // 優化項 minimizer: [ new OptimizeCss(), // 壓縮css new UglifyJsPlugin({ // 壓縮js cache: true, // 是否用緩存 parallel: true, // 並發打包 sourceMap: false, // es6 -> es5 轉換時會用到 }), ], } // 中間部分省略 // 抽離css樣式 plugins: [ new MiniCssExtractPlugin({ filename: 'css/[name].css', // 抽離出來樣式的名字 }), ], }
- 啟用依賴關系可視化工具
-
完成上面工作之后,陷入了茫然,網站還是很卡,不知道還能怎么調優,在翻閱了很多網站資料以后,發現了一個依賴關系可視化工具,這對於我來說是一個重大的突破口
// 依賴關系可視化 // *************webpack需要引入的包************************* const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); // *************webpack相關配置部分************************* module.exports = { // 啟動依賴關系可視化窗口,綁定端口8919 plugins: [ new BundleAnalyzerPlugin({ analyzerPort: 8919 }), ], }
-
通過這個效果圖可以很明顯的看出js文件里面包含什么依賴,我就是通過這個線索來進行優化的。
- 抽離共通部分
-
為了方便我調查,我把共通的依賴部分都抽離出來了。而這個功能是webpack4自帶的,如果是之前或者更早版本的webpack,需要引入第三方組件
CommonsChunkPlugin
這里不做介紹。module.exports = { optimization: { //打包 公共文件 splitChunks: { cacheGroups: { vendor: { //node_modules內的依賴庫 chunks: 'all', test: /[\\/](node_modules)[\\/]/, // 文件路徑里面帶有node_modules 都抽離出來做共通 name: 'vendor', minChunks: 1, //被不同entry引用次數(import),1次的話沒必要提取 maxInitialRequests: 5, minSize: 0, priority: 100, // enforce: true? }, common: { // ‘src/js’ 下的js文件 chunks: 'all', test: /[\\/]src[\\/]js[\\/]/, //也可以值文件/[\\/]src[\\/]js[\\/].*\.js/, name: 'common', //生成文件名,依據output規則 minChunks: 2, maxInitialRequests: 5, minSize: 0, priority: 1, }, }, }, runtimeChunk: { name: 'manifest', }, } }
-
一開始我對於這個屬性的名字難以理解,以至於沒有效果,看了下面的文章后全明白了。
- 分析包大小問題
- 從上面的依賴效果圖可以明顯的看出,有幾個包特別大,特別顯眼
- ant-design的Icons文件
- moment文件
- quill文件
- highlight.js文件
- ant-design的Icons文件優化
- 這是ant-design的一個問題
- 而關於上面的問題,我建議你們直接看鏈接最下面的部分。(上面的一群人聊了半天,不知所以然,各種鏈接來回跳,也沒找到結果)
- 核心的幾句話。
JS解決方案
TS解決方案
- 通過了自己的理解,一個要自己引入相應的Icon,另一個是要在webpack里面進行配置
-
增加antdIcon.ts代碼,引入相應的Icon
// 自己項目里面用到的Icon export { default as FileOutline, } from '@ant-design/icons/lib/outline/FileOutline'; // antd的message組建內部用到的Icon 把源代碼復制過來。 // var iconType = { // info: 'info-circle', // success: 'check-circle', // error: 'close-circle', // warning: 'exclamation-circle', // loading: 'loading' // }[args.type] // message info export { default as InfoCircleTwoTone, } from '@ant-design/icons/lib/twotone/InfoCircleTwoTone'; // message success export { default as CheckCircleTwoTone, } from '@ant-design/icons/lib/twotone/CheckCircleTwoTone'; // message error export { default as CloseCircleTwoTone, } from '@ant-design/icons/lib/twotone/CloseCircleTwoTone'; // message warning export { default as ExclamationCircleTwoTone, } from '@ant-design/icons/lib/twotone/ExclamationCircleTwoTone'; // message loading export { default as LoadingOutline, } from '@ant-design/icons/lib/outline/LoadingOutline';
-
修改 webpack 配置
module.exports = { resolve: { modules: [path.resolve(__dirname, './src'), 'node_modules'], // <- 追加代碼 extensions: ['.ts', '.js', '.vue', '.json'], // <- 追加代碼 alias: { vue$: 'vue/dist/vue.esm.js', '@ant-design/icons/lib/dist$': path.resolve(__dirname, './src/tools/antdIcon.ts'), // <- 追加代碼 }, plugins: [ // <- 追加代碼 new TsconfigPathsPlugin({ configFile: path.resolve(__dirname, './tsconfig.json'), }), ], },
- moment文件優化
- 這是個Ant-design內部依賴的語言文件,我的程序里面本身沒有引用,我主要用到的是里面的中文,所以,中文以外的我全部在webpack里面設置忽略就行了
module.exports = { plugins: [ // 只讀取(zh-cn)文件。 new webpack.ContextReplacementPlugin(/moment[\\\/]locale$/, /^\.\/(zh-cn)$/), ], }
- quill文件優化
-
這個是我用到的富文本功能,本身對這個組件不太了解,但又必須要用到,也沒什么太好優化方法,索性,把它抽離成一個單獨的共通JS文件,這樣起碼有2個組建同時調用這個富文本的情況下,只有第一個掉用的那個需要引入JS文件,第二次的那個會直接利用瀏覽器的緩存來調用這個JS文件的,也有一定程度的優化效果。
-
所以我修改了抽離共通組件的那部分代碼
module.exports = { optimization: { splitChunks: { cacheGroups: { vendor: { chunks: 'all', test: /[\\/](quill)[\\/]/, // <- 就是簡單修改了下匹配規則 name: 'vendor', minChunks: 1, maxInitialRequests: 5, minSize: 0, priority: 100, }, common: { chunks: 'all', test: /[\\/]src[\\/]js[\\/]/, name: 'common', minChunks: 2, maxInitialRequests: 5, minSize: 0, priority: 1, }, }, }, runtimeChunk: { name: 'manifest', }, } }
- highlight.js文件優化
- 這個主要是我用markdown編輯器的時候,用來給文字着色的。沒有這個,在編寫markdown的時候,內容非常的丑陋。
- 但是這個東西的語法太多了,導致這個包非常的大,我編寫的時候,只需要利用其中的幾種情況而已,我先隨便定幾種情況,反正是自己的項目,有不夠的以后隨時再追加(正式項目的話請做好調研)
-
// 按需加載的寫法 import hljs from 'highlight.js/lib/highlight'; import javascript from 'highlight.js/lib/languages/javascript'; hljs.registerLanguage('javascript', javascript);
-
至此,我覺得以我現在的水平代碼已經沒有什么好調整了,main文件還是有點大,我也已經盡力了。
- 服務開啟Gzip代碼壓縮
- 我用的是nginx服務器,它可以開啟Gzip,代碼壓縮率非常可觀。200k文件直接被它壓縮到幾十k。
-
原本還有點小卡的網站,在啟用了Gzip之后,變得一點也不卡了。
-
修改nginx配置,這里有個小的坑(最后還給我來一個坑),隨便找個網站復制下,大致都長下面這樣,最后要重啟nginx服務,讓它讀取最新配置
nginx -s reload
。如果你用的是docker
請輸入docker exec -it 容器名字 service nginx reload
gzip on; gzip_min_length 5k; gzip_buffers 4 16k; #gzip_http_version 1.0; gzip_comp_level 3; gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; gzip_vary on;
-
坑在哪里?你自己看吧,說出來都是淚啊坑
-
Gzip有啥缺點? 我也不太清楚,第一應該是它不支持IE6以及IE6以下的瀏覽器。還有人說他不利於SEO,但也有人說他利於SEO,是真是假去問百度。網上大部分人覺的他的優點大於缺點。
-
謝謝大家。