---
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**

#### 優化後 **668.24 KB**

---
### 參考資料
- [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)