本篇将不逐一介绍webpack配置项的意义和作用,配置项不熟悉可参考webpack官方文档(https://www.webpackjs.com/)。
或者也可以参考我的另一篇文章 webpack之深入浅出。
现在仅从项目实践角度出发,结合开发过程中遇到的优化问题,具体给出webpack( 项目中webpack版本为3.12.0,webpack 4.x略有不同 )配置项的实现目的和优化方案。优化方案的最终结果将在两个维度体现出来:构建性能效率和打包资源体积。本文将默认按照项目webpack从上到下的配置项,逐次展开,添加优化项。
1、resolve
resolve解析项目中的模块,但是如果检索每个文件夹就会浪费资源,降低效率。所以要设定或者排除,哪些文件夹需要检索,哪些不需要。
resolve: {
...
// resolve.modules -> webpack 解析模块时应该搜索的目录,可以设置 node_moudles 目录
modules: [path.resolve(__dirname, "src"), "node_modules"]
},
2、loaders
A、删除冗余loaders
项目默认使用sass处理样式文件。所以不需要配置less,stylus等其他类型的loaders。初始化的时候,将冗余loader配置删除,仅保留项目使用的文件。
function generateLoaders () {
// 动态创建loader ...
}
return { //返回css类型对应的loader组成的对象 generateLoaders()来生成loader
css: generateLoaders(),
// postcss: generateLoaders(),
// less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
// stylus: generateLoaders('stylus'),
// styl: generateLoaders('stylus')
}
// 删除冗余css-loaders,把postcss, less, sylus, styl 等项目中未使用的loaders配置删除。
B、简化loader的检索范围
和resolve.moudels类似,loader也会检索项目中出现的正则匹配的文件。所以仍需要设置需要检索的文件夹,提高效率
// 比如 js文件
{
test: /\.js$/,
//loader: 'babel-loader',
loader: 'happypack/loader?id=happy-babel-js',
// 以下为新增优化配置
// 目的在于只检索src下的js文件即可,不需要检索其他文件夹,提高检索效率
include: [resolve('src')]
},
...
3、sourceMap
sourcemap 一个反应原文件映射关系的文件,在开发环境调试阶段尤为重要,可以在原代码中直接报出出错的行数和列数,方便定位。但是在生产环境中,则不需要。所以,不同环境之间设置有所不同。
A、devtool
不同的devtool的配置,直接影响到项目构建速度。具体可查看官方文档 https://www.webpackjs.com/configuration/devtool/#devtool。
经综合比较,得出开发环境和生产环境模式下的配置:
// dev 开发环境
// cheap-module-eval-source-map is faster for development
devtool: 'cheap-module-eval-source-map',
// production 生产环境
devtool: 'cheap-module-source-map';
或者直接设置为false (不设置source-map)
B、productionSourceMap
打包时,不需要sourcemap来映射文件关系,所以生产模式下关闭 sourcemap。
module.exports = {
build: {
...
productionScourceMap: false
}
}
4、plugins
不同于loader作为解释转化器的角色,plugins作为webpack功能的拓展,会在webpack构建的某个节点(生命周期)执行某些任务。
A、webpack-parallel-uglify-plugin
该插件的作用在于:
1、压缩输出js文件
2、设置缓存文件,加速构建。
3、删除js注释、冗余变量等。
// npm i -D webpack-parallel-uglify-plugin
// config.js
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
plugins: [
...
new ParallelUglifyPlugin ({
// 设置缓存路径,不改动的调用缓存,第二次及后面build时提速
cacheDir: '.cache/',
// 混淆压缩js文件
uglifyJS:{
output: {
beautify: false,
comments: false
},
warnings: false,
compress: {
// 删除所有的 `console` 语句,可以兼容ie浏览器
drop_console: true,
// 内嵌定义了但是只用到一次的变量
collapse_vars: true,
// 提取出出现多次但是没有定义成变量去引用的静态值
reduce_vars: true,
}
}
})
]
B、extract-text-webpack-plugin
该插件的作用在于单独提取css文件,不直接将style注入html的head中,单独打包。
// npm i -D extract-text-webpack-plugin
var ExtractTextPlugin = require('extract-text-webpack-plugin')
// extract css into its own file
new ExtractTextPlugin({
// 输出文件名更改为 文件指纹命方式,避免缓存
filename: utils.assetsPath('css/[name].[contenthash].css')
}),
C、CompressionWebpackPlugin
该插件的作用在于开启GZIP压缩,可以使输出文件的体积显著变小。
// npm i -D compression-webpack-plugin
var CompressionWebpackPlugin = require('compression-webpack-plugin')
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
// 正则匹配需要 Gzip压缩的文件格式 productionGzipExtensions -> [js, css, json]
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
// 只处理比这个值大的资源。按字节计算
threshold: 10240,
// 只有压缩率比这个值小的资源才会被处理
minRatio: 0.8
})
D、HappyPack
该插件的作用在于充分发挥电脑多核CPU,把任务分解给多个子进程去并发的执行,提高构建速度。
// npm i -D happypack
const HappyPack = require('happypack');
const os = require('os');
// 获取电脑硬件的cpu核心数,准备开启多线程构建
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
module.exports = {
// 要告诉 happypack 处理哪些类型的文件 比如 vue,js文件
moudles: {
rules: [
{
test: /\.vue$/,
loader: 'happypack/loader?id=vue',
},
{
test: /\.js$/,
//loader: 'babel-loader',
loader: 'happypack/loader?id=happy-babel-js',
include: [resolve('src'), resolve('test')]
},
]
},
// plugins
plugins: [
new HappyPack({
// //用id来标识 happypack处理那里类文件
id: 'happy-babel-js',
loaders: ['babel-loader?cacheDirectory=true'],
// 共享进程池
threadPool: happyThreadPool,
}),
new HappyPack({
id: 'vue',
loaders: [{
loader:'vue-loader',
options:vueLoaderConfig
}],
threadPool: happyThreadPool,
}),
]
}
E、image-webpack-loader
该插件作用在于处理项目中图片的体积,可以显著减少各种格式图片的体积.(这个属于loader优化,暂且放在这部分)
// npm i -D image-webpack-loader
// 具体可参照文档 https://www.npmjs.com/package/image-webpack-loader
rules: [
{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
'file-loader',
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
progressive: true,
quality: 65
},
// optipng.enabled: false will disable optipng
optipng: {
enabled: false,
},
pngquant: {
quality: [0.65, 0.90],
speed: 4
},
gifsicle: {
interlaced: false,
},
// the webp option will enable WEBP
// 其中注意 webp格式 只支持谷歌浏览器 所以可以不用配置
webp: {
quality: 75
}
}
},
}]
F、webpack-bundle-analyzer
该插件的作用在于分析打包情况,可以以图表的方式直观给出打包过后资源依赖的大小,有针对性的去优化依赖。
// npm i -D webpack-bundle-analyzer
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
// npm run build -> Analyze package size
new BundleAnalyzerPlugin({
analyzerMode: 'server',
analyzerHost: '127.0.0.1',
// 自动开启 8889 端口显示资源大小
analyzerPort: 8889,
reportFilename: 'report.html',
defaultSizes: 'parsed',
openAnalyzer: false,
generateStatsFile: false,
statsFilename: 'stats.json',
statsOptions: null,
logLevel: 'info'
}),
以上方案在项目实践中得到了检验,有效的提高了项目构建的效率,减少打包后dist包的体积。
欢迎补充~~.