摘要:同時也要引入對應版本的先引入引入組件庫因為依賴是從外部引入的,所以需要告知在打包時,依賴的來源。然后在中加入一條命令執行或者即可完成打包。因此將此次優化記錄下來,并傳上了中。
本文原文
前言公司有好幾個項目都有后臺管理系統,為了方便開發,所以選擇了 vue 中比較火的 后臺模板 作為基礎模板進行開發。但是,開始用的時候,作者并沒有對此進行優化,到項目上線的時候,才發現,打包出來的文件都十分之大,就一個 vendor 就有 770k 的體積(下圖是基礎模板,什么都沒加打包后的文件信息):
通過 webpack-bundle-analyzer 進行分析可得,體積主要來源于 餓了么UI(體積為 500k),因為沒對其進行部分引入拆分組件,導致 webpack 把整個組件庫都打包進去了。其次就是 vue 本身,體積也達到了 80k 之大。
所以,對其進行打包優化,是一件刻不容緩的事情。
優化優化主要目的有:
加快資源加載速度,減少用戶等待的時間和首頁白屏時間,提高用戶體驗。
加快打包速度,不要將時間浪費在等待打包上。
解決第一個問題,很多人都會想到資源文件放在 CDN 上就好了,沒錯,這次我們就是通過 CDN 來解決加載問題。
CDN - 提高加載速度像 vue, element ui 這些比較成熟的框架/組件庫,一般都有免費、高速、公共的 cdn 供開發者使用,鑒于大部分用戶均在國內,所以這次使用了 bootcdn 這個庫。該庫熱門資源比較齊全,各個版本都有,而且國內訪問速度很快,簡直是開發者的福音。
在 index.html 中引入 vue 和 餓了么組件。
vue-admin-template
因為依賴是從外部引入的,所以需要告知 webpack 在打包時,依賴的來源。
修改 webpack.base.conf.js:
module.exports = { ... externals: { vue: "Vue", "element-ui":"ELEMENT" } }
再一次打包,確實能極大的壓縮了打包的體積,從 700k 驟減至 130k:
但是隨之而來的就有問題了:
明明我在本地開發,但是由于引入了線上的生產版本的 vue 文件,因此 vue-dev-tools 就不能進行調試。
因此,我們需要再次調整一下 webpack 的配置,webpack.base.conf.js,而且 webpack 注入的 js 總是在最后面的,因此,我們需要 html-webpack-include-assets-plugin 幫忙在注入 app.js 后,再注入相對應的組件庫 :
const HtmlWebpackIncludeAssetsPlugin = require("html-webpack-include-assets-plugin") const externals = { // 因為打包時,還沒注入,所以這里要去掉。 // "element-ui":"ELEMENT" } // 生產環境中使用生產環境的 vue // 開發環境繼續使用本地 node_modules 中的 vue if (process.env.NODE_ENV === "production") { externals["vue"] = "Vue" // 如發現打包時依舊將 element-ui 打包進入 vendor,可以在打包時將其加入外部依賴。 externals["element-ui"] = "ELEMENT" } // 生產環境默認注入 vue // 開發環境中不注入 const defaultJS = process.env.NODE_ENV === "production" ? [{ path: "https://cdn.bootcss.com/vue/2.4.2/vue.min.js", type: "js" }] : [] const plugins = [ new HtmlWebpackIncludeAssetsPlugin({ assets: defaultJS.concat([ { path: "https://cdn.bootcss.com/element-ui/2.3.2/index.js", type: "js" }, { path: "https://cdn.bootcss.com/element-ui/2.3.2/locale/zh-CN.min.js", type: "js" }, ]), // 是否在 webpack 注入的 js 文件后新增?true 為 append, false 為 prepend。 // 生產環境中,這些 js 應該先加載。 append: process.env.NODE_ENV !== "production", publicPath: "", }) ] module.exports = { ... externals, plugins, ... }
OK,這時候,既能兼顧打包后的體積大小,也能在開發模式中使用 vue-dev-tool 進行調試。
DLL - 提高打包速度經常打包的前端會發現,很多時候,我們為了修復某些bug(如 promise 在 ie Safari 下的 bug),而新引入了一個 polyfill,然而,打包完后發現,vendor 的 hash 值變了,而整個 vendor 只新加了一個 es6-promise 的依賴,但是付出的代價就是,需要拋棄之前打包好的 vendor,用戶重新訪問時,需要再一次拉取一個全新的 vendor,這個代價就有點大了。
這時候,使用 dllPlugin 打包就有優勢了。它可以將一些基礎依賴模塊統一先打包起來,當正式打包時,則可以略過這些模塊,不再重復打包進去 vendor,提高打包速度的同時也能減少 vendor 的體積。
如,后臺管理系統基礎模塊基本有以下幾個:
axios: ajax 請求。
vuex: 全局狀態管理。
js-cookie: 前端處理 cookie。
vue-router: 路由管理。
這四個基礎模塊幾乎是必須的,那么可以先提取出來。
先在 build 文件夾下新建一個用于打包 dll 的配置文件 webpack.dll.conf.js:
const webpack = require("webpack"); const path = require("path"); const vueLoaderConfig = require("./vue-loader.conf") const utils = require("./utils") function resolve(dir) { return path.join(__dirname, "..", dir) } const vendor = [ // "vue/dist/vue.runtime.esm.js", // 由于 vue 在生產環境中使用的是 cdn 引入,所以也無需提前打包進 dll // "raven-js", // 前端監控,若無此需求,可以忽略。 "es6-promise", // 修復 promise 中某些 bug。 "vue-router", "js-cookie", "axios", "vuex", ]; const webpackConfig = { context: __dirname, output: { path: path.join(__dirname, "../static/js/"), filename: "[name].dll.js", library: "[name]_[hash]", }, entry: { vendor }, plugins: [ new webpack.DllPlugin({ context: __dirname, path: path.join(__dirname, ".", "[name]-manifest.json"), name: "[name]_[hash]", }), new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false }, sourceMap: true, // parallel: true }) ], module: { rules: [{ test: /.vue$/, loader: "vue-loader", options: vueLoaderConfig }, { test: /.js$/, loader: "babel-loader", include: [resolve("src"), resolve("test"), resolve("node_modules/webpack-dev-server/client")] }, { test: /.(png|jpe?g|gif|svg)(?.*)?$/, loader: "url-loader", options: { limit: 10000, name: utils.assetsPath("img/[name].[hash:7].[ext]") } }, { test: /.(mp4|webm|ogg|mp3|wav|flac|aac)(?.*)?$/, loader: "url-loader", options: { limit: 10000, name: utils.assetsPath("media/[name].[hash:7].[ext]") } }, { test: /.(woff2?|eot|ttf|otf)(?.*)?$/, loader: "url-loader", options: { limit: 10000, name: utils.assetsPath("fonts/[name].[hash:7].[ext]") } } ] } }; module.exports = webpackConfig
然后在 package.json 中加入一條命令:
{ "scripts": { ... "build:dll": "webpack --config build/webpack.dll.conf.js", ... } }
執行 yarn build:dll 或者 npm run build:dll 即可完成打包 dll。執行完成后:
yarn build:dll yarn run v1.5.1 $ webpack --config build/webpack.dll.conf.js Hash: f6894dff019b2e0734af Version: webpack 3.10.0 Time: 1295ms Asset Size Chunks Chunk Names vendor.dll.js 62.6 kB 0 [emitted] vendor [8] dll vendor 12 bytes {0} [built] + 32 hidden modules ? Done in 1.89s.
同時,可以在 build 目錄下,找到各個模塊對應關系文件 vendors-manifest.json 和 static/js 下的 vendor.dll.js。
打包后的 dll 文件需要手動在 index.html 引入:
修改 build/webpack.prod.conf.js:
module.exports = { plugins: [ ... new webpack.DllReferencePlugin({ context: __dirname, manifest: require("./vendor-manifest.json") }), ... ] }
再次打包:
$ yarn build:report yarn run v1.5.1 $ npm_config_report=true node build/build.js Hash: b4ff51852866ed865cfd Version: webpack 3.10.0 Time: 6532ms Asset Size Chunks Chunk Names static/js/manifest.42b9584a653aec2b9c5e.js 1.5 kB 5 [emitted] manifest static/img/404.a57b6f3.png 98.1 kB [emitted] static/js/1.9e4133a25808e2101dd3.js 1 kB 1 [emitted] static/js/2.2a8a8e01c51473fab882.js 4.34 kB 2 [emitted] static/js/vendor.c7b076ef3341d4711402.js 39.4 kB 3 [emitted] vendor static/js/app.6d52c7a5bf1bacb5cc85.js 21.4 kB 4 [emitted] app static/js/0.cbc645864aab28ae8055.js 15.3 kB 0 [emitted] static/css/app.1b30f8eba210e245a5f96d7bf0d6fb6c.css 7.6 kB 4 [emitted] app favicon.ico 67.6 kB [emitted] index.html 986 bytes [emitted] static/js/vendor.dll.js 62.6 kB [emitted] Build complete. Tip: built files are meant to be served over an HTTP server. Opening index.html over file:// won"t work.
發現 vendor 現在只有 40k 的體積,減少了一半的體積,而且打包速度也快了 2s,而相對于最開始的基礎模板,打包速度快了 12s,這是很讓人欣慰。
后記使用了 cdn 和 dll 打包后,無論是打包速度還是頁面加載的速度都有很大的提升。因此將此次優化記錄下來,并傳上了 GitHub 中。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/95022.html
摘要:原文地址對于沒有了解過的童鞋,建議先去看看官方的教程傳送門新版本的新特性插件使用的插件,可以很快的搭建一個項目的結構。使用時直接引入即可。的界面讓管理項目變得更加簡單。如遷移過程中有任何疑問,可以留言一起探討。 原文地址 對于沒有了解過 vue-cli3 的童鞋,建議先去看看官方的教程: 傳送門 新版本的新特性 1. 插件 使用 cli 的插件,可以很快的搭建一個項目的結構。如 ax...
摘要:用戶體驗的需求,完美地保留了瀑布流模態框的閱讀模式。不支持的話,就不攔截瀑布流文塊的,也就是直接讓其跳轉。 背景 想當年,我做了一個新媒體網站項目(AIISPO,已下線)。跟普通資訊網站不一樣的是,老板要求PC端前臺的文章閱讀模式一定得是瀑布流+模態框。瀑布流指的是以瀑布流的形式將文章羅列出來,而模態框則指的是點擊瀑布流中代表文章的某個文塊時,直接在當前頁面彈出模態框來顯示文章正文。 ...
摘要:用戶體驗的需求,完美地保留了瀑布流模態框的閱讀模式。不支持的話,就不攔截瀑布流文塊的,也就是直接讓其跳轉。 背景 想當年,我做了一個新媒體網站項目(AIISPO,已下線)。跟普通資訊網站不一樣的是,老板要求PC端前臺的文章閱讀模式一定得是瀑布流+模態框。瀑布流指的是以瀑布流的形式將文章羅列出來,而模態框則指的是點擊瀑布流中代表文章的某個文塊時,直接在當前頁面彈出模態框來顯示文章正文。 ...
摘要:重構總共耗時個工作日。第一個重構原因就是沒有引入靜態類型,導致查看一個對象結構需要翻來覆去在多個文件中查找。第三是各個狀態模塊耦合度高,加大了代碼維護難度。但如果耦合度過高,往往是因為模塊沒有細分到位。這個項目也不列外。 showImg(https://segmentfault.com/img/remote/1460000019660483); 不知不覺已是2019年的7月,恍惚之間已...
閱讀 3997·2021-11-18 13:22
閱讀 1823·2021-11-17 09:33
閱讀 2882·2021-09-26 09:46
閱讀 1214·2021-08-21 14:11
閱讀 2892·2019-08-30 15:53
閱讀 2711·2019-08-30 15:52
閱讀 1894·2019-08-30 10:52
閱讀 1521·2019-08-29 15:30