WebpackDevServer
- 每次的代码修改都需要重新编译打包,刷新浏览器,特别麻烦,可以通过安装
webpackDevServer
来改善这方面的体验。
npm install --save-dev webpack-dev-server
- 启动命令:
npx webpack-dev-server
- 或者,
package.json
中添加scripts
...,
"scripts": {
"server": "webpack-dev-server"
}
- 修改
webpack.config.js
module.exports = {
...,
devServer: {
// 生成的虚拟目录路径
contentBase: "./dist",
// 自动开启浏览器
open: true,
// 端口
port: 8081
}
}
- 启动服务以后,
webpack
不在会把打包后的文件生成到硬盘真实目录中了,而是直接存在了内存中(同时虚拟了一个存放目录路径),后期更新编译打包和访问速度大大提升。
Proxy
- 当下前端的开发都是前后端分离开发的,前端开发过程中代码会运行在一个服务器环境下(如当前的
WebpackDevServer
),那么在处理一些后端请求的时候通常会出现跨域的问题。 WebpackDevServer
内置了一个代理服务,通过内置代理就可以把我们的跨域请求转发目标服务器上(WebpackDevServer
内置的代理发送的请求属于后端 -node
,不受同源策略限制),具体如下:- node.js服务端:
const Koa = require('koa');
const KoaRouter = require('koa-router');
const app = new Koa();
const router = new KoaRouter();
router.get('/api/info', async ctx => {
ctx.body = {
username: 'zMouse',
gender: 'male'
}
})
app.use( router.routes() );
app.listen(8787);
- 前端:
axios({
url: 'http://localhost:8787/api/info'
}).then(res => {
console.log('res',res.data);
})
- 默认情况下,该代码运行以后会出现跨域请求错误,修改
webpack
配置。
module.exports = {
...,
devServer: {
// 生成的虚拟目录路径
contentBase: "./dist",
// 自动开启浏览器
open: true,
// 端口
port: 8081,
proxy: {
'/api': {
target: 'http://localhost:8787'
pathRewrite: {
'^/api': ''
}
}
}
}
}
- 通过
proxy
设置,当我们在当前WebpackDevServer
环境下发送以/api
开头的请求都会被转发到 http://localhost:8787 目标服务器下 - 修改前端代码
axios({
//url: 'http://locahost:8081/api/info',
url: '/api/info'
}).then(res => {
console.log('res',res.data);
})
注意:
url
地址要填写WebpackDevServer
域,比如当前WebpackDevServer
开启的是 http://localhost:8081,也就是我们当前前端代码运行的环境,那么请求的url
也必须发送到这里,当我们的请求满足了proxy
中设置的/api
开头,那么就会把请求转发到target
,所以最后的实际请求是:http://lcoahost:8787/api/info
Hot Module Replacement
- 在webpack构建的项目中修改文件内容,不用手动刷新浏览器,内容会经过自动编译发送给浏览,实现原理就是webpack里又引用封装了websocket。
- 在之前当代码有变化,使用的
live reload
,也就是刷新整个页面,虽然这样为我们省掉了很多手动刷新页面的麻烦,但是这样即使只是修改了很小的内容,也会刷新整个页面,无法保持页面操作状态。HMR
随之就出现了,它的核心的局部(模块)更新,也就是不刷新页面,只更新变化的部分。
module.exports = {
...,
devServer: {
// 生成的虚拟目录路径
contentBase: "./dist",
// 自动开启浏览器
open: true,
// 端口
port: 8081,
// 开启热更新
hot:true,
// 即使 HMR 不生效,也不去刷新整个页面(选择开启)
hotOnly:true,
proxy: {
'/api': {
target: 'http://localhost:8787'
}
}
}
}
- 开启
HMR
以后,当代码发生变化,webpack
即会进行编译,并通过websocket
通知客户端(浏览器),我们需要监听处理来自webpack
的通知,然后通过HMR
提供的API
来完成我们的局部更新逻辑。 - 例如:
./fn1.js
export default function() {
console.log('start1!');
}
index.js
import fn1 from './fn1.js';
box1.onclick = fn1;
if (module.hot) {//如果开启 HMR
module.hot.accept('./fn1.js', function() {
// 更新逻辑
box1.onclick = fn1;
})
}
- 从上面就可以看到,
HMR
其实就是以模块为单位,当模块代码发生修改的时候,通知客户端进行对应的更新,而客户端则根据具体的模块来更新我们的页面逻辑(这些逻辑需要自己去实现),好在当前一些常用的更新逻辑都有了现成的插件。
css热更新
样式热更新比较简单,style-loader
中就已经集成实现了,我们只需要在 use
中使用就可以了