以前用vuecli
作了個博客,是一個單頁面項目,大概有十個路由
直接npm run build
打包出來,有一個1M
的巨大js
文件css
先掛載到服務器上試試
好傢伙 這加載時間 彷彿過了半個世紀html
首屏頁面整整加載了9s
光加載那個大文件就花了8s
這必須得作個優化了,沒有用戶能忍受9s
的白屏而不關閉頁面的vue
過程當中,我還順便把項目從vuecli 2.x
遷移到了vuecli 3
,因此接下來還會介紹一些它們在優化上的異同webpack
vuecli 2.x
自帶了分析工具
只要運行npm run build --report
web
若是是vuecli 3
的話,先安裝插件vue-cli
cnpm intall webpack-bundle-analyzer –save-dev
而後在vue.config.js
中對webpack
進行配置express
chainWebpack: (config) => { /* 添加分析工具*/ if (process.env.NODE_ENV === 'production') { if (process.env.npm_config_report) { config .plugin('webpack-bundle-analyzer') .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin) .end(); config.plugins.delete('prefetch') } } }
再運行npm run build --report
npm
會在瀏覽器打開一個項目打包的狀況圖,便於直觀地比較各個bundle
文件的大小element-ui
能夠看到 項目中全部的依賴,全部的路由,都被打包進了同一個文件中瀏覽器
另外,在瀏覽器中,也能夠經過converge
來查看代碼的使用情況
紅色的是下載了但未使用的部分
當打包構建應用時,JavaScript包會變得很是大,影響頁面加載。
若是咱們能把不一樣路由對應的組件分割成不一樣的代碼塊,而後當路由被訪問的時候才加載對應組件,這樣就更加高效了。
在一開始就下載完全部路由對應的組件文件,這明顯是不合適的,這就像下載一個app
了,因此咱們就須要使用路由懶加載
在router.js
文件中,原來的靜態引用方式
import ShowBlogs from '@/components/ShowBlogs' routes:[ path: 'Blogs', name: 'ShowBlogs', component: ShowBlogs ]
改成
routes:[ path: 'Blogs',name: 'ShowBlogs',component: () => import('./components/ShowBlogs.vue')
以函數的形式動態引入,這樣就能夠把各自的路由文件分別打包,只有在解析給定的路由時,纔會下載路由組件
首屏須要加載的文件變成了橙色的部分,被小弟們分流出去了300k
若是是在vuecli 3
中,咱們還須要多作一步工做
由於vuecli 3
默認開啓prefetch
(預先加載模塊),提早獲取用戶將來可能會訪問的內容
在首屏會把這十幾個路由文件,都一口氣下載了
因此咱們要關閉這個功能,在vue.config.js
中設置
參考官網的作法:
設置完畢後,首屏就只會加載當前頁面路由的組件了
首屏須要加載的依賴包,其中element-ui
整整佔了568k
本來的引進方式引進了整個包:
import ElementUI from 'element-ui' Vue.use(ElementUI)
但實際上我用到的組件只有按鈕,分頁,表格,輸入與警告
因此咱們要按需引用:
import { Button, Input, Pagination, Table, TableColumn, MessageBox } from 'element-ui'; Vue.use(Button) Vue.use(Input) Vue.use(Pagination) Vue.prototype.$alert = MessageBox.alert
注意MessageBox
註冊方法的區別,而且咱們雖然用到了alert
,但並不須要引入Alert
組件
在.babelrc
文件中添加(vue-cli 3
要先安裝babel-plugin-component
):
plugins: [ [ "component", { "libraryName": "element-ui", "styleLibraryName": "theme-chalk" } ] ]
element-ui
小了不少,不過看到那個顯眼的table.js
後想到,table
組件只有後臺管理頁面用到了,不須要全局註冊,因此咱們刪除main.js
中Table
和TablColumn
的引用,並在後臺組件中局部註冊
import { Table, TableColumn } from "element-ui"; components: { "el-table": Table, "el-table-column": TableColumn },
table
就被拆分到了路由文件中
能夠看到上圖,有兩個路由文件都引用了codemirror.js
形成重複下載
咱們能夠在webpack
的config
文件中,修改CommonsChunkPlugin
的配置
minChunks: 3
把3改成2,就會把使用2次及以上的包抽離出來,放進公共依賴文件,不過因爲首頁也有複用的組件,因此首頁也會下載這個公共依賴文件
首頁下載了黃色和灰色部分
拆了半天,又回到原點
固然,咱們能夠繼續折騰CommonsChunkPlugin
的配置來解決這個問題
但在新版webpack
中,CommonsChunkPlugin
被自由度更高,更高級的SplitChunksPlugin
代替
這也是爲何我要把項目遷移到vuecli 3
(使用webpack4
)
默認就作了優化,首頁只會下載灰色的部分(235K
)
拆完包以後,咱們再用gzip
作一下壓縮
安裝compression-webpack-plugin
cnmp i compression-webpack-plugin -D
在vue.congig.js
中引入並修改webpack
配置
const CompressionPlugin = require('compression-webpack-plugin') configureWebpack: (config) => { if (process.env.NODE_ENV === 'production') { // 爲生產環境修改配置... config.mode = 'production' return { plugins: [new CompressionPlugin({ test: /\.js$|\.html$|\.css/, //匹配文件名 threshold: 10240, //對超過10k的數據進行壓縮 deleteOriginalAssets: false //是否刪除原文件 })] } }
能夠看到200k
以上的文件被壓縮到了100k
之內
在服務器咱們也要作相應的配置
若是發送請求的瀏覽器支持gzip
,就發送給它gzip
格式的文件
個人服務器是用express
框架搭建的
只要安裝一下compression
就能使用
const compression = require('compression') app.use(compression())
注意,後面這一句,要放在全部其餘中間件註冊以前
首屏加載資源198k,加載時間1s,相比原來速度提高了90%
vuecli 3
和vuecli2.x
還有一個區別是vuecli 3
會默認開啓一個css
分離插件 ExtractTextPlugin
每個模塊的css
文件都會分離出來,整整13個css
文件,而咱們的首頁就請求了4個,花費了很多的資源請求時間
咱們能夠在vue.config.js
中關閉它
css: { // 是否使用css分離插件 ExtractTextPlugin extract: false, // 開啓 CSS source maps? sourceMap: false, // css預設器配置項 loaderOptions: {}, // 啓用 CSS modules for all css / pre-processor files. modules: false },
打包出來的文件中,直接就沒有了css
文件夾
取而代之的是整合起來的一個js
文件,負責在一開始就注入全部的樣式
首屏加載文件數減小,但體積變大,最終測下來速度沒有太大差別
因此,是否要css拆分就見仁見智,具體項目具體分析吧
性能優化是一個很是使人愉悅的過程,同時也是個深坑,有着太多東西,本篇文章開了個頭,但願能對你們有所幫助
Vue打包優化之code spliting
https://juejin.im/post/5ac815...
Vue 性能優化:如何實現延遲加載和代碼拆分?
https://www.infoq.cn/article/...*zN
Webpack 打包優化之體積篇
https://www.jeffjade.com/2017...
記一次vue+element+echarts項目的優化
https://juejin.im/post/5b0033...