module.exports = {
configureWebpack: {
resolve: {
alias: {
‘@’: resolve(‘./src’)
}
},
plugins
},
}

/* 第二种方式 在vuecli中*/
// configureWebpack 返回函数式写法
const CompressionWebpackPlugin = require(‘compression-webpack-plugin’)
const isProduction = process.env.NODE_ENV !== ‘development’
module.exports = {

configureWebpack: (config) => {
config.plugins.push(
new HardSourcePlugin()
)
// 其他配置
Object.assign(config.resolve, {
alias: {
‘@’: resolve(‘./src’)
}
})
// 为生产环境修改配置
if (isProduction) {
config.plugins.push(
new CompressionWebpackPlugin({
filename: ‘[path].gz[query]’,
algorithm: ‘gzip’,
test: new RegExp(‘.(’ + [‘html’, ‘js’, ‘css’].join(‘|’) + ‘)$’),
threshold: 10240, // 只有大小大于该值的资源会被处理 10240
minRatio: 0.8, // 只有压缩率小于这个值的资源才会被处理
deleteOriginalAssets: false // 删除原文件
})
)
}
},

}

// webpack.config.js 在webpack搭建的项目中
const CompressionWebpackPlugin = require(‘compression-webpack-plugin’)
module.exports = {
mode: ‘development’,

plugins: [
new CompressionWebpackPlugin({
filename: ‘[path].gz[query]’,
algorithm: ‘gzip’,
test: new RegExp(‘.(’ + [‘html’, ‘js’, ‘css’].join(‘|’) + ‘)$’),
threshold: 10240, // 只有大小大于该值的资源会被处理 10240
minRatio: 0.8, // 只有压缩率小于这个值的资源才会被处理
deleteOriginalAssets: false // 删除原文件
})
]


##### 服务端配置, 以nginx为例


服务端 Nginx 需开启 gzip\_static 功能;  
 在nginx.conf的server模块中加入以下代码:



server{
//开启和关闭gzip模式
gzip on;
//gizp压缩起点,文件大于2k才进行压缩;设置允许压缩的页面最小字节数,页面字节数从header头得content-length中进行获取。 默认值是0,不管页面多大都压缩。建议设置成大于2k的字节数,小于2k可能会越压越大。
gzip_min_length 2k;
// 设置压缩所需要的缓冲区大小,以4k为单位,如果文件为7k则申请2*4k的缓冲区
gzip_buffers 4 16k;
// 设置gzip压缩针对的HTTP协议版本
gzip_http_version 1.0;
// gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间
gzip_comp_level 2;
//进行压缩的文件类型
gzip_types text/plain application/javascript text/css application/xml;
// 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;
}


访问时 可以看到


![](https://img-blog.csdnimg.cn/img_convert/32c36e372add1619293b63f1c2a1ffda.webp?x-oss-process=image/format,png)


#### 利用多核/多进程能力


##### `thread-loader`


* 多进程程处理loader
* 使用时,需将此 loader 放置在其他 loader 之前。放置在此 loader 之后的 loader 会在一个独立的 worker 池中运行。
* 本身启动进程就需要耗费时间,\*\*请仅在耗时的操作中使用此 loader!\*\*要不然收益达不到你的预期


##### `happypack`


* 启动多进程来优化构建速度,但是作者不维护了,注意安装版本,
* 替换方案建议使用`thread-loader`



{
// 当js代码用babel处理兼容性且本身代码就比较多的情况下可以使用thread-loader开启多线程打包
// thread-loader本身启动进程就需要耗费时间, 所以当js代码不多时就不要开启, 否则还可能会延长打包时间
test: ‘/.js$/’,
exclude: /node_modules/,
use: [
{
loader: ‘thread-loader’,
options: {
// 默认是cpu核 - 1, 可以通过这里更改开启几个进程
works: 2
}
}
]

}



// @file: webpack.config.js
const HappyPack = require(‘happypack’);
var happyThreadPool = HappyPack.ThreadPool({ size: 5 });

exports.module = {

rules: [
{

  test: /.js$/,
  // 1) replace your original list of loaders with "happypack/loader":
  // loaders: [ 'babel-loader?presets[]=es2015' ],
  use: ['happypack/loader'?id=babel], // 这里的id 就是定义在plugin里面HappyPack实例构造参数传入的id
  include: [ /* ... */ ],
  exclude: [ /* ... */ ]
},
{ 

  test: /.less$/,
  use: 'happypack/loader?id=styles'
},

]
};

exports.plugins = [
// 2) create the plugin:
new HappyPack({

// 3) re-add the loaders you replaced above in #1:
loaders: [ 'babel-loader?presets[]=es2015' ],
threadPool: happyThreadPool,
id: 'babel'

}),
new HappyPack({

id: 'styles',
threadPool: happyThreadPool,
loaders: [ 'style-loader', 'css-loader', 'less-loader' ]

})
];


注意: **这部分,如果你是vueCli创建的项目,则不用配置, 内部已处理**


#### 关闭source map


生产环境关闭`productionSourceMap`、`css sourceMap`, 生产环境没必要打开这个



// vue.config.js
const isProduction = process.env.NODE_ENV === ‘production’
// 判断是否是生产环境
module.exports = {
productionSourceMap: !isProduction, //关闭生产环境下的SourceMap映射文件
css: {
sourceMap: !isProduction, // css sourceMap 配置
loaderOptions: {
…其它代码
}
},
…其它代码
}


#### 组件的按需加载配置


这里以ElementUi 为例, 其他组件库官网上会有对应说明, 大体上差不多


借助 babel-plugin-component,我们可以只引入需要的组件,以达到减小项目体积的目的。



npm install babel-plugin-component -D
// .babelrc 或者 babel.config.js
{
“presets”: [[“es2015”, { “modules”: false }]],
“plugins”: [
[
“component”,
{
“libraryName”: “element-ui”,
“styleLibraryName”: “theme-chalk”
}
]
]
}


如图,可以看到对比,


![](https://img-blog.csdnimg.cn/img_convert/2574cc6a566754f9a753f9feb2f8bb7c.webp?x-oss-process=image/format,png)


![](https://img-blog.csdnimg.cn/img_convert/80158c2d8e8763afb2ca1fc7ab16f507.webp?x-oss-process=image/format,png)


还有需要注意的是,如果你使用了自定义主题, 那么在babel的配置中如官网以下


![](https://img-blog.csdnimg.cn/img_convert/e2d0582411b98b7fb8e028646e4028aa.webp?x-oss-process=image/format,png)


#### 解决Echarts打包后体积过大问题


从刚开始的图中,能看到, echarts占了很大的体积, 这不能接受


##### 方案一


在index.html模板文件中引入cdn, 打包的时候webpack配置externals ,这样webpack就不会打这个包到vendors里,减少体积,缺点是cnd稳定性可能会有问题,而且是先请求cdn资源之后再请求自己服务器代码,非同源。pass


##### 方案二


`babel-plugin-equire` 我见社区有这个按需引入echarts的插件, 不过我没研究过, 感兴趣的可以去试试,我选择的是方案三


##### 方案三


在线定制echarts, 可以选择自己想要的功能,生成的js,就会小很多,


[在线定制网址](https://bbs.csdn.net/topics/618166371)


将生成的echarts.min.js引入到项目中,替换项目中的echarts引用



import echarts from ‘echarts’
变成下面
import echarts from ‘./plugins/echarts.min.js’

也可将这个js放到index.html里面,

在main.js文件里面
Vue.prototype.$echarts = window.echarts

同时可以卸载调之前装的echarts
npm unistall echarts


![](https://img-blog.csdnimg.cn/img_convert/53a2d62b09f4a00ecaad1883aa355dfc.webp?x-oss-process=image/format,png)


![](https://img-blog.csdnimg.cn/img_convert/65d28b54fe056ca84f1652b34783dea9.webp?x-oss-process=image/format,png)


可以看到 还是很明显的变化的


接下来 再看看打包生成的report现状


![](https://img-blog.csdnimg.cn/img_convert/025a725b5d119974486c943d11390da0.webp?x-oss-process=image/format,png)


可以看到pdf占比还是很大, 继续优化


#### pdf插件优化


项目中有pdf预览的功能,安装了`pdfjs-dist` 和`vue-pdf`两个插件,后来跟后端协商,走文件流的方式了, 就没用到这两个, 就卸载了, 如果谁有相关方案,欢迎来提


#### moment.js的优化


如果时间充裕,建议换成day.js 大小只有6kb, 但是我们项目里面用moment地方太多了,且比较混乱, 就暂时先不更换, 采用剔除其他语言包的方案


方案一



const MomentLocalesPlugin = require(‘moment-locales-webpack-plugin’);

module.exports = {
configureWebpack: {
plugins: [
new MomentLocalesPlugin({
// 保留一个
localesToKeep: [‘zh-cn’],
}),
]
}
}

//使用
import moment from ‘moment’;
// 按需加载需要引入对应的语言包
import ‘moment/locale/zh-cn’;

moment.locale(‘zh-cn’);


方案二



const webpack = require(‘webpack’);
module.exports = {
//…
plugins: [
// 忽略 moment.js的所有本地文件
new webpack.IgnorePlugin(/^./locale / , / m o m e n t /, /moment /,/moment/),
],
};

// 使用
import moment from ‘moment’;
// 按需加载需要引入对应的语言包
import ‘moment/locale/zh-cn’;

moment.locale(‘zh-cn’);


![](https://img-blog.csdnimg.cn/img_convert/4c774f62900a195cca102dcad7825ca5.webp?x-oss-process=image/format,png)


![](https://img-blog.csdnimg.cn/img_convert/2e71b7f02f739a9b5d02f56c3a4214cf.webp?x-oss-process=image/format,png)


#### 针对lodash库优化


项目中有时会安装lodash,但一般只使用几个方法, 在打包的时候,会发现会将lodash全部打进去, 所以使用下面这两个库


* `babel-plugin-lodash` 用来精简Lodash模块的,只保留用到的方法。
* `lodash-webpack-plugin` 这个插件经过用noop, identity, 或其余更简单的替代品来替换一些模块的特性,使得打包后的体积更小(翻译)。

 注意:这个插件默认会关闭一些lodash不经常使用的特性,能够给插件传递options来开启某些特性



modules.exports = {
// 其余配置省略…
plugins: [‘lodash’]
}

// vue.config.js
const LodashModuleReplacementPlugin = require(‘lodash-webpack-plugin’);
module.exports = {
// …
configureWebpack: {
plugins: [
new LodashModuleReplacementPlugin()
]
}
}

// 或者chainWebpack 但是我觉得这种写法,有点一言难尽
module.exports = {
chainWebpack: config => {
config.plugin(“loadshReplace”)
.use(new LodashModuleReplacementPlugin());
}
}


![](https://img-blog.csdnimg.cn/img_convert/41fe1572d7471bb5db8fd0d8e114fdf4.webp?x-oss-process=image/format,png)


![](https://img-blog.csdnimg.cn/img_convert/36f94bf2f92d9c2adca4fc7bb20f34de.webp?x-oss-process=image/format,png)


注意: 这个插件可能带来一些意想不到的坑, 可能会导致使用第三方插件报错出现一些其他问题,具体可以参考下这篇文章 [zhuanlan.zhihu.com/p/349260482](https://bbs.csdn.net/topics/618166371)


#### 开启 Tree Shaking 功能


在前面的依赖视图分析中可以看到sailfish 这个依赖,如下图,它是我们公司以前封装的UI库,它是以源码的方式供项目使用, 没有打包. 老项目里面用了几个组件,打包的时候发现还是全部打进来了


![](https://img-blog.csdnimg.cn/img_convert/28a1da10593c96378dc5de769600138e.webp?x-oss-process=image/format,png)


![](https://img-blog.csdnimg.cn/img_convert/d4aeed47d536088e1f1f79ef43c17a05.webp?x-oss-process=image/format,png)


优化方式有以下几个点


1. 按需加载:在需要使用这个 UI 库的组件时再进行动态加载,不在打包时将整个库全部打入。
2. 开启 Tree Shaking:如果你使用的是 ES6 模块化的方式引入这个 UI 库,并且使用了相关的工具(如 webpack),则可以开启 Tree Shaking 功能,只将你用到的组件打入打包文件中,未使用的组件将会被去除。
3. 使用 babel-plugin-import 插件:有些 UI 库将所有的组件都导出为一个模块,对于这种情况,你可以使用 babel-plugin-import 插件,通过按需加载的方式只加载你使用的组件,而不是全部导入。
4. 自己打包:如果这个 UI 库的源码是开放的,而且你只想使用部分组件,那么你也可以自己将需要的组件单独打包,而不是全部打包。


因为后期规划要替换掉它,所以不想在它上面浪费过多精力


#### 其他的优化


##### externals


`externals`配置项用来告诉`Webpack`要构建的代码中使用了哪些不用被打包的模块,也就是说这些模版是外部环境提供的,`Webpack`在打包时可以忽略它们


一般是将体积较大的第三方包抽离为externals,一般处理`element-ui`,`vue`或者其他的,看自己项目



// vue.config.js
module.exports = {
configureWebpack: {
externals: {
// 安装的包名 — 暴露的全局变量的值
“element-ui”: “ELEMENT”,
echarts: “echarts”,
vue: “Vue”,
},
},
}


然后在index.html引入对应的cnd链接, 如果害怕cdn不稳定,可以去下载下来,copy到自己的项目中,手动引入, 也可使用webpack配置注入进去



// vue.config.js

module.exports = {
chainWebpack: config => {
config.plugin(‘html’).tap(args => {
args[0].cdn = {
js: [
‘https://xx.com/CDN/js/index-element-ui@2.13.0.js’,
],
css: [
‘https://xx.com/CDN/css/element-ui2.13.0/index.css’,
],
};
return args;
});
}
}

// 使用

<% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %> <% } %> <% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %> <% } %>

注意


* externals:声明文件被外部引用不用打包,不参与打包流程,由于直接写死在html里,可以使用cdn等加速
* externals缺点:直接html内引入的,所以不会有treeshaking,按需引入等,具体看自己取舍


推荐常用的两个cdn服务 BootCDN 与 cdnjs 。


#### 移除 preload(预载) 与 prefetch (预取)


vue 脚手架默认开启了 preload 与 prefetch,当我们项目很大时,会造成首屏加载速度慢的元凶



> 
> preload 与 prefetch 都是一种资源预加载机制; preload 是预先加载资源,但并不执行,只有需要时才执行它; prefetch 是意图预获取一些资源,以备下一个导航/页面使用; preload 的优先级高于 prefetch。
> 
> 
> 



// vue.config.js

chainWebpack: config => {
// 移除 preload(预载) 插件
config.plugins.delete(‘preload’)
// 移除 prefetch(预取) 插件
config.plugins.delete(‘prefetch’)
}


主要关注首屏速度, 可自行去体验下关闭前后的效果


#### 清除log等调试信息


使用 terser-webpack-plugin 清除 console.log



先安装依赖

npm install terser-webpack-plugin --save-dev

然后配置

const TerserPlugin = require(‘terser-webpack-plugin’);

module.exports = {
configureWebpack: config => {

❤️ 谢谢支持

喜欢的话别忘了 关注、点赞哦~。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

前端校招面试题精编解析大全

// 移除 preload(预载) 插件
config.plugins.delete(‘preload’)
// 移除 prefetch(预取) 插件
config.plugins.delete(‘prefetch’)
}


主要关注首屏速度, 可自行去体验下关闭前后的效果


#### 清除log等调试信息


使用 terser-webpack-plugin 清除 console.log



先安装依赖

npm install terser-webpack-plugin --save-dev

然后配置

const TerserPlugin = require(‘terser-webpack-plugin’);

module.exports = {
configureWebpack: config => {

❤️ 谢谢支持

喜欢的话别忘了 关注、点赞哦~。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

[外链图片转存中…(img-6f0IVaO4-1714164498360)]

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