--- tags: Webpack --- # Webpack 優化打包資源 ### 工具 ```bash npm i -D webpack-bundle-analyzer babel-plugin-component image-webpack-loader babel-plugin-lodash lodash-webpack-plugin compression-webpack-plugin ``` - **webpack-bundle-analyzer** 圖形化分析工具 - **babel-plugin-component** 讓 `babel.config.js` 可以使用 component plugin,藉此達到只引入需要的組件來減小體積 - **image-webpack-loader** 壓縮圖片 - **babel-plugin-lodash** 讓 `vue.config.js` 可以使用 `lodash-webpack-plugin`,優化 lodash 打包資源 - **lodash-webpack-plugin** 按需引入 lodash - **compression-webpack-plugin** gzip 壓縮資源檔 --- ### 圖形化分析 #### vue.config.js ```javascript= const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; module.exports = { // ... configureWebpack: { plugins: [ // 分析打包資源 new BundleAnalyzerPlugin(), ], }, } ``` --- ### element-ui #### babel.config.js 將 `element-ui` 引入檔元件化,便可以只引入需要的組件來減小體積 ```javascript= module.exports = { // ... plugins: [ // ... [ 'component', { libraryName: 'element-ui', styleLibraryName: 'theme-chalk', }, ], ], }; ``` #### src/main.js ```javascript= //... import { Breadcrumb, BreadcrumbItem, Loading, // 其餘會使用到的 element-ui 元件 ... } from 'element-ui'; // ... Vue.use(Breadcrumb); Vue.use(BreadcrumbItem); // 其餘會使用到的 element-ui 元件 ... Vue.prototype.$loading = Loading.service; // ... ``` --- ### 壓縮圖片 ```javascript= module.exports = { // ... chainWebpack: config => { // 壓縮圖片 config.module .rule('images') .test(/\.(png|jpg|jpeg|gif|svg|svgz)$/i) .use('image-webpack-loader') .loader('image-webpack-loader') .options({ // jpeg mozjpeg: { progressive: true, quality: 30 }, // png optipng: { enabled: false }, // png pngquant: { quality: [0.65, 0.9], speed: 4 }, // svg gifsicle: { interlaced: false }, // jpg & png into webp webp: { quality: 75 }, }) .end(); }, } ``` --- ### Gzip 壓縮 #### vue.config.js ```javascript= const CompressionPlugin = require('compression-webpack-plugin'); module.exports = { // ... configureWebpack: { plugins: [ new CompressionPlugin({ test: /\.(js|css|svg|otf)$/, filename: '[path][base].gz', threshold: 10240, }), ], }, } ``` --- ### lodash #### vue.config.js ```javascript= const LodashWebpackPlugin = require('lodash-webpack-plugin'); module.exports = { // ... configureWebpack: { plugins: [ // ... // lodash 按需打包 new LodashWebpackPlugin({ 'collections': true, }), ], }, } ``` #### babel.config.js ```javascript= module.exports = { // ... plugins: [ [ 'lodash' ], ], }; ``` --- ### jquery #### vue.config.js ```javascript= module.exports = { // ... chainWebpack: config => { // 指定引入 jquery 的檔案路徑 config.resolve.alias .set('jquery', 'jquery/dist/jquery.slim.min.js'); }, // ... } ``` --- ### router #### src/router/index.js 某些較大的檔案使用 lazyload 方式引入 不宜過度使用,避免請求過多而變慢導致反效果 ```javascript= // ... import LoginPage from '../views/ds_auth/LoginPage.vue'; // 其餘較小的檔案 ... Vue.use(VueRouter); const routes = [ { path: '/', name: 'Index', component: () => import(/* webpackChunkName: "index" */ '../views/global/Index.vue'), }, { path: '/loginPage', name: 'LoginPage', component: LoginPage, }, // ... ]; // ... ``` --- ### 優化成果 #### 優化前 **1.18 MB** ![](https://i.imgur.com/Fj8LeqV.png) #### 優化後 **668.24 KB** ![](https://i.imgur.com/MHVEm3j.png) --- ### 參考資料 - [webpack-bundle-anallyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer) - [Element-ui 按需引入](https://element.eleme.io/#/zh-CN/component/quickstart#an-xu-yin-ru) - [babel-plugin-component](https://github.com/ElementUI/babel-plugin-component) - [image-webpack-loader](https://github.com/tcoopman/image-webpack-loader#readme) - [compression-webpack-plugin](https://github.com/webpack-contrib/compression-webpack-plugin) - [lodash-webpack-plugin](https://github.com/lodash/lodash-webpack-plugin) - [babel-plugin-lodash](https://github.com/lodash/babel-plugin-lodash#readme)