Webpack 开发工具与模块热替换

简介: Webpack 开发工具与模块热替换​️ 注意:永远不要在生产环境中使用这些工具,永远不要。devtool当 JavaScript 异常抛出时,你常会想知道这个错误发生在哪个文件的哪一行。

Webpack 开发工具与模块热替换

​️ 注意:
永远不要在生产环境中使用这些工具,永远不要。

devtool

当 JavaScript 异常抛出时,你常会想知道这个错误发生在哪个文件的哪一行。然而因为 webpack 将文件输出为一个或多个 bundle,所以 追踪这一错误会很不方便。

Source maps 试图解决这一问题。它有很多选择,各有优劣:

devtool build rebuild production quality
eval +++ +++ no generated code
cheap-eval-source-map + ++ no transformed code (lines only)
cheap-source-map + o yes transformed code (lines only)
cheap-module-eval-source-map o ++ no original source (lines only)
cheap-module-source-map o - yes original source (lines only)
eval-source-map -- + no original source
source-map -- -- yes original source
nosources-source-map -- -- yes without source content

 + 表示较快,- 表示较慢,o 表示时间相同

对于开发环境,通常希望更快速的 Source Map,需要添加到 bundle 中以增加体积为代价,但是对于生产环境,则希望更精准的 Source Map,需要从 bundle 中分离并独立存在。

个人建议:开发环境使用 cheap-module-eval-source-map ;开发环境使用 cheap-module-source-map

使用方式非常简单,在 webpack.config.js 中配置如下:

module.exports = {
  // 通过在浏览器调试工具(browser devtools)中添加元信息(meta info)增强调试
  // devtool: "eval", // 没有模块映射,而是命名模块。以牺牲细节达到最快。
  // devtool: "source-map", // 牺牲了构建速度的 `source-map' 是最详细的
  // devtool: "inline-source-map", // 嵌入到源文件中
  // devtool: "eval-source-map", // 将 SourceMap 嵌入到每个模块中
  // devtool: "hidden-source-map", // SourceMap 不在源文件中引用
  // devtool: "cheap-source-map", // 没有模块映射(module mappings)的 SourceMap 低级变体(cheap-variant)
  // devtool: "cheap-module-source-map", // 有模块映射(module mappings)的 SourceMap 低级变体
  devtool: "cheap-module-eval-source-map",
};

webpack-dev-server

webpack-dev-server 可以提供了一个服务器和实时重载(live reloading) 功能。

在开始前,确定你有一个 index.html 文件指向你的 bundle。假设 output.filename 是 bunlde.js

<html>
<body>
<script type="text/javascript" src="./dist/bundle.js"></script>
</body>
</html>

首先从 npm 安装 webpack-dev-server

$ npm install --save-dev webpack-dev-server

安装完成之后,你应该可以使用 webpack-dev-server 了,方式如下:

$ webpack-dev-server --open

上述命令应该自动在浏览器中打开 http://localhost:8080

提示:

本教程中的 示例代码 除了 demo00 ,都可以使用 webpack-dev-server 命令启动服务。

在你的文件中做一点更改并且保存。你应该可以在控制台中看到正在编译。编译完成之后,页面应该会刷新。如果控制台中什么都没发生,你可能需要调整下 watchOptions

默认情况下 webpack 会使用inline mode(内联模式)。这种模式在你的 bundle 中注入客户端(用来 live reloading 和展示构建错误)。Inline 模式下,你会在你的 DevTools 控制台中看到构建错误。

webpack-dev-server 可以做很多事情,比如转发请求到你的后端服务器。

webpack-dev-server 支持很多 cli 参数,来手动配置服务的选项。

但是,个人建议,一种更好的做法是在 webpack.config.js 文件中通过配置 devServer 属性来配置 webpack-dev-server 。

更多配置项参考:官方文档 - 开发中 Server(DevServer)

示例DEMO12: (DEMO / SOURCE)

在本示例中,devServer 配置如下:

devServer: {
  contentBase: [path.join(__dirname, "dist")],
  compress: true,
  port: 9000, // 启动端口号
  inline: true,
}

执行 webpack-dev-server 后,会启动一个端口为 9000 的本地服务。

热模块替换(Hot Module Replacement)

​​ 提示:

模块热替换功能一般用于开发环境。

