webpack+vite前端构建工具 - 10 开发模式
10 开发模式
- 开发项目时,npm run dev开发模式启动服务运行项目。
- 本节介绍开发模式如何控制调配。
- webpack运行开发模式的工作流程
- 1 安装webpack-dev-server
- 独立于webpack,需单独安装
- 2 设置devServer字段(有默认值)
- 3 用webpack-dev-server运行
- 1 安装webpack-dev-server
10.1 webpack-dev-server工作原理
- webpack-dev-server,用express开启node服务的工具。
- 运行webpack-dev-server(输入webpack-dev-server),webpack-dev-server利用express开启node服务,调用webpack工具(实质是webpack方法,在js文件里调用webpack方法)进行打包。获取到打包结果,使用express开启的node服务将打包结果展示出来。
- 项目发生更改,通知到webpack服务,通知到express,会再次调用webpack进行打包。
10.2 原理示例
10.2.0 准备项目
项目结构
// package.json
{"name": "webpackdemo2","version": "1.0.0","description": "","main": "index.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1","dev": "webpack"},"keywords": [],"author": "","license": "ISC","type": "commonjs","devDependencies": {"express": "^5.1.0","html-webpack-plugin": "^5.6.3","webpack-dev-middleware": "^7.4.2"},"dependencies": {"webpack": "^5.99.9"}
}
// webpack.config.js
const htmlwebpack = require('html-webpack-plugin');
module.exports = {entry: {app1: ["./app.js"]},output: {path: __dirname + '/dist',filename: "[name].[chunkhash:4].bundle.js"},mode: "development",plugins: [new minicss({filename: './css/test.bundle.css'// 打包的css名称}),new htmlwebpack({template: './index.html',filename: "index.html"})]
}
10.2.1 安装webpack-dev-server
- 安装 express,webpack-dev-middleware,html-webpack-plugin
- 安装命令:
npm install a b c --save-dev
webpack-dev-middleware:启动webpack开发模式的中间件
express:node框架,启动服务
10.2.2 编写js文件用于运行开发模式
// mydev.js
const express = require("express");
const webpackDevMiddleWare = require("webpack-dev-middleware")
const webpack = require("webpack")
// 引入配置文件
const config = require("./webpack.config.js")
// 打包结果
const dist = webpack(config)
// 准备好服务
const app = express()
// 打包结果给中间件,借express开启的服务app启动
// 将webpack打包的内容显示在服务上
app.use(webpackDevMiddleWare(dist));
// 将服务挂载在2000端口
app.listen(2000);
10.2.3 运行服务
运行js文件,启动服务,命令: node mydev.js
真正启动开发模式,命令:webpack-dev-server
指令
webpack-dev-server
相当于node mydev.js
(用node运行js文件)
webpack-dev-server 相当于 node mydev.js,即js文件编写+启动。
结果
包括打包结果,启动项目。此时打包结果用服务启动起来了。
使用2000端口可以看到整个项目的内容(模拟的线上展示)
以上是简单模拟webpack开发模式的原理。
10.3 使用示例
10.3.1 配置devServer
配置属性devServer
// webpack.config.js
const htmlwebpack = require('html-webpack-plugin');
module.exports = {entry: {app1: ["./app.js"]},output: {path: __dirname + '/dist',filename: "[name].[chunkhash:4].bundle.js"},mode: "development",// 配置开发模式devServer: {port: 1000,hot: true,//热更新},plugins: [new htmlwebpack({template: './index.html',filename: "index.html"})]
}
10.3.2 开启开发模式
1 开启开发模式
命令: webpack-dev-server
结果:报错。
2 解决
- 安装
webpack
webpack-cli
- 安装
webpack-dev-server
- 启动命令修改为:
webpack serve
3 结果
点击命令行的地址,打开项目。
页面展示index.html的内容,控制台打印js文件定义的内容。
10.4 热更新
10.4.1 热更新与强制更新
热更新是开发模式下的。
- 热更新
- 不刷新浏览器的情况下更新页面
- 可以保持页面的当前状态
例如当前页有计时器,已经计到10。如果是热更新,那么计时器依然在10,当前页面所有状态会被保留下来。如果是强制更新,相当于手动帮用户刷新页面,会重置页面状态
- 强制更新
- 自动刷新页面来更新页面
- 会重置页面状态
相同点 | 不同点 | |
---|---|---|
热更新 | 发生更改后不需要用户自己更新页面 | 完全不会刷新浏览器,保持页面状态 |
强制更新 | 同上 | 自动刷新页面,重置页面状态 |
10.4.2 示例
更改与js无关的css代码,是热更新处理的。即页面样式变化,但js的定时器仍继续在原来基础上计时,而不会被重置为0.
更改与css无关的js代码,是强制更新,整个页面的状态会刷新。
一般而言,js代码采用强制更新,css代码采用热更新。
10.4.3 设置更新方式
1 设置js热更新
设置js热更新,在js文件里加入以下代码,则当前js文件为热更新模式。
通常来说不会这么设置。
if(module.hot) {module.hot.accept();
}
2 设置强制更新
webpack.config.js的devServer的hot设置为false,则css等文件也不会热更新了。
推荐css热更新
10.5 proxy
- 由webpack-dev-server开启的node服务代替我们请求接口
- 如果后端没有开启cors,我们直接从前端请求会跨域
- 用proxy代替我们请求接口
- 整个开发模式是用node写的服务,使用proxy让请求先到node服务,然后再由node服务转发真实接口
- 通常是开发阶段解决跨域问题(项目最终打包上线就没有了)
- proxy是webpack-dev-server开的node服务做的。
- 项目上线没有node服务,是用服务器实现。
10.5.1 示例
1 模拟接口
使用node模拟接口,地址是/api/getNum1,返回结果是“hello webpack”. 挂载在3000端口。
// server.js
const express = require('express');
const app = express();
app.get('/api/getNum1', (req, res) => {res.status(200).end("hello webpack")
})
app.listen(3000);
2 请求接口
请求此接口
// app.js
import axios from 'axios'
axios.get("http://localhost:3000/api/getNum1").then((res) => {console.log("🚀 ~ axios.get ~ res:", res)
})
3 运行-跨域错误
失败,babel-loader编译import错误。
理想情况:
会报跨域错误。
打开项目可以看到请求/api/getNum1接口,状态为CORS错误,即跨域错误。
直接请求会报错,除非后端设置CORS.
4 增加proxy代理
// webpack.config.js
module.exports = {// 配置开发模式devServer: {port: 1000,hot: true, //是否使用热更新proxy: {"/": {// 代理转发target: "http://localhost:3000/"}}}
}
同时,请求的接口可以省去前面http部分
// app.js
import axios from 'axios';
axios.get("/api/getNum1").then((res) => {console.log("🚀 ~ axios.get ~ res:", res)
})
/开头的请求,通过代理转发到配置的服务上。
10.5.2 路径重写
webpack.config.js的devServer.proxy的"/"开头的pathRewrite配置
可见p9-20:00
10.5.3 请求头设置
webpack.config.js的devServer.proxy的"/"开头的headers配置
可见p9-20:00
10.5.4 多组proxy规则
在webpack.config.js的devServer.proxy里配置多个规则。
10.5 source-map
- 出现错误,或输出内容时,source-map帮助定位错误代码。
- 通过source-map(调节等级)可以定位打包前的代码。
控制台sources的代码一般都是打包后的代码
调整source-map等级,控制台sources的代码可以显示打包前的代码
- source-map模式(用到再看)
- 项目上线后就不使用source-map了,即模式为none