Webpack 基础用法及解析
-
loader特点
- loader的执行顺序和代码书写的顺序是相反的,即:最后一个loader最先执行,第一个loader最后执行
- 第一个执行的loader会接收源文件做为参数,下一次执行的loader会接收前一个loader执行的返回值做为参数
use
属性的值需要是一个由 Loader 名称组成的数组,Loader 的执行顺序是由后到前的;- 每一个 Loader 都可以通过 URL querystring 的方式传入参数,例如
css-loader?minimize
中的minimize
告诉css-loader
要开启 CSS 压缩。
-
loader编写原则
- 单一原则: 每个 Loader 只做一件事;
- 链式调用: Webpack 会按顺序链式调用每个 Loader;
- 统一原则: 遵循 Webpack 制定的设计规则和结构,输入与输出均为字符串,各个 Loader 完全独立,即插即用;
-
解析
ES6
-
使用
babel-loader
,babel
的配置文件是.babelrc
-
npm i @babel/core @babel/preset-env babel-loader -D
-
-
解析
CSS
-
CSS-loader
用于加载.css
文件,并且转换成commonjs
对象 -
style-loader
将样式通过<style>
标签插入到head
中 -
npm i style-loader css-loader -D
-
loader
的调用是链式调用的,因此需要将style-loader
放至css-loader
之前
-
-
解析
less
和sass
-
npm i less less-loader -D
-
-
解析图片
-
file-loader
用于处理文件 -
npm i file-loader -D
-
-
使用
url-loader
-
url-loader
也可以处理图片和字体,可以设置较小资源自动base64
-
npm i url-loader -D
-
接收一个参数
options
-
module:{ rules:[ { test:/\.(png|svg|jpg|gif)$/, use:[ loader:'url-loader', options{ limit:10240 } ] } ] }
-
-
-
webpack
文件监听-
文件监听是在发现源码发生改变时,自动重新构建出新的输出文件
-
webpack
开启监听模式,有俩种方式:-
启动
webpack
命令时,带上--watch
参数-
"scripts":{ "build":"webpack", "watch":"webpack --watch" } /*******唯一缺陷:每次需要手动刷新浏览器*******/ npm run watch
-
watch
是放进本地的磁盘中去扫描二维码关注公众号,回复: 8781251 查看本文章
-
-
在配置
webpack.config.js
中设置watch:true
-
-
-
文件监听的原理分析
-
轮询判断文件的最后编辑时间是否变化
-
某个文件发生了变化,并不会立刻告诉监听者,二十先缓存起来,等
aggregateTimeout
-
module.export = { //默认 false ,也就是不开启 watch : true, //只有开启监听模式, watchOptions 才有意义 watchOptions:{ //默认为空,不监听的文件或者文件夹,支持正则匹配 ignored:/node_modules/,//不监听node_modules,会提升性能 //监听到变化发生后会等300ms 再去执行,默认300ms, aggregateTimeout:300, //判断文件是否发生变化是通过不停询问系统指定文件有没有变化实现的,默认每秒问1000次 poll:1000 } }
-
webpack
的热更新及原理分析-
热更新:
webpack-dev-server
-
WDS
不刷新浏览器 -
WDS
不输出文件,而是放在内存中 -
WDS
优势:是没有磁盘的IO
,构建速度会更快 -
使用
HotModuleReplacementPlugin
插件 -
"scripts":{ "build":"webpack", "dev":"webpack-dev-server--open" }
-
启用
热模块更换
,也称为HMR
,HMR 绝对不能在生产中使用。 -
首先导入 webpack const webpack = require('webpack') 将 mode 换成开发环境 , mode: development plugins:[ new webpack.HotModuleReplacementPlugin({ // Options... }); ], devServer:{ //contentbase代表html页面所在的相对目录,如果我们不配置项,devServer默认html所在的目 //录就是项目的根目录 contentBase:'./dist', hot:true }
-
-
热更新:使用
webpack-dev-middleware
-
WDM
将webpack
输出的文件传输给服务器 -
适用于灵活的定制场景
-
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = { mode: 'development', entry: { app: './src/index.js', print: './src/print.js', }, devtool: 'inline-source-map', devServer: { contentBase: './dist', }, plugins: [ new CleanWebpackPlugin(), new HtmlWebpackPlugin({ title: 'Output Management', }), ], output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist'), + publicPath: '/', }, };
-
-
热更新原理分析
Webpack Compile
:将JS
编译成Bundle
HMR Serve
:将热更新的文件输出给HMR Rumtime
Bundle server
:提供文件在浏览器的访问HMR Rumtime
:会被注入到浏览器,更新文件的变化bundle.js
:构建输出的文件- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hbMvjE6w-1579333594145)(C:\Users\36584\AppData\Roaming\Typora\typora-user-images\1579312892510.png)]
-
热更新的过程
- 启动阶段,是在文件系统进行编译,将初始代码进行
Webpack Compile
进行打包编译 ,打包之后,把编译好的文件传输给Bundle Server
,(Bundle Server
其实就是一个服务器),就可以让浏览器访问 1 ==> 2 ==> A ==> B - 本地文件变更阶段,还是会经过
Webpack Compile
编译,服务端HMR Server
通知浏览器端HMR Runtime
,之后更新代码
- 启动阶段,是在文件系统进行编译,将初始代码进行
-
什么是文件指纹 生产环境中
- 打包输出的文件名的后缀
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-95Xv6ijI-1579333594156)(C:\Users\36584\AppData\Roaming\Typora\typora-user-images\1579317143791.png)]
- 文件指纹好处:作为版本的管理,发版的时候只会更新变更的文件,替换其变更的文件指纹,其余不变,另外,对于没有修改的,会使用本地的缓存,加快访问
文件指纹如何生成
Hash
:和整个的项目的构建相关,只要项目文件有修改,整个项目构建的hash
值就会更改Chunkhash
:和webpack
打包的chunk
有关,不同的entry
会生成不同的chunkhahs
值Contentthash
:跟还有文件内容来定义hash
,文件内容不变,则contenthash
不变,比如修改js
但是css
并没有修改,此时css
并不需要更换文件指纹
JS
的文件指纹设置
-
设置
output
的filename
,使用[chunkhash]
-
output :{ filename:'[name][chunkhash:8].js', path:_dirname + '/dist' }
-
CSS
的文件指纹设置
-
设置
NibiCssExtractPlugin
的filename
使用[contenthash]
-
npm i mini-css-extract-plugin -D
-
plugins:[ new MiniCssExtractPlugin({ filename:'[name][contenthash:8]' }) ]
-
插件是把
css
独立提取为一个文件,插件的loader
是无法与style-loader
同时使用,因为它们之间的功能是互斥的,style-loader
是把样式提取到heade
里面,而插件是将其提取出来,所以在使用的时候是将style-loader
替换成MiniCssExtractPlugin.loader
-
图片的文件指纹设置
-
设置
file-loader
的name,使用[hash]
-
module :{ rules:[{ test:/\.(png|svg|jpg|gif)$/, use:[{ loader:'file-loader', options:{ name:'img/[name][hash:8].[ext]' } }] }] } //hash:8 取哈希值的前8位,md 是有32位 //[ext] 图片的后缀
-
代码压缩
JS
文件的压缩- 内置了
uglifyjs-webpack-plugins
- 内置了
CSS
文件的压缩
-
使用
optimeize-css-assets-webpack-plugin
-
同时使用
cssnano
-
plugins:[ new OptimeizeCSSAssetsPlugin({ assetNameRegExp:/\.css$/g, cssProcessor:require('cssnano') }) ]
html
文件得压缩
-
修改
html-webpack-plugin
,设置压缩参数 -
plugins:[ new HtmlWebpackPlugin({ template:path.join(_dirname,'src/search.html'), filename:'search.html', //指定打包出来之后得文件名称 chunks:['search'], inject:true, minify:{ html:true, collapseWhitespace:true, preserveLineBreaks:false, minifyCSS:true, minifyJS:true, removeComments:false } }) ]