现在你有了实时重载功能,你甚至可以更进一步:Hot Module Replacement(热模块替换)。这是一个接口,使得你可以替换模块而不需要刷新页面。不用每次修改都重新启动服务,这可以极大地提高开发效率。

那么,如何配置 webpack 来实现热替换呢?

请按以下步骤一步步来:

首先,安装依赖  react-hot-loader(确保使用这个包的 next 版本)

$ npm install --save babel-loader react-hot-loader@next

配置 entry

你需要定义几个用于热替换的入口路径

entry: {
  main: [
    // App 入口
    "./app/index",

    // 开启 React 代码的模块热替换(HMR)
    'react-hot-loader/patch',

    // 为 webpack-dev-server 的环境打包代码
    // 然后连接到指定服务器域名与端口
    'webpack-dev-server/client?http://localhost:9000',

    // 为热替换(HMR)打包好代码
    // only- 意味着只有成功更新运行代码才会执行热替换(HMR)
    'webpack/hot/only-dev-server',
  ],
},

配置 output

publicPath 对于热替换(HMR)是必须的,让 webpack 知道在哪里载入热更新的模块(chunk)

output: {
  ... ...
  // 对于热替换(HMR)是必须的,让 webpack 知道在哪里载入热更新的模块(chunk)
  publicPath: "/"
},

配置 module

需要使用 ES2015 模块来使 HMR 正常工作。为此,在我们的 es2015 preset 设置中,将 module 选项设置为 false。

并且,在此要引入 react-hot-loader/babel 开启 React 代码的模块热替换(HMR)

module: {

    rules: [
      {
        // 语义解释器,将 js/jsx 文件中的 es2015/react 语法自动转为浏览器可识别的 Javascript 语法
        test: /\.jsx?$/,
        include: path.resolve(__dirname, "app"),
        exclude: /node_modules/,

        // 应该应用的 loader,它相对上下文解析
        // 为了更清晰,`-loader` 后缀在 webpack 2 中不再是可选的
        // 查看 webpack 1 升级指南。
        loader: "babel-loader",

        // loader 的可选项
        options: {
          presets: [
            // webpack 现在已经支持原生的 import 语句了, 并且将其运用在 tree-shaking 特性上
            [
              "es2015",
              {
                "modules": false
              }
            ],

            "react" // 转译 React 组件为 JavaScript 代码
          ],
          plugins: [
            "react-hot-loader/babel" // 开启 React 代码的模块热替换(HMR)
          ]
        },
      },
    ]
  },

配置 devServer

此处,也需要引入 publicPath ,且和上文 outputpublicPath 值保持一致。

hot 属性需要置为 true,表示开启服务器的模块热替换。

devServer: {
  contentBase: [path.join(__dirname, "dist")],
  compress: true,
  port: 9000, // 启动端口号
  hot: true, // 启用 webpack 的模块热替换特性
  inline: true,
  publicPath: "/", // 和上文 output 的“publicPath”值保持一致
}

配置 plugins

最后,需要开启 webpack 自带的 HotModuleReplacementPluginNamedModulesPlugin 插件,启动热替换功能。

plugins: [
  // 开启全局的模块热替换(HMR)
  new webpack.HotModuleReplacementPlugin(),

  // 当模块热替换(HMR)时在浏览器控制台输出对用户更友好的模块名字信息
  new webpack.NamedModulesPlugin(),
],

示例DEMO13: (SOURCE)

在示例中,启动服务后,打开浏览器,访问 http://localhost:9000/

按快捷键 F12 打开浏览器调试窗口,可以看到类似提示信息

[HMR] Waiting for update signal from WDS...
[HMR] Waiting for update signal from WDS...
[WDS] Hot Module Replacement enabled.

这表示热替换功能已启动。

修改 app/index.jsx 文件,来看看热替换的效果:

修改前:

ReactDOM.render(
  <Welcome name="Victor Zhang"/>,
  document.getElementById("root")
);

修改后:

ReactDOM.render(
  <Welcome name="guest"/>,
  document.getElementById("root")
);

此时,应该看到页面内容会替换为你修改的内容。

Webpack 系列教程

欢迎阅读其它内容:

