webpack基本使用详解
我们现在只学webpack的基本使用,在后续webpack高级中,coderwhy老师还会教手写loader这些,面向25k开发的。
webpack依赖图
webpack打包的时候,会先找那个入口文件(默认index.js,找不到就报错,我们可以用命令或者在webpack.conig.js配置文件中指定入口文件),然后打包入口文件,发现入口文件又导入了其他模块,就又会打包其他模块,最终生成浏览器可以识别的静态代码。
tips:默认webpack只打包js的,那些css等文件需要使用对应的loader
比如vue框架,webpack本身是打包不了.vue文件的,但是现在大家都是用webpack打包,那么vue的开发者就需要写一个vue的loder出来供webpack使用识别.vue文件
css-loader的使用
内联式和cli方式
方式三常用
我们要使用loder,就必须安装loader,命令npm install css-loader -D (因为是开发环境,所以-D)
然后我们在配置文件webpack.config.js文件中添加
module: {
rules: [
{
// 告诉webpack匹配什么文件
test: /\.css$/,
//告诉用哪个loader解析
use: [
"css-loader",
]
}
]
}
但是我们发现,虽然能打包了,但是css不生效,因为css-loader只解析css,但是不会把css插入到html
我们还需要一个style-loader,照样是先安装后写入配置,主要use数组里面的loader是从下面往上面执行(如果是缩写,就从右向左),所以得先css-loader解析,后style-loader插入。
我们loader有简写方法,但是不建议。
全称如use是一个数组,里面的没一个loader都是一个对象,但是如果我们不需要对这个loader配置,可以不写loader对象,直接写名称。不过当你要配置又要改回全称,还不如起初就全称。
这些css和less如果直接引入对应的解析和插入loader确实可以生效,但是是通过内联式,也就是插入在index.html的style标签中生效的,如果需要单独生成一个css文件,需要做高级配置。
less文件的解析同理,安装一个less-loader即可。
const path = require("path")
module.exports = {
entry: "./src/main.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "./build")
},
module: {
rules: [
{
// 告诉webpack匹配什么文件
test: /\.css$/,
// use: [ // use中多个loader的使用顺序是从后往前
// { loader: "style-loader" },
// { loader: "css-loader" }
// ],
// 简写一: 如果loader只有一个
// loader: "css-loader"
// 简写二: 多个loader不需要其他属性时, 可以直接写loader字符串形式
use: [
"style-loader",
"css-loader",
"postcss-loader"
// {
// loader: "postcss-loader",
// options: {
// postcssOptions: {
// plugins: [
// "autoprefixer"
// ]
// }
// }
// }
]
},
{
test: /\.less$/,
use: [ "style-loader", "css-loader", "less-loader", "postcss-loader" ]
}
]
}
}
tips:css中有一个user-select:none属性,可以让用户无法选中内容
但是这个属性可能是不兼容一些浏览器的,所以得加前缀如-ms-user-select:none;-webkit-user-select
那我咋全知道哪些浏览器兼容哪些属性?一个个记吗?所以webpack中有一个postcss-loader可以自动判断,并帮我们添加前缀。
我们加了postcss-loader还是不行,因为它只是一个工具,你想使用它,还需要借助一个插件autoprefixer(也得npm install)。自动前缀的意思
我们需要把插件写进postcss-loader里面的option配置中,然后postcssOption插件plugin中
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"autoprefixer"
]
}
}
如果把这段代码写在webpack.confog.js中绝的各种配置太繁琐太难管理的话,可以单独抽取到一个postcss-config.js中(webpack的config中找不到,它会自动再寻找postcss-config.js)
好处:我们postcss不一定就css使用,less中也可能要使用,那么在less匹配的loader中也就要加配置代码,抽取到单独文件中,就避免了这一操作。
单独配置文件的代码格式又和在webpack配置中写的格式不同,这都是loader的开发者自己定义的,我们记住就好了,其实也不需要记,因为我们现在是为了方便了解webpack的工作流程,所以学习这些东西,实际开发中这些配置脚手架都会帮我们配好。
问题:为什么建立了postcss.config.js,webpack中的loader就会来找这个文件读取配置,是如何绑定的?
它就是这样设置的,在这个loader被开发出来就写了这个逻辑,应该是通过名字绑定loader和配置文件js,如postcss-loader对应的就是postcss.config.js,通过前面那个单词来绑定。
然后通过commonjs模块化导出配置
postcss-preset-env预设
它除了可以代替autoprefixer的加前缀功能,还能把浏览器不支持的,但是我们开发代码中有的新特性css写法,转换为浏览器支持的代码。
webpack打包图片
图片怎么导入到依赖图中,从而让webpack打包?
我们直接import xxx(随便起个名字) from “图片路径”即可,因为在webpack中任意文件其实都可以被看做一个模块。
// 引入图片模块
import zznhImage from "../img/zznh.png"
// 创建img元素
const imgEl = document.createElement("img")
imgEl.src = zznhImage
document.body.append(imgEl)
比如打包图片等文件,其实webpack5已经给我们内置了与loader相似的功能,但是webpack默认是打包js,虽然它有打包图片的功能,我们需要在webpack.config.js中配置如下
我们先匹配结尾为这些名称的文件,然后type:“asset”
tips:webpack.config.js是我们自己创造的文件,你随便写成什么名字开头都可以,比如demo.config.js
但是你在执行webpack命令的时候得带上,如npx webpack –config demo.config.js就是此次打包webpack运用那个js文件的配置。 为了方便我们通常在package.json中写一个script来包含这个命令
"scripts": {
"build": "webpack --config demo.config.js"
},
那么我们只需要执行 npm run build即可,注意别写成npx了,这个执行script不需要去node_module找,你npx反而会出错找不到了。
1-其中asset/resource运行机制是把当前图片复制了一份到build文件夹中
2-asset/inline是把图片base64编码到了js文件中
3-resource方法会增加一次网络请求,inline方式会让js文件变的很大(会导致页面渲染慢),所以我们一般把大的图片用resource方法,小图片用inline方法
4-我们在type:“asset”,就写一个asset的话,配合paeser属性中的maxSize可以设置,自动判断大于多大的图片用resource,否则inline
tips:这些配置什么的单词很多,没必要记,知道有这个东西,会查阅文档就好了。
const path = require("path")
const { VueLoaderPlugin } = require("vue-loader/dist/index")
module.exports = {
entry: "./src/main.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "./build"),
// assetModuleFilename: "abc.png"
},
resolve: {
extensions: [".js", ".json", ".vue", ".jsx", ".ts", ".tsx"],
alias: {
utils: path.resolve(__dirname, "./src/utils")
}
},
module: {
rules: [
{
test: /\.css$/,
use: [ "style-loader", "css-loader", "postcss-loader" ]
},
{
test: /\.less$/,
use: [ "style-loader", "css-loader", "less-loader", "postcss-loader" ]
},
{
test: /\.(png|jpe?g|svg|gif)$/,
// 1.打包两张图片, 并且这两张图片有自己的地址, 将地址设置到img/bgi中
// 缺点: 多图片加载的两次网络请求
// type: "asset/resource",
// 2.将图片进行base64的编码, 并且直接编码后的源码放到打包的js文件中
// 缺点: 造成js文件非常大, 下载js文件本身消耗时间非常长, 造成js代码的下载和解析/执行时间过长
// type: "asset/inline"
// 3.合理的规范:
// 3.1.对于小一点的图片, 可以进行base64编码
// 3.2.对于大一点的图片, 单独的图片打包, 形成url地址, 单独的请求这个url图片
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 60 * 1024
}
},
generator: {
// 占位符
// name: 指向原来的图片名称
// ext: 扩展名
// hash: webpack生成的hash
filename: "img/[name]_[hash:8][ext]"
}
},
{
test: /\.js$/,
use: [
{
loader: "babel-loader",
// options: {
// plugins: [
// "@babel/plugin-transform-arrow-functions",
// "@babel/plugin-transform-block-scoping"
// ]
// }
}
]
},
{
test: /\.vue$/,
loader: "vue-loader"
}
]
},
plugins: [
new VueLoaderPlugin()
]
}
如上的代码中的60*1024就是64kb的意思
问题:当我们很多张图片被打包复制到了build文件中,但是build文件中的代码是hash过的名字,怎么办?
我们可以使用generator属性修改
generator: {
// 占位符
// name: 指向原来的图片名称
// ext: 扩展名,如jpg,png
// hash: webpack生成的hash,:8就是截取保留八位
filename: "img/[name]_[hash:8][ext]"
}
我们一般也是用占位符命名,不会写死,因为当有多张图片,不可能叫一样的名字,这样照样无法识别。
img/的作用是在bulid中生成一个img的文件夹来保存这些被打包的图片,否则bulid里面的东西太乱了
webpack基本使用流程自我总结
1-首先npm init 生成一个package.json
2-安装webpack,npm install webpack webpack cli -D (-D是开发依赖局部安装的意思)
3-创造webpack.config.js文件。里面写webpack的配置,如使用哪些loder,打包输出的主js文件叫什么,webpack打包入口js是哪个等等各种配置。
4-从打包入口js处写入import引入代码,引入其他文件,形成依赖图,然后安装需要的各种需要的loder
5-在package.json设置一个script,让npx webpack –config webpack.config.js这行命令简化成一个script,当然你乐意敲可以不设置。(npx是因为模块的查找机制,当前路径是没有webpack的,因为是局部安装,环境变量中也没有webpack,所以npm会找不到,npx则会自动取node_module文件夹找)
6-运行webpack,得到build文件,里面就有打包好的原生js
webpack对js的打包babel作用
原先webpack一样能打包代码,但是如果我们写了es6的代码,打包后还是es6,就导致有的浏览器可能不兼容,那么如何把所有js代码转换为es5呢,就需要用到babel-loader
babel命令行的使用
它本身是一个独立的工具,可以独立使用,也可以配合webpack,在webpack中写入配置使用。
注意这里不是一个babel-loader就把代码的箭头函数和const声明方式转换了,而是用了两个插件
{
test: /\.js$/,
use: [
{
loader: "babel-loader",
// options: {
//这里注释是因为我们使用了预设,这里的代码就不需要了
// plugins: [
// "@babel/plugin-transform-arrow-functions",
// "@babel/plugin-transform-block-scoping"
// ]
// }
}
]
}
babel插件的单独配置文件
和postcss一样,babel也可以单独配置文件,防止webpack.config.js的代码太过冗杂
手动添加一个babel.config.js代码如下
module.exports = {
// plugins: [
// "@babel/plugin-transform-arrow-functions",
// "@babel/plugin-transform-block-scoping"
// ]
presets: [
"@babel/preset-env"
]
}
babel的预设
有了这个预设,箭头函数和声明方式就不需要两个插件了,只需要一个预设
上面的命令是工具单独使用,我们一般不用的,我们都是在webpack中添加配置文件,配合babel使用,代码在上面写过了。
babel的常见预设有三个
其中env就environment环境的意思。
babel的更加详细的使用和原理在工程化高级里面coderwhy老师会讲,这里我们知道有这个东西就好了。
对vue文件处理打包
我们开发vue,自然要npm install vue,注意这里不要加-D因为vue在生产和开发中都要用到,不像webpack只在我们开发的时候用到,但是这里也是局部安装,只存在于安装的这个文件内,全局安装是要-g的(vue也不会全局安装,因为不同项目用的版本不同)。
vue比较特殊,安装了vue-loader,还必须安装一个插件
resolve模块解析
它是帮助webpack从require和import中找到需要引入的模块
const path = require("path")
const { VueLoaderPlugin } = require("vue-loader/dist/index")
module.exports = {
entry: "./src/main.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "./build"),
// assetModuleFilename: "abc.png"
},
resolve: {
//为import和require引入东西的时候,添加扩展名
extensions: [".js", ".json", ".vue", ".jsx", ".ts", ".tsx"],
//alias设置别名
alias: {
utils: path.resolve(__dirname, "./src/utils")
}
},
}
当我们import或者require一个东西在页面上
如下
import { createApp } from 'vue'
import Hello from './vue_demo/Hello'
import { sum } from './utils/math'
如果是一个文件,带了后缀名,就会直接打包
不带后缀名的话,就会webpack底层就会通过resolve.extensions自动为我们的文件添加后缀名。
怎么自动找到我的文件应该是什么后缀?不同的代码有不同的特点,webpack有自己的识别办法。
extensions是可以自己配置的
我们可以自己配置,把需要自动加后缀名的后面加到resolve对象的extensions数组里面
所以如果我们不配置这个extensions那么直接import Vue文件的话,就会识别不到,然后报错无法找到import文件,所以必须自己写上.vue后缀,如hello.vue
如果是文件夹,如import utils from “./utils”那么就会默认变成import utils from “./utils/index”,这个index的后缀又会进行resolve.extensions匹配。
我认为根本没必要配,页面import或者require引入的时候,全部老老实实写个后缀还容易区分点
alias
当我们的层级很深(项目中很容易遇到),那么引入写相对路径的话,就需要写好多个../非常不容易识别,所以我们经常在webpack.config.js内给它配置一个alias
//这里是webpack.config.js
resolve: {
//为import和require引入东西的时候,添加扩展名
extensions: [".js", ".json", ".vue", ".jsx", ".ts", ".tsx"],
//alias设置别名
alias: {
utils: path.resolve(__dirname, "./src/utils")
}
},
webpack的常见插件和模式
loader就是把各种各样后缀的代码,变成浏览器可以看得懂的三剑客代码
plugin可以做loader外的各种事情。优化打包,资源管理(管理文件等),环境变量注入等等各种拓展功能。
const path = require("path")
const { VueLoaderPlugin } = require("vue-loader/dist/index")
const { CleanWebpackPlugin } = require("clean-webpack-plugin")
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { DefinePlugin } = require("webpack")
module.exports = {
mode: "production",
entry: "./src/main.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "./build"),
clean: true
// assetModuleFilename: "abc.png"
},
resolve: {
extensions: [".js", ".json", ".vue", ".jsx", ".ts", ".tsx"],
alias: {
utils: path.resolve(__dirname, "./src/utils")
}
},
module: {
rules: [
{
test: /\.css$/,
use: [ "style-loader", "css-loader", "postcss-loader" ]
},
{
test: /\.less$/,
use: [ "style-loader", "css-loader", "less-loader", "postcss-loader" ]
},
{
test: /\.(png|jpe?g|svg|gif)$/,
// 1.打包两张图片, 并且这两张图片有自己的地址, 将地址设置到img/bgi中
// 缺点: 多图片加载的两次网络请求
// type: "asset/resource",
// 2.将图片进行base64的编码, 并且直接编码后的源码放到打包的js文件中
// 缺点: 造成js文件非常大, 下载js文件本身消耗时间非常长, 造成js代码的下载和解析/执行时间过长
// type: "asset/inline"
// 3.合理的规范:
// 3.1.对于小一点的图片, 可以进行base64编码
// 3.2.对于大一点的图片, 单独的图片打包, 形成url地址, 单独的请求这个url图片
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 60 * 1024
}
},
generator: {
// 占位符
// name: 指向原来的图片名称
// ext: 扩展名
// hash: webpack生成的hash
filename: "img/[name]_[hash:8][ext]"
}
},
{
test: /\.js$/,
use: [
{
loader: "babel-loader",
// options: {
// plugins: [
// "@babel/plugin-transform-arrow-functions",
// "@babel/plugin-transform-block-scoping"
// ]
// }
}
]
},
{
test: /\.vue$/,
loader: "vue-loader"
}
]
},
plugins: [
new VueLoaderPlugin(),
// new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: "电商项目",
template: "./index.html"
}),
new DefinePlugin({
BASE_URL: "'./'",
coderwhy: "'why'",
counter: "123"
})
]
}
有的插件不用引入,因为根本没用到里面的变量,如postcss的autoprefixer
有的插件比如下面的插件,你需要在plugin里面new 实例化东西,就必须引入了
引入的方式不同插件也不同,看插件作者怎么写的,如cleanwebpackplugin需要解构,但是htmlwebpackplugin又不需要解构
cleanWebpackPlugin
dist文件夹就是打包后默认生成的文件夹,我们原先自己在webpack.config.js 的output中配置了文件夹名称为build,不配置默认是dist
tips:我们可以不用这个插件,在最新的webpack里面,配置中有一个output.clean可以和这个插件有相同的效果。
文档https://webpack.docschina.org/concepts/
html-wepack-plugin
1-意思就是说,webpack打包后,不会自动生成index.html在dist里面,这个插件可以自动生成一个html,这个html模板可以在node_modules里面的此插件的包的lib/default_index.js修改,或者在template指定模板。
2-默认生成title为WebpackAPP,我们可以在new的时候就修改
plugins: [
// new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: "电商项目",
template: "./index.html"
}),
3-其实我感觉这些都是鸡肋,我还不如自己建一个index.html,花里胡哨的全是配置恶心死了。
DefinePlugin
它是webpack内置的插件
const { DefinePlugin } = require("webpack")
new DefinePlugin({
BASE_URL: "'./'",
coderwhy: "'why'",
counter: "123"
})
1-它的作用就是注入一个变量,如上代码写在webpack.config.js中,就把当前项目注入了三个变量,比如在其他地方页面是可以直接使用coderwhy这个变量表示why字符串的
2-它默认注入了一个process.env.NODE_ENV,里面记录了当前的模式
Mode模式配置
1-通俗点就是写上production意思是生成的代码用于生产环境,不是在开发中,就又很多模块会去混淆压缩代码什么的,然后代码都在一行很难看懂
2-写development就是告诉webpack当前是在开发阶段,那么打包的代码,就能被开发者看懂。
webpack打包本地服务器
打包需要开启本地服务器服务才能执行,以前我们是通过live server插件来打开的,有一个弊端
每次我们修改了代码,都需要重新打包。特别麻烦
webpack搭建的本地服务器去执行的话,就可以实时编译,我们写的代码一变,浏览器页面也可以更着变化。
开启本地服务器
1-安装这个包
2-在webpack.config.js中的script中添加”serve”:“webpack serve –config wk.config.js”
3-npm run serve或者npx webpack serve –config wk.config.js
注意不能直接写npx webpcak -serve 因为如果你不指定配置,有的设置不存在,会报错的。
HMR热模块替换
热模块更新,就是我们只改了一个东西,比如把console.log(‘1’)改成了console.log(‘2’)
我们不应该重新刷新整个页面,而是只改变这个console.log
在webpack-dev-server中其实内置了hmr热模块更新,也是默认打开的,所以下图中的hot:true可写可不写
虽然直接支持也默认开启了,但是我们需要在打包入口文件.js中指定哪些模块发生更新时,进行HMR
问题:这玩意也太麻烦了,一个一个判断引入,我不如让它页面直接全部刷新呢,真是鸡肋!
事实上这些是不需要我们自己配置的,在vue-loader中,这些东西都帮我们配置好了,我们这里学它只是了解有这个东西。
devServer配置
webpack-dev-server默认是在8080端口,我们也可以配置这些东西,比如指定端口。
devServer: {
hot: true,
// host: "0.0.0.0",
// port: 8888,
//自动打开浏览器
// open: true
//压缩文件
// compress: true
},
host写成0.0.0.0的话,如我们本地ip地址为192.168.1.90,那么在学校机房,同一个局域网内,我的同学是192.168.1.91,同学也是可以在浏览器中通过192.168.1.90:8080访问到我们的页面 的
开发和生成环境
如何区分生产和开发环境
以前我们把所有的配置都写在webpack.config.js中,其实不同插件是运用于不同开发环境的,比如devServer插件是用于生产环境,而cleanWebpackPlungun是用于在开发环境帮我们删文件的。
如果它们都配置在webpack.config.js同一个地方,在运行的时候就会浪费一些性能,比如我们在开发的时候,就不需要devServer插件再去运行一下子了
入口entry文件解析
我们一般不修改content,就让它默认就好了
这里只需要知道,即使webpack.dev.config.js文件在config文件夹内,也就是多进去了一层,entry还是写./src/main.js的,而不是../src/main.js
webpack配置文件抽取公共部分
tips:为什么webpack里面的配置用的是commomjs?因为webpack是需要运行在node环境中的,node环境直接支持的就是commomjs模块化
上面说到要把webpack.config.js分为webpack.dev.config.js和webpack.product.config.js两个配置文件,在运行的时候可以节约性能,那么它们之间是有很多共同的配置的,也就是公共部分。
比如入口entry和出口打包文件的output还有loader等等都是公共部分,两个配置文件都需要。
所有我们通常再创造一个文件webpack.common.config.js(这个名字随便命名,你用的时候知道就好了)
webpack.dev.config.js
const { merge } = require("webpack-merge")
const commonConfig = require("./webpack.common.config")
module.exports = merge(commonConfig, {
mode: "development",
devServer: {
hot: true,
// host: "0.0.0.0",
// port: 8888,
// open: true
// compress: true
}
})
如上,抽取了公共配置后,dev配置直接使用require引入就好了
然后我们需要用到一个合并插件
npm installwebpack-merge -D
可以看到在代码中,我们使用了这个插件的包的一个merge函数,然后通过这个函数合并了公共配置和当前dev配置。
总结
这些七里八里的配置插件,大部分不需要记,我们知道有这个东西,万一需要查文档用就好了
而且大部分配置我们在vue开发中,脚手架都帮我们搞好了,只是说了解了原理,出现了错误,我们可以快速解决
作业布置
三. 什么是loader?webpack的loader是什么作用?和Plugin有什么区别?
loader用来对模块的源代码进行转换,加载文件
比如因为webpack 不知道怎么样去加载css文件,所以我们需要用css-loader来加载css文件
主要通过配置方式来使用loader来加载
module: { rules: [ { // 告诉webpack匹配以.css结尾的文件 test: /\.css$/, // use: [ // // 注意顺序,从下往上执行 // { loader: "style-loader" }, // { loader: "css-loader" } // ] //简写一: 如果loader只有一个 // loader: "css-loader" //简写二: 多个loader不需要其他属性时,可以直接写loader字符串形式 // 配置方式一 use: ["style-loader", "css-loader", "postcss-loader"] // 配置方式二 // use: ["style-loader", "css-loader", { // loader: "postcss-loader", // options: { // postcssOptions: { // plugins: [ // "autoprefixer" // ] // } // } // }] }, { // 告诉webpack匹配以.css结尾的文件 test: /\.less$/, // use: [ // // 注意顺序,从下往上执行 // { loader: "style-loader" }, // { loader: "css-loader" }, // { loader: "less-loader" }, // { loader: "postcss-loader" } // ] // 简写 use: ["style-loader", "css-loader", "less-loader", "postcss-loader"], } ] }
- loader和plugin的区别
- loader是用于特定的模块类型(css,vue…)进行解析加载
- plugin 是用于执行更多广泛的任务,比如打包优化,资源管理,环境变量注入等
- 常见的插件
- CleanWebpackPlugin 每次修改了一些配置,重新打包时,帮助我们删除dist文件夹
- HtmlWebpackPlugin 对index.html进行打包处理,自动在dist文件夹中,生成了一个index.html的文件
- DefinePlugin 允许在编译时创建配置的全局常量,是一个webpack内置的插件(不需要单独安装)
- 比如process.env.NODE_ENV 判断当前环境是开发还是生产
- 常见的插件
- loader和plugin的区别
四. 什么是babel?babel在开发中是什么作用?
- Babel是一个工具链,主要用于旧浏览器或者环境中将ECMAScript 2015+代码转换为向后兼容版本的JavaScript (ES6以上的代码转成ES5代码)
- 作用: 语法转换,源代码转换,箭头函数转换 ,ES6以上的代码转成ES5代码
五.webpack的开发模式和生产模式有什么区别?
- Mode: development 开发模式
- 会将process.env.NODE_ENV 的值设置为development
- Mode: production 生产模式
- 会将process.env.NODE_ENV 的值设置为production
六. webpack如何开启本地服务器,并且提高页面的更新效率(HMR)?
如何开启本地服务器?
安装webpack-dev-server
npm install webpack-dev-server -D
修改配置文件,启动时加上serve
"scripts": { "serve": "webpack serve --config wk.config.js" },
命令 : npm run serve
HMR 模块热替换
模块热替换是指在 应用程序运行过程中,替换、添加、删除模块,而无需重新刷新整个页面
如何使用HMR
- 默认情况下,webpack-dev-server已经支持HMR,我们只需要开启即可(默认已经开启);
- 在不开启HMR的情况下,当我们修改了源代码之后,整个页面会自动刷新,使用的是live reloading;
在main.js中
if (module.hot) { module.hot.accept("./utils/demo.js", () => { console.log("demo更新") }) }