devServer的原理
Express本地服务器
话不多说,看图
当我们使用devServer打开一个项目时:
1. webpack会帮我们开启一个express本地服务器
2. 源代码会被打包 但不会输出打包文件 而是放到内存中的memfs库中
3.浏览器访问本地服务器获取静态资源
4.本地服务器从内存中的memfs库中调取到打包资源
5.返回给浏览器
前面说的是 当我们刚刚devServer启动一个本地服务时会做的事情,但devServe能帮我们做的远不止于此
在我们使用devServe时,当我们在源代码中做一些修改,会编译打包重新放入内存中,于此同时,我们会发现浏览器居然自动刷新了!!!?? (也就是liveReloading)
通常我们可以可以通过一些插件形式监听源代码更新,然后通知浏览器进行刷新 那么我们在没有安装插件的情况下为什么浏览器也会重新刷新?devServer是怎么做到的呢?
其实很简单,因为devServer除了开启本地服务器 为我们开启了一个Socket服务器
Socket服务器
Server服务器 负责直接提供静态资源 即打包后的资源浏览器可直接通过服务器进行请求和解析
贴出大佬贴: webSocket是什么
简单来说,一般情况下客户端与浏览器建立连接 使用的是http协议建立的短连接
短连接 建立连接 -> 客户端请求 -> 服务器响应 -> 断开连接
短连接只能通过客户端主动请求连接 然后服务器才能响应 并且每次请求结束连接都会断开 (服务器可创建的连接数有限)
而使用Soket服务器建立的连接 是长连接
长连接 建立连接->传输数据->保持连接->传输数据....->一方主动断开连接
长连接 不管是客户端还是服务器都可以发送主动发送数据(全双工通信)
而这个Socket服务器就是帮助我们建立从服务器到浏览器的长连接 每当我们对源码修改时 socket服务器监听到之后会通知浏览器进行livereLoad
HMR 模块热更新
设置devServer.hot = true 开启HMR
当然只做上面这一步是不够的 因为webpack默认是不知道哪些模块需要热更新的
所以还需要通过指定模块:
HMR原理
先上图 模块热更新原理
1.开启HMR即使用HMR服务器 本质也是Socket服务器 在浏览器之间建立了一条长连接
2.当我们的源码发生改变时 webpack对其进行编译 HMR服务器会监听到模块变化 如果是普通模块 刷新浏览器
3. 如果是指定的热更新模块 则服务器会生成两个文件 一个.json清单文件(包含的所要更新的模块列表) 和 .js文件(更改的模块代码) 依次将两个文件发送给客户端
4.浏览器拥有一个HMR.runtime 是进行的HMR的中枢 浏览器接收到两个文件之后 调用HMR runtime机制 针对修改的模块进行更新
常用配置
contentBase
当使用本地服务,本地服务器中没有想要的资源时 通过contentBase指定一个文件夹进行查找
图解:在开发阶段 当我们开启本地服务,webpack不会输出打包文件,而是将打包文件放在内存的memfs中,浏览器访问服务器 -> 服务器调用内存中的打包文件 - >发送给浏览器 -> 浏览器进行解析打包文件 这个时候 就有可能出现一个问题 有一些模块并不一定会加入到依赖图中进行打包 浏览器解析打包文件并不能解析到这些资源 他就会找服务器去要 那么服务器他会去哪里找呢??
contentBase设置的路径就是这个作用
当然这是在开发环境下,如果到了生产环境,我们可以采用copyWebpackPlugin将这些文件复制到最后的打包文件中
对比publicPath : 设置本地服务中打包的地址 访问打包文件时需要加上该路径
host 主机地址
默认为localhost -> 127.0.0.1 回环地址 会在网络层截获 不经过数据链路层和物理层 所以统一网段下的电脑也访问不到
0.0.0.0 可以在同一个网段中被访问到
port 端口号
open 是否打开浏览器
是否自动打开浏览器
compress 压缩
是否开启静态资源的gzip解压 Content-Encoding:gzip
Porxy 代理
//跨域代理
proxy:{
"/api":{
target:"127.0.0.1",
pathRewrite:{
"/api":""
},
changeOrigin:true
}
}