目录
相关文章
|
2月前
|
缓存 前端开发 JavaScript
深入了解Webpack:模块打包的革命
【10月更文挑战第11天】深入了解Webpack:模块打包的革命
|
7月前
|
存储 API
使用Webpack的module.hot API来定义模块的热替换
使用Webpack的`module.hot` API实现模块热替换,简单示例展示如何在`myModule`变化时执行回调。`module.hot.accept`接收模块路径和回调函数,当模块或其依赖变更时触发回调,用于执行更新逻辑。可通过`module.hot.data`保存和恢复状态以实现热替换时保持应用程序的状态。
|
2月前
|
缓存 前端开发 JavaScript
Webpack技术深度解析:模块打包与性能优化
【10月更文挑战第13天】Webpack技术深度解析:模块打包与性能优化
|
3月前
|
前端开发 开发者
在前端开发中,webpack 作为一个强大的模块打包工具,为我们提供了丰富的功能和扩展性
【9月更文挑战第1天】在前端开发中,Webpack 作为强大的模块打包工具,提供了丰富的功能和扩展性。本文重点介绍 DefinePlugin 插件,详细探讨其原理、功能及实际应用。DefinePlugin 可在编译过程中动态定义全局变量,适用于环境变量配置、动态加载资源、接口地址配置等场景,有助于提升代码质量和开发效率。通过具体配置示例和注意事项,帮助开发者更好地利用此插件优化项目。
87 13
|
4月前
|
缓存 前端开发 JavaScript
Webpack 模块解析:打包原理、构造形式、扣代码补参数和全局导出
Webpack 模块解析:打包原理、构造形式、扣代码补参数和全局导出
205 1
|
4月前
|
前端开发 开发者
在前端开发中,webpack 作为模块打包工具,其 DefinePlugin 插件可在编译时动态定义全局变量,支持环境变量定义、配置参数动态化及条件编译等功能。
在前端开发中,webpack 作为模块打包工具,其 DefinePlugin 插件可在编译时动态定义全局变量,支持环境变量定义、配置参数动态化及条件编译等功能。本文阐述 DefinePlugin 的原理、用法及案例,包括安装配置、具体示例(如动态加载资源、配置接口地址)和注意事项,帮助开发者更好地利用此插件优化项目。
118 0
|
6月前
|
前端开发 JavaScript 架构师
Webpack模块联邦:微前端架构的新选择
Webpack的模块联邦是Webpack 5引入的革命性特性,革新了微前端架构。它允许独立的Web应用在运行时动态共享代码,无需传统打包过程。基本概念包括容器应用(负责加载协调)和远程应用(独立应用,可暴露模块)。实现步骤涉及容器和远程应用的`ModuleFederationPlugin`配置,以及在应用间导入和使用远程模块。模块联邦的优势在于独立开发、按需加载、版本管理和易于维护。通过实战案例展示了如何构建微前端应用,包括创建容器和远程应用,以及消费远程组件。高级用法涉及动态加载、路由集成、状态管理和错误处理。
115 3
|
6月前
|
缓存 前端开发 JavaScript
Webpack作为模块打包器,为前端项目提供了高度灵活和可配置的构建流程
【6月更文挑战第12天】本文探讨了优化TypeScript与Webpack构建性能的策略。理解Webpack的解析、构建和生成阶段是关键。优化包括:调整tsconfig.json(如关闭不必要的类型检查)和webpack.config.js选项,启用Webpack缓存,实现增量构建,代码拆分和懒加载。这些方法能提升构建速度,提高开发效率。
65 3
|
7月前
|
前端开发 JavaScript 开发者
深入了解Webpack:前端模块打包工具
深入了解Webpack:前端模块打包工具
109 1
|
前端开发 JavaScript 开发者
webpack模块打包器
Webpack是一种前端资源构建工具,可以将多个文件和模块打包成一个或多个bundle。它具有高度的可配置性,支持各种类型的文件和插件,可以自定义打包过程和结果。Webpack的核心概念包括入口、出口和模式,可以分别用于指示打包的起点、输出位置和优化级别。Webpack还具有自动化构建过程,通过Tapable机制组织多个处理流程,并允许插件监听特定事件来参与整个构建过程。总之,Webpack是一个功能强大的前端资源构建工具,提供了高度可配置的选项和插件机制,方便开发者进行自定义和扩展。