1 安装webpack


  1. npm init -y

  1. npm webpack webpack-cli
  1. 查看webpack安装的版本
  1. node_modules/.bin/webpack -v

2 最简单的例子

  1. 编写webpack.config.js文件
  1. 'use strict'
  2. const path = require('path')
  3. module.exports = {
  4. entry: './src/index.js',
  5. output: {
  6. path: path.join(__dirname, 'dist'),
  7. filename: 'boundle.js'
  8. },
  9. mode: 'production'
  10. }

执行node_modules/.bin/webpack

3 通过npm运行webpack


  1. {
  2. "name": "webpackGeek",
  3. "version": "1.0.0",
  4. "description": "一个用来练习webpack的项目",
  5. "main": "index.js",
  6. "scripts": {
  7. "test": "echo \"Error: no test specified\" && exit 1",
  8. "build": "webpack"
  9. },
  10. "keywords": [],
  11. "author": "",
  12. "license": "ISC",
  13. "devDependencies": {
  14. "webpack": "^4.41.2",
  15. "webpack-cli": "^3.3.10"
  16. }
  17. }

模块局部安装会在node_module/.bin目录下创建软连接

4 entry的用法

entry 入口起点,表示webpack应该使用哪个模块来作为构建其内部依赖图的开始。

  1. 单文件
  1. entry: './src/index.js'
  1. 多文件
  1. entry: {
  2. app: '',
  3. appadmin: ''
  4. }

5 output

  1. 对于单文件入口的output配置
  1. module.exports = {
  2. entry: './src/index.js'
  3. output: {
  4. path: __dirname + '/dist',
  5. filename: 'bundle'
  6. }
  7. }
  1. 对于多文件文件入口的output配置
  1. module.exports = {
  2. entry: {
  3. app: '',
  4. appadmin: ''
  5. }
  6. output: {
  7. path: __dirname + '/dist',
  8. filename: '[name].js' // 占位符的设置 文件名会是入口文件的key
  9. }
  10. }

6 loader

webpack开箱默认只支持js和json两种文件类型,通过loader来支持其他文件类型。
本身是一个函数,接受源文件作为参数,返回转换的结果。

  1. module: {
  2. rules:[
  3. {test: /\.txt$/, use: 'raw-loader'}
  4. // test 指定匹配规则 use: 指定使用的loader
  5. ]
  6. }

常用的loader

  1. babel-loader 转换es6 7 =>es5
  2. css-loader
  3. less-loader
  4. ts-loader
  5. file-loader 图片字体的打包
  6. raw-loader 将文件以字符串的形式导入
  7. thred-loader 多进程打包

7 plugins

通过loader做不到的事情都可以使用plugins,例如:构建文件的清理
插件用于bundle文件的优化,资源管理和环境变量注入,作用于整个构建过程
常见的plugins

名称 作用
CommonsChunkPlugin 将chunks相同的模块代码提取成公共js
CleanWebpackPlugin 清理构建目录
ExtractTextWebpackPlugin 将css从bundle文件里提取成一个独立的css文件
CopyWebpackPlugin 将文件或者文件夹拷贝到构建的输出目录
HtmlWebpackPlugin 创建html文件去承载输出的bundle
UglifyjsWebpackPlugin 压缩js
ZipWebpackPlugin 将打包出的资源生成一个zip包
  1. plugins: [
  2. new HtmlWebpackPlugin({
  3. tempalte: './src/index.html'
  4. })
  5. ]

8 mode

  1. module.export = {
  2. mode: 'production'
  3. }
选项 描述
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 -D
npm i react react-dom @babel/preset-react -D

  1. 添加.babelrc文件
  1. {
  2. "presets": [
  3. "@babel/preset-env",
  4. "@babel/preset-react"
  5. ]
  6. }
  1. 添加babel-loader
  1. module:{
  2. rules:[
  3. { test:/\.js$/, use:'babel-loader' }
  4. ]
  5. }

10 解析css less 和scss

  1. 安装相应的loader

npm i style-loader css-loader -D

npm i less less-loader -D

css-loader 加载css文件,并转换成commonjs对象
style-loader 将样式通过<style>标签插入到head中

  1. 配置
  1. module: {
  2. rules: [
  3. {
  4. test: /\.css$/,
  5. use: [
  6. 'style-less',
  7. 'css-loader'
  8. ]
  9. },
  10. {
  11. test: /\.less$/,
  12. use: [
  13. 'style-less',
  14. 'css-loader',
  15. 'less-loader'
  16. ]
  17. }
  18. ]
  19. }

use链式调用,先调用右边的,再调用左边的

11 解析图片和字体

  1. 安装file-loadernpm i file-loader -D
  1. {
  2. test: /.(png|jpg|svg|gif)$/,
  3. use: [
  4. 'file-loader'
  5. ]
  6. },
  7. {
  8. test: /.(ttf|woff|woff2|eot|otf)$/,
  9. use: [
  10. 'file-loader'
  11. ]
  12. }
  1. url-loader也可以处理图片和字体, 可以设置较小资源自动转base64
  1. {
  2. test: /.(png|jpg|svg|gif)$/,
  3. use: [
  4. {
  5. loader: 'url-loader',
  6. options: {
  7. limit: 10240
  8. }
  9. }
  10. ]
  11. }

