开发环境
常见需求
开发模式下对更关注构建的效率, 常见的需求有
- 自动构建: 当模块内容变化时, 期望能监听到变化并自动编译
- 无刷新响应: 当模块内容变化时, 期望能自动编译但不自动刷新页面
- 源代码映射: 开发中 debug, 查看输出时, 期望准确定位至源文件中
自动构建
自动构建有以下几种处理方式
- 使用 webpack 的观察模式 (最易)
- 使用
webpack-dev-server(常用) - 使用
webpack-dev-middleware(灵活)
启用观察模式
观察模式下 webpack 将监听文件内容的变化并进行自动构建,该方式无法自动刷新
package.json
json
"scripts:" {
"watch": "webpack --watch"
}使用 webpack-dev-server
webpack-dev-server 将开启一个 web 服务器,并监听文件内容变化并自动构建,同时自动刷新页面; 其相关选项在 devServer 字段中配置
安装依赖
shell
npm i --save-dev webpack-dev-serverpackage.json
json
"scripts": {
"start": "webpack-dev-server --open --mode=development"
}webpack.config.js
js
module.exports = {
// ...others
devServer: {
// 这里列出常见的配置, 大部分配置使用默认值即可
hot: true, // 模块热替换, 需要同时添加 webpack.HotModuleReplacementPlugin 插件
https: true,
host: 'localhost',
port: 8080,
allowedHosts: ['.host.com', 'xxoo.host.com'], // 白名单, '.' 表示任意子域名
proxy: {
'/router': 'http://localhost:3000/router'
},
historyApiFallback: true // history 模式下, 将 404 响应替换为 index.html; 可以指定一个对象进行深度配置
defore(app) {}, // 在服务内部的所有中间件之前执行
after(app) {}, // 在服务内部的其他中间件执行后执行
publicPath: '/assets/', // 此路径下的打包文件可在浏览器中访问, 确保总是以 '/' 开头和结尾 或使用完整的 URL
contentBase: './dist', // 提供内容的目录, 在提供静态文件时才需要, 优先级低于 publicPath
open: true, // 自动打开浏览器
openPage: '/', // 指定打开浏览器的页面
clientLogLevel: 'info', // 'info' | 'none' | 'error' | 'warning' 控制 console 输出信息内容
color: true, // 开启命令行彩色输出
progress: true, // 显示进度
compress: false, // 关闭 gzip 压缩
}
}使用 webpack-dev-middleware
webpack-dev-middleware 是一个中间件模块, 会将 webpack 处理后的内容传递给一个服务器, webpack-dev-server 内部使用了该中间件, 该中间件也可以配合其他服务单独使用。
webpack.config.js
js
// 来自官网的示例, 需要安装 express 和 webpack-dev-middleware
const express = require("express");
const webpack = require("webpack");
const webpackDevMiddleware = require("webpack-dev-middleware");
const app = express();
const config = require("./webpack.config.js");
const compiler = webpack(config);
// Tell express to use the webpack-dev-middleware and use the webpack.config.js
// configuration file as a base.
app.use(
webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath,
})
);
// Serve the files on port 3000.
app.listen(3000, function () {
console.log("Example app listening on port 3000!\n");
});package.json
json
{
"script": {
"server": "node server.js"
}
}无刷新响应
使用 webpack-dev-server 时,每次更新时会自动刷新页面,在大多数情况下期望页面无刷新就能响应模块的变化。
webpack 中使用 模块热替换(HMR) 实现无刷新响应的功能
启用 HMR 插件
在配置文件中添加插件
webpack.config.js
js
const webpack = require("webpack");
module.exports = {
// others...
devServer: {
hot: true, // 开启 HMR
},
plugins: [
// others...
new webpack.HotModuleReplacementPlugin(), // HMR 插件
new webpack.NamedModulesPlugin(), // 开启 HMR 时显示模块相对路径
],
};添加处理逻辑
开启 HMR 后需要在相应的模块中添加处理逻辑
index.js
js
//假设需要热替换 test 文件
import test from "test";
module.hot &&
module.hot.accept("./test.js", function () {
test();
});注意: 若 DOM 绑定了 HMR 中处理的方法, 在处理模块替换时并不会更新对应的监听器, 需要手动重新处理
loader 自处理
一些常用的 loader 内部会自行行使用 module.hot.accept 处理 HMR 的逻辑, 常见的有
style-loader,css-loadervue-loaderreact-hot-loaderelm-hot-loaderangular-hmr
源代码映射
源代码映射(Source Map)用于将构建后的代码映射至对应的源码, 可以通过以下方式开启
- 指定
devtool配置选项 - 使用
SourceMapDevToolPlugin/EvalSourceMapDevToolPlugin插件
注意
SourceMapDevToolPlugin/EvalSourceMapDevToolPlugin插件提供了更加详细的配置devtool选项内部使用了SourceMapDevToolPlugin/EvalSourceMapDevToolPlugin插件devtool与SourceMapDevToolPlugin/EvalSourceMapDevToolPlugin不要并用(会重复执行)
基本配置
webpack.config.js
js
module.exports = {
// ...others
devtool: "source-map",
};配置选项
devtool 提供了默认的 false 及其他多种选项,这些选项为以下基本选项的组合
inline: 不会生成独立的 map 文件而是以 dataURL 形式插入cheap: 会忽略源文件中列信息, 可以提高构建速度module: 包含了 loader 之间的 source mapeval- 构建和重新构建速率高
- 会生成
//@ sourceURL进行映射关联 - 不会生成 source-map 文件
- 只能映射至转换后的代码, 而非源码
source-map- 为每个打包后模块生成独立的 sorce map 文件
常用选项
对于开发环境
eval-source-map: 用于生成最佳品质的 source mapcheap-module-eval-source-map: 低开销的 source map , 会忽略列映射
对于生成环境
false或省略source-map: 生成独立的 source map 文件, 应当禁止普通用户访问这些文件hidden-source-map: 用于错误报告工具, 不应当部署至服务器nosources-source-map: 不包含源码内容, 用于映射堆栈跟踪, 可以部署至服务器
推荐的选项
- 开发环境:
cheap-module-eval-source-map - 生成环境:
cheap-module-source-map