webpack简单配置及其用法二
一、编写可维护的webpack构建配置
栗子:构建配置包设计
构建配置抽离成npm包的意义
通过性:业务开发者无需关注构建配置;统一团队构建脚本
可维护性:构建配置合理的拆分;reademe,changelog文档
质量:冒烟测试,单元测试,测试覆盖率;持续继承
构建配置管理的可选方案
1)通过多个配置文件管理不同环境的构建,webpack —config参数进行控制使用的配置文件,如
基础配置:webpack.base.js;开发环境:webpack.dev.js;生产环境:webpack.prod.js;ssr环境:webpack.ssr.js
2)将构建配置设计成一个库,比如hjs-webpack Neutrino webpack-blocks
规范:git commit日志,README,ESLINT规范,Semver规范
质量:冒烟测试,单元测试,测试覆盖率和CI
3)抽成一个工具进行管理,比如:create-react-app kyt nwb
4)将所有的配置写在一个文件,通过—env参数控制分支选择、
1)2)适合小团队使用,大团队可选择3)方式
通过webpack-merge组合配置
const merge = require("webpack-merge)
merge(
{a:[1], b:5, c:20},
{a:[2], b:6, d:35}
)
>{a:[1,2],b:6,c:20,d:35} // 非对象或非数组,则有相同的变量名,后面的覆盖前面的
合并配置:module.exports=merge(baseConfig,devConfig)
二、webpack构建速度和体积优化策略
体积优化方法:
1)scope hoisting
2)tree-shaking
3)公共资源分离
4)图片压缩
5)动态polyfill
提升构建速度方法:
1)充分使用缓存,提升二次构建速度
2)进一步分包:预编译资源模块
栗子:构建速度和速度分析
1)使用webpack内置的stats:构建的统计信息
2)速度分析:用speed-measure-webpack-plugin,分析整个打包的耗时,每个插件和loader的耗时
安装插件
npm install -D speed-measure-webpack-plugin
创建对象
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();
将之前module.exports的内容,包裹在smp.wrap()里面
smp.wrap(...)
3)体积分析:用webpack-bundle-analyzer
可以分析依赖的第三方模块文件大小,业务里面的组件代码大小
安装依赖
npm install -D webpack-bundle-analyzer
配置
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin()
]
}
栗子:使用高版本的webpack和node
栗子:充分利用缓存,提升二次构建速度——首次构建速度不会变化,下次构建的速度才会有变化
缓存思路:
1)babel-loader开启缓存,解析js语法或者jsx语法,等下次在解析一样的语法的时候,就可以读取缓存的内容,提升解析的速度
2)terser-webpack-plugin 开启缓存,代码压缩的时候,提升压缩速度
3)cache-loader或者hard-source-webpack-plugin,提升模块转换阶段的速度
如果在代码层面开启了缓存,那在node_modules下有.cache目录,比如开启了babel-loader,则会生成文件夹babel-loader(node_modules/.cache/babel-loader/….),文件夹里面包含了解析出的js文件
注意:如果开启了缓存,有可能会影响到包的更新,比如在项目中安装了包a@1.0.0,后面更新成a@1.0.1,但是发现这个包的代码还是上个版本的
解决方法:就是在更新包之前要将.cache文件夹整个移除,在更新包
以hard-source-webpack-plugin为栗子:
1)安装hard-source-webpack-plugin插件
npm install -D hard-source-webpack-plugin
2)在配置文件中,引进该插件,并进行配置
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')
plugin: [
new HardSourceWebpackPlugin()
]
栗子:缩小构建目标
目的:尽可能的少构建模块,
比如:babel-loader不解析node_modules
module.exports = {
module: {
rules: [
{
test: /\.js$/,
loader: ''babel-loader,
exclude: 'node_modules
}
]
}
}
比如:减少文件搜索范围:
webpack同node查找文件的方法很相似,指定要查找的路径或者文件类型,缩小查找时间
优化resolve.modules配置(减少模块搜索层级)
优化resolve.mainFields配置
优化resolve.extensions配置
合理使用alias
resolve: {
alias: {
react: path.resolve(__dirname, ./node_modules/react/dist/react.min.js') // 直接给定取别名的路径
},
modules: [path.resolve(__dirname, 'node_modules')], // 安装第三方包是在node_modules目录下,那么在引进第三方包的时候直接到node_module目录下查找
extensions: ['.js'], // 指定查找文件的类型
mainFields: ['main'] // 发布到npm上的包会指定入口路径,即main字段的值,即查找文件只在该路径下查找
}
栗子:tree shaking(摇树优化)
概念:1个模块可能有多个方法,只要其中某个方法使用到,则整个文件就会被打包到bundle,而tree shaking只是把用到的方法打包到bundle里面,没用到的方法会在uglify阶段擦除掉
使用:webpack默认支持,在.babelrc设置modules:false即可,注意:mode:production情况下默认开启
要求:必须是ES6语法,cjs方式不支持
无用的css如何删除?
PurifyCSS:遍历代码,识别已经用到的的css class
uncss:HTML需要通过jsdom加载,所有的样式通过PostCSS解析,通过document.querySelector来识别在html文件里面不存在的选择器
在webpack中如何使用PurifyCSS
使用purgecss-webpack-plugin和min-css-extract-plugin配合使用
1)安装插件purgecss-webpack-plugin
npm i purgecss-webpack-plugin -D
2)在项目中把插件引进来
下面写法是单文件入口写法,参考地址:https://www.npmjs.com/package/purgecss-webpack-plugin
const PurgeCSSPlugin = require('purgecss-webpack-plugin')
const PATHS = {
src: path.join(__dirname, 'src')
}
plugins: [
new PurgeCSSPlugin({
paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }),
})
]
栗子:图片压缩
要求:基于Node库的imagemin或者tinypng API
使用:配置image-webpack-loader
使用参考文档:https://www.npmjs.com/package/image-webpack-loader
1)安装插件
npm install image-webpack-loader -D
2)在配置文件中设置
module.exports.module.rules = [{
test: /\.(png|jpg|jpeg|gif|svg)$/,
use: [
{
loader: 'file-loader',
options: {
name: 'img_[name][hash:8].[ext]'
}
},
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
progressive: true,
},
// 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: {
quality: 75
}
}
}
]
}]
栗子:构建体积优化,动态polyfill
使用polyfill-service:只给用户返回需要的polyfill,ua识别,下发不同的polyfill
三、通过源代码,掌握webpack打包原理
栗子:webpack启动过程分析
项目启动的时候发生了什么?
一般启动项目,我们都会砸控制台输入npm run dev等语句,然后项目就启动,或者在控制台输入webpack entry.js bundle.js也能直接运行————这个过程发生什么???
当执行上面语句的时候,npm会让命令行工具进入node_modules/.bin目录查找是否存在webpack.sh webpack.cmd文件,存在就执行,否则抛错;实际的入口文件路径:node_modules/webpack/bin/webpack.js(这里定义了命令,但是是webpack包还是webpack-cli包那个提供的命令?)
全局安装的包,会从userLocal/.bin下查找,但是webpack我们一般是局部安装,即安装到具体项目里面,所以会从项目的根目录下的node_modules/.bin去查找文件
局部安装包的时候,想再.bin目录下有这个命令,就必须在package.json的bin字段进行指定
看下node_modules/.bin/webpack文件里面定义了什么
process.exitCode = 0 // 正常执行返回
const runCommand = (command, args) => {} // 运行某个命令
const isInstalled = packageName => {} // 判断某个包是否安装了
const CLIs = [....] // webpack可以用的cli:webpack-cli webpack-command
const isntalledClis = CLIs.filter(cli => cli.installed) // 判断安装了那些cli
if (isntalledClis.length === 0) {// 根据安装数量进行处理
} else if (isntalledClis.length === 1) {
} else {
}
启动后的结果:
webpack最终找到webpack-cli(webpack-command)这个npm包,并且执行cli
栗子:webpack-cli源码阅读
还没有评论,来说两句吧...