webpack4实战记录
webpack4/rollup/parcel
为什么要构建工具?
转化es6语法
转化jsx
Css前缀补全/预处理器
压缩混淆
图片压缩
安装 nvm
nvm(Node.js Version Manager)也就是 Node.js 的包管理器,可以通过它方便安装和切换不同的Node.js版本。
./node_modules/.bin/webpack -v 查看羡慕中webpack的版本
通过npm run build运行构建,原理:
模块局部安装会在node_mudules/.bin目录创建软链接
核心概念之entry
单入口:entry是一个字符串
多入口:entry是一个对象
核心概念之output
output用来告诉webpack如何将编译后的文件输出到磁盘。
指定filename——通过占位符确保文件名称的唯一,path就可以了。
核心概念之loaders
webpack开箱即用只支持js和json两种文件类型,通过loaders去支持其他文件类型并且把他们转化成有效的模块,并可以添加到依赖图中。
Loaders本身是一个函数,接受源文件作为参数,返回转换的结果。
注意:默认情况下webpack会开启一个进程进行打包。thread-laoder用于多进程打包js和css。
核心概念之plugins
插件用于打包输出文件的优化,资源管理和环境变量注入。
作用于整个构建过程,也就是构建开始到构建结束都可以使用plugins
使用:放到plugins数组里
核心概念之mode
Mode用来指定当前的构建环境是production , development , none
设置mode 可以使用wenpack内置的函数,默认值为production
解析es6和react jsx
解析es6——babel-loader
babel的配置文件是:.babelrc
资源解析:增加es6的babel preset配置
1.plugins : 一个plugins对应一个功能
2.preset :是一系列babel plugins的集合
解析css
Css-loader用于加载.css文件,并且转换成common.js对象
Style-loader将样式通过<style>标签插入到head中
解析图片
File-loader 用于处理文件/字体
Url-loader 用于处理文件/字体,也可以设置较小资源自动base64,增加一个limit参数
Options:{
Limit:10240 //代表10240字节,就是10K
}
webpack中文件的监听
文件监听是在发现源码发生变化时,自动重新构建出新的输出文件。
Webpack开启监听模式,有两种方式:
1.启动webpack命令时,带上- -watch参数
使用:npm run watch 缺陷:每次都需要手动刷新浏览器
2.在配置webpack.config.js中设置watch:true
文件监听的原理分析:
轮询判断文件的最后编辑时间时候变化,
某个文件发生了变化,并不会立刻告诉监听者,而是先缓存起来,等aggregateTimeout
Module.export = {
//默认fasle,也就是不开启
watch:true,
//只有开启监听模式,watchoptions才有意义
watchOptions: {
//默认为空,不监听的文件或者文件夹,支持正则
ignored: /node_modules/,
//监听到变化发生后,等300ms再去执行,默认300ms
aggregateTimeout:300,
//判断文件是否发生变化是通过不停询问文件系统指定文件有没有变化实现的,默认每秒问1000次
poll:1000
}
}
热更新:webpack-dev-server
WDS不刷新浏览器
WDS不输出文件,而是放在内存中,而不是像watch一样,放在本地磁盘中,它没有I/O
使用HotModuleReplacementPlugin插件
dev: webpack-dev-srever —open
plugin: [
new webpack.HotModuleReplacementPlugin() //可以不加,也会自动配置
],
devServer: {
contentBase:’/dist’,
hot:true
}
热更新:webpack-dev-middleware
需要在用express或者koa创建一个node server
WDM将webpack输出的文件传输给服务器
适用于灵活的定制场景
热更新原理分析:
webpack Compile:将js 编译成Bundle
HMR server:将热更新文件输出给HMR Rumtime
Bundle server:提供文件在浏览器的访问
HMR Rumtime:会被注入到浏览器,更新文件的变化
Bundle.js:构建输出的文件
HMR Server 是服务端,用来将变化的 js 模块通过 websocket 的消息通知给浏览器端。
HMR Runtime是浏览器端,用于接受 HMR Server 传递的模块数据,浏览器端可以看到 .hot-update.json 的文件过来。
webpack 构建出来的 bundle.js 本身是不具备热更新的能力的,HotModuleReplacementPlugin 的作用就是将 HMR runtime 注入到 bundle.js,使得bundle.js可以和HMR server建立websocket的通信连接
文件指纹策略:chunkhash,contenthash , hash
文件指纹:打包后输出文件名的后缀,通常做一些版本的管理
文件指纹的生成 :
Hash: 和这个项目的构建有关,只要项目文件有修改,整个项目构建的hash值就会更改
chunkhash : 和webpack打包的chunk有关,不用的entry会生成不同的chunkhash值
contenthash : 根据文件内容来定义hash,文件内容不变,则contenthash不变
js文件指纹设置:设置output的filename,使用filename:’[name][chunkhash:8].js’
Css文件指纹设置:设置minicssExtractPlugin的filename,使用[contenthash]
Plugin:[
new minicssExtractPlugin({
filename:’[name][contenthash:8].css’
})
]
图片文件指纹设置:设置file-loader的name,使用[hash]
Options:{
name:’img/[name][hash:8].[ext]’
}
占位符名称 含义
[ext] 资源后缀名
[name] 文件名称
[path] 文件的相对路径
[floder] 文件的所在文件夹
[contenthash] 文件的内容hash,默认是md5生成
[hash] 文件的内容hash,默认是md5生成
[emoj] 一个随机的指定文件内容的emoj
代码压缩
Html压缩 修改html-webpack-plugin,设置压缩参数(一个页面对应一个html-webpack-plugin)
Css压缩 使用optimize-css-assets-webpack-plugin,同时使用cssnano
js压缩 webpack4中内置了uglifyjs-webpack-plugin
自动清理构建目录产物
1.通过npm scripts清理构建目录
rm -rf ./dist && wegpack
rimraf ./dist && webpack
2.为了避免构建前每次都需要手动删除dist
使用clean-webpack-plugin 默认会删除output指定的输出目录
postcss插件autoprefixer自动补齐css3前缀
css媒体查询实现响应式布局
缺陷:需要写多套适配样式代码
w3c对rem的定义:font-size of the root element , rem为相对单位。
lib-flexible 页面渲染时计算根元素的font-size值,可以使用手淘的lib-flexible库
移动端css px自动转换成rem 使用postcss-plugin-px2rem
资源内联的意义
1.代码层面:
页面框架的初始化脚本(比如页面加载时候rem的计算)
上报相关打点(css,js加载完成,初始化都需要内联到代码中)
css内联避免页面闪动(首屏或者是页面的css内联到html中,这样子加载的时候避免页面闪动)
2.请求层面:减少http网络请求数
小图片或者字体内联(url-loader)
html和js内联
Raw-loader内联html
<script>{require(‘raw-loader!babel-laoder!../node_modules/lib-flexible/lib-flexible.js’)}</script>
css内联
1.借助style-loader
2.html-inline-css-webpack-plugin
多页面通用打包方案
多页面应用(MPA)
每一次页面跳转的时候,后台服务器都会给返回一个新的html文档
这种类型的网站也就是多页网站,也叫做多页应用
之前我们需要一个entry,一个html-webpack-plugin
现在:动态的获取entry和设置html-webpack-plugin的数量
利用glob库(glob原理:类似linux下文件通配,匹配的概念)
glob.sync把文件以同步的方式查找出来
entry:glob.sync(path.join(__dirname,’./src/*/index.js’))
source map
作用:通过source map定位到源码
开发环境开启,线上环境关闭
线上排查问题的时候可以将sourcemap上传到错误监控系统
source map 关键字
eval:使用Eval包裹模块代码
source map :产生.map文件
cheap:不包含列信息
Inline : 将.map作为dataurl嵌入,不单独生成.map文件
module : 包含loader的sourcemap
提取页面公共资源
1.基础库分离
思路:将react,react-dom基础包通过cdn引入,不打入bundle中
方法:使用html-webpack-externals-plugin
2.利用splitChunksPlugin进行公共脚本分离
webpack4内置的,替代commonsChunkPlugin插件
chunks参数说明:
async异步引入的库进行分离(默认)
Initial同步引入的库进行分离
all所有引入的库进行分离 (推荐)
3.利用splitChunksPlugin进行分离基础包
test:匹配出需要分离的包
tree shaking(摇树优化)
概念:1个模块可能有多个方法,只要其中的某个方法使用到了,则整个文件都会被打到bundle里面去,tree shaking就是把用到的方法打入bundle,没用到的放大会在uglify阶段被擦除掉。
使用:webpack4默认支持,在.babelrc里设置modules:false即可
production mode的情况下默认开启
要求:必须是es6语法,cjs的方式不支持
Tree-shaking原理:
利用es6模块的特点:
只能作为模块顶层的语句出现
Import的模块名只能是字符串常量
Import binding是immutable的
代码擦除:uglify阶段删除无用的代码
现象:构建后的代码存在大量的闭包代码
会导致的问题:
1.大量函数闭包包裹代码,导致体积增大(模块越多越明显)
2.运行代码时创建的函数作用域变多,内存开销变大
模块转换分析:
被webpack转换后的模块会带上一层包裹
import会被转换成__webpack_require
进一步分析webpack的模块机制
打包出来的是一个llFE
modules是一个数组,每一项是一个模块初始化函数
__wbepack_require用来加载模块,返回modules.exports
通过WEBPACK_REQUIRE_METHOD(0)启动程序
Scope hoisting使用和原理
原理:将所有模块的代码按照引用顺序放在一个函数作用域里,然后适当的重命名一些变量以防止变量名冲突
对比:通过Scope hoisting可以减少函数声明代码和内存开销
使用:webpack mode为production默认开启
注意:必须是es6语法,cjs不支持
代码分割
懒加载js脚本的方式
1.common.js:require
2.es6:动态import(目前原生不支持,需要babel转换)
安装@babel/plugin-syntax-dynaic-import
在.babelrc文件中:
“plugins”:[‘@babel/plugin-syntax-dynaic-import’]
webpack中使用esLint
esLint如何执行落地?
1.和CI/CD系统集成
2.和webpack集成 eslint-config-airbnb
使用eslint-loader,构建时检查JS规范
webpack中怎么打包一个组件和一个库
实现一个大整数加法库的打包?支持ES module, CJS, AMD
未压缩版:large-number.js
压缩版: large-number.min.js
webpack中如何进行SSR?
渲染:html+css+js+data 渲染后的html
服务端:所有模块等资源都存储在服务器,内网机器拉取数据更快,一个html返回所有数据。(1个请求)
服务端渲染(SSR)的核心就是减少请求。
减少白屏时间,对于SEO友好
优化构建时命令行的显示日志
使用friendly-errors-webpack-plugin
success:构建成功的日志提示
Warning:构建警告的日志提示
Error:构建报错的日志提示
stats设置成errors-only
Plugins:[
new FriendlyErrorsWebpackPlugin()
],
stats:’errors-only’
构建异常和中断处理
echo $? 获取错误码。不为0的话就是失败的。
构建配置包设计
A.通过多个配置文件管理不同环境的构建,webpack —config参数控制
B.将构建配置设计成一个库,比如: hjs-webpack、Neutrino、webpack-blocks
C.抽成一个工具进行管理,比如:create-react-app, kit, nwb
D.将所有的配置放在一个文件,通过—env参数控制分支选择
构建包功能模块设计和目录结构