12 webpack中的文件监听

webpack开启监听模式

  1. 启动webpack命令时,带上—watch参数
  2. 在webpack.config.js 中设置watch: true

文件监听的原理分析

  • 轮询判断文件的最后编辑时间是否发生变化
  • 某个文件发生了变化,并不会立刻告诉监听者,而是先缓存起来,等aggregateTimeout
  1. module.exports = {
  2. watch: true, // 默认为false,也就是不开启
  3. // 只有watch开启,watchOptions才有意义
  4. watchOptions: {
  5. ignored: /node_modules/, // 默认为空,不监听的文件活文件夹,支持正则匹配
  6. aggregateTimeout: 300, // 监听到变化后会等300ms再去执行,默认300ms
  7. // 判断文件是否发生变化是通过不停询问系统指定文件又没有发生变化实现的,默认美秒询问1000次
  8. poll: 1000
  9. }
  10. }

13 webpack中热更新及原理分析

热更新

  1. WDS不刷新浏览器
  2. WDS不输出文件,而是放在内存中
  3. 使用HotModuleReplacementPlugin()插件

packagejson.js新增配置
npm i webpack-dev-server -D
“dev”:”webpack-dev-server —open”
webpack.config.js新增配置

  1. dev:"development" // 开发模式启用
  2. plugins:[
  3. new webpack.NamedModulesPlugin(),// 以便更容易查看要修补(patch)的依赖
  4. new webpack.HotModuleReplacementPlugin()
  5. ],
  6. devServer:{
  7. contentBase: './dist',
  8. hot: true // 可以不引入上面的HotModuleReplacementPlugin(),hot开启后,会自动引入
  9. }
  • 疑问解答:

这里面的热更新有最核心的是 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
  1. WDM将文件输出给服务器
  2. 适用于灵活定制场景

image.png
大体分为两个阶段

  1. 启动阶段,1-2-A-B
  2. 热更新阶段, 1-2-3-4-5

    14 文件指纹策略,chunkhash, contenthash 和hash

  3. hash 和整个项目的构建相关,只要项目文件有修改,整个项目构建的hash值就会修改。(使用频率不高)

  4. chunkhash 和webpack打包的chunk相关,不同的entry会生成不同的chunkhash值。(js通常使用)
  5. contenthash 根据文件的内容来定义hash,文件内容不变,contenthash值就不变(css和file图片通常使用)

整个配置应该是属于生产环境的配置
js的chuankhash设置

  1. module. exports = {
  2. output:{
  3. path: __dirname+'/dist',
  4. filename: '[name]_[chunkhash:8].js' // :8代表取hash值的前8位,总共32位
  5. }
  6. }

文件指纹(图片,字体等)
image.png
图片的hash值的解释就是contenthash

  1. {
  2. test: /.(png|jpg|svg|gif)$/,// test: /.(ttf|woff|woff2|eot|otf)$/,字体也是一样的
  3. use: [
  4. {
  5. loader: "file-loader",
  6. options: {
  7. name: "[name]_[hash:8].[ext]"
  8. }
  9. }
  10. ]
  11. }

image.png
记得删除热替换的插件,否则会影响contenthash
css的contenthash的设置,

  1. 安装npm i mini-css-xtract-plugin -D
  2. 此插件和style-loader插件冲突,详见配置
  3. webpack配置
  1. const MiniCssExtractPlugin = require("mini-css-extract-plugin");
  2. module.exports = {
  3. module:{
  4. rules:[
  5. {
  6. test: /.css$/,
  7. use: [MiniCssExtractPlugin.loader, 'css-loader']
  8. },
  9. {
  10. test: /.less$/,
  11. use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"]
  12. },
  13. ]
  14. },
  15. plugins:[
  16. new MiniCssExtractPlugin({
  17. filename: "[name]_[contenthash:8].css"
  18. })
  19. ]
  20. }

15 HTML CSS JavaScript代码压缩

  1. javascript压缩,webpack4默认开启js压缩,但是你也可以使用uglifyjs-webpack-js
  2. css压缩npm i optimize-css-assets-webpack-plugin -D

npm i cssnano -D

  1. plugins:[
  2. new OptimizeCssAssetsWebpackPlugin({
  3. assetNameRegExp: /.css$/g,
  4. cssProcessor: require('cssnano')
  5. })
  6. ]
  1. html压缩
  1. new htmlWebpackPlugin({
  2. template: path.join(__dirname, 'src/index.html'),// 模版页
  3. filename: 'index.html',// 输出的文件名
  4. chunks:['index'], // 使用的chunk的代码,通常多页面打包需要,但页面可以不填写
  5. inject: true,
  6. minify: {
  7. html5: true,
  8. collapseWhitespace: true,
  9. preserveLineBreaks: false,
  10. minifyCSS: true,
  11. minifyJS: true,
  12. removeComments: false
  13. }
  14. })