1 安装webpack
npm init -y
npm webpack webpack-cli
- 查看webpack安装的版本
node_modules/.bin/webpack -v
2 最简单的例子
- 编写webpack.config.js文件
'use strict'const path = require('path')module.exports = {entry: './src/index.js',output: {path: path.join(__dirname, 'dist'),filename: 'boundle.js'},mode: 'production'}
执行node_modules/.bin/webpack
3 通过npm运行webpack
{"name": "webpackGeek","version": "1.0.0","description": "一个用来练习webpack的项目","main": "index.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1","build": "webpack"},"keywords": [],"author": "","license": "ISC","devDependencies": {"webpack": "^4.41.2","webpack-cli": "^3.3.10"}}
模块局部安装会在node_module/.bin目录下创建软连接
4 entry的用法
entry 入口起点,表示webpack应该使用哪个模块来作为构建其内部依赖图的开始。
- 单文件
entry: './src/index.js'
- 多文件
entry: {app: '',appadmin: ''}
5 output
- 对于单文件入口的output配置
module.exports = {entry: './src/index.js',output: {path: __dirname + '/dist',filename: 'bundle'}}
- 对于多文件文件入口的output配置
module.exports = {entry: {app: '',appadmin: ''}output: {path: __dirname + '/dist',filename: '[name].js' // 占位符的设置 文件名会是入口文件的key}}
6 loader
webpack开箱默认只支持js和json两种文件类型,通过loader来支持其他文件类型。
本身是一个函数,接受源文件作为参数,返回转换的结果。
module: {rules:[{test: /\.txt$/, use: 'raw-loader'}// test 指定匹配规则 use: 指定使用的loader]}
常用的loader
- babel-loader 转换es6 7 =>es5
- css-loader
- less-loader
- ts-loader
- file-loader 图片字体的打包
- raw-loader 将文件以字符串的形式导入
- thred-loader 多进程打包
7 plugins
通过loader做不到的事情都可以使用plugins,例如:构建文件的清理
插件用于bundle文件的优化,资源管理和环境变量注入,作用于整个构建过程
常见的plugins
| 名称 | 作用 |
|---|---|
| CommonsChunkPlugin | 将chunks相同的模块代码提取成公共js |
| CleanWebpackPlugin | 清理构建目录 |
| ExtractTextWebpackPlugin | 将css从bundle文件里提取成一个独立的css文件 |
| CopyWebpackPlugin | 将文件或者文件夹拷贝到构建的输出目录 |
| HtmlWebpackPlugin | 创建html文件去承载输出的bundle |
| UglifyjsWebpackPlugin | 压缩js |
| ZipWebpackPlugin | 将打包出的资源生成一个zip包 |
plugins: [new HtmlWebpackPlugin({tempalte: './src/index.html'})]
8 mode
module.export = {mode: 'production'}
| 选项 | 描述 |
|---|---|
| development | 会将 process.env.NODE_ENV 的值设为 development。启用 NamedChunksPlugin 和 NamedModulesPlugin。 |
| production | 会将 process.env.NODE_ENV 的值设为 production。启用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 UglifyJsPlugin. |
| node | 不开启任何优化效果 |
9 编译ECMAScript6 和 React JSX
添加必要依赖npm i @babel/core @babel/preset-env babel-loader -Dnpm i react react-dom @babel/preset-react -D
- 添加.babelrc文件
{"presets": ["@babel/preset-env","@babel/preset-react"]}
- 添加babel-loader
module:{rules:[{ test:/\.js$/, use:'babel-loader' }]}
10 解析css less 和scss
- 安装相应的loader
npm i style-loader css-loader -D
npm i less less-loader -D
css-loader 加载css文件,并转换成commonjs对象
style-loader 将样式通过<style>标签插入到head中
- 配置
module: {rules: [{test: /\.css$/,use: ['style-less','css-loader']},{test: /\.less$/,use: ['style-less','css-loader','less-loader']}]}
use链式调用,先调用右边的,再调用左边的
11 解析图片和字体
- 安装file-loader
npm i file-loader -D
{test: /.(png|jpg|svg|gif)$/,use: ['file-loader']},{test: /.(ttf|woff|woff2|eot|otf)$/,use: ['file-loader']}
- url-loader也可以处理图片和字体, 可以设置较小资源自动转base64
{test: /.(png|jpg|svg|gif)$/,use: [{loader: 'url-loader',options: {limit: 10240}}]}
12 webpack中的文件监听
webpack开启监听模式
- 启动webpack命令时,带上—watch参数
- 在webpack.config.js 中设置watch: true
文件监听的原理分析
- 轮询判断文件的最后编辑时间是否发生变化
- 某个文件发生了变化,并不会立刻告诉监听者,而是先缓存起来,等aggregateTimeout
module.exports = {watch: true, // 默认为false,也就是不开启// 只有watch开启,watchOptions才有意义watchOptions: {ignored: /node_modules/, // 默认为空,不监听的文件活文件夹,支持正则匹配aggregateTimeout: 300, // 监听到变化后会等300ms再去执行,默认300ms// 判断文件是否发生变化是通过不停询问系统指定文件又没有发生变化实现的,默认美秒询问1000次poll: 1000}}
13 webpack中热更新及原理分析
热更新
- WDS不刷新浏览器
- WDS不输出文件,而是放在内存中
- 使用HotModuleReplacementPlugin()插件
packagejson.js新增配置npm i webpack-dev-server -D
“dev”:”webpack-dev-server —open”
webpack.config.js新增配置
dev:"development" // 开发模式启用plugins:[new webpack.NamedModulesPlugin(),// 以便更容易查看要修补(patch)的依赖new webpack.HotModuleReplacementPlugin()],devServer:{contentBase: './dist',hot: true // 可以不引入上面的HotModuleReplacementPlugin(),hot开启后,会自动引入}
- 疑问解答:
这里面的热更新有最核心的是 HMR Server 和 HMR runtime。
HMR Server 是服务端,用来将变化的 js 模块通过 websocket 的消息通知给浏览器端。
HMR Runtime是浏览器端,用于接受 HMR Server 传递的模块数据,浏览器端可以看到 .hot-update.json 的文件过来。
继续回到这个问题:老师HotModuleReplacementPlugin是做什么用的?
webpack 构建出来的 bundle.js 本身是不具备热更新的能力的,HotModuleReplacementPlugin 的作用就是将 HMR runtime 注入到 bundle.js,使得bundle.js可以和HMR server建立websocket的通信连接
- 还可以使用webpack-dev-middleware
- WDM将文件输出给服务器
- 适用于灵活定制场景

大体分为两个阶段
- 启动阶段,1-2-A-B
-
14 文件指纹策略,chunkhash, contenthash 和hash
hash 和整个项目的构建相关,只要项目文件有修改,整个项目构建的hash值就会修改。(使用频率不高)
- chunkhash 和webpack打包的chunk相关,不同的entry会生成不同的chunkhash值。(js通常使用)
- contenthash 根据文件的内容来定义hash,文件内容不变,contenthash值就不变(css和file图片通常使用)
整个配置应该是属于生产环境的配置
js的chuankhash设置
module. exports = {output:{path: __dirname+'/dist',filename: '[name]_[chunkhash:8].js' // :8代表取hash值的前8位,总共32位}}
文件指纹(图片,字体等)
图片的hash值的解释就是contenthash
{test: /.(png|jpg|svg|gif)$/,// test: /.(ttf|woff|woff2|eot|otf)$/,字体也是一样的use: [{loader: "file-loader",options: {name: "[name]_[hash:8].[ext]"}}]}

记得删除热替换的插件,否则会影响contenthash
css的contenthash的设置,
- 安装
npm i mini-css-xtract-plugin -D - 此插件和style-loader插件冲突,详见配置
- webpack配置
const MiniCssExtractPlugin = require("mini-css-extract-plugin");module.exports = {module:{rules:[{test: /.css$/,use: [MiniCssExtractPlugin.loader, 'css-loader']},{test: /.less$/,use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"]},]},plugins:[new MiniCssExtractPlugin({filename: "[name]_[contenthash:8].css"})]}
15 HTML CSS JavaScript代码压缩
- javascript压缩,webpack4默认开启js压缩,但是你也可以使用uglifyjs-webpack-js
- css压缩
npm i optimize-css-assets-webpack-plugin -D
npm i cssnano -D
plugins:[new OptimizeCssAssetsWebpackPlugin({assetNameRegExp: /.css$/g,cssProcessor: require('cssnano')})]
- html压缩
new htmlWebpackPlugin({template: path.join(__dirname, 'src/index.html'),// 模版页filename: 'index.html',// 输出的文件名chunks:['index'], // 使用的chunk的代码,通常多页面打包需要,但页面可以不填写inject: true,minify: {html5: true,collapseWhitespace: true,preserveLineBreaks: false,minifyCSS: true,minifyJS: true,removeComments: false}})
