[webpack3.8.1]Guides-6-Hot Module Replacement(模块热重置)

news/2024/7/3 1:17:01 标签: webpack, javascript, runtime

Hot Module Replacement

This guide extends on code examples found in the Development guide.

       温馨提示:这个指南中的例子是基于上一个指南的。(╯°Д°)╯

Hot Module Replacement (or HMR) is one of the most useful features offered by webpack. It allows all kinds of modules to be updated at runtime without the need for a full refresh. This page focuses on implementation while the concepts page gives more details on how it works and why it's useful.

       Hot Module Replacement,或称之为HMR,是webpack提供的非常有用的特性之一。它允许你各种各样的模块在运行时自动更新,而无需整体更新。在这一趴,我们主要关注这一切是如何实现的,不像概念部分那样,我们会告诉你它是怎么工作的,为什么这样是实用的。

HMR is not intended for use in production, meaning it should only be used in development. See the building for production guide for more information.

       我们不建议在产品中使用HMR,这意味着它应当在开发过程中使用。戳这里,查看更多信息。

Enabling HMR

This feature is great for productivity. All we need to do is update our webpack-dev-server configuration, and use webpack's built in HMR plugin. We'll also remove the entry point for print.js as it will now be consumed by the index.js module.

       这个特性对于生产效率很重要。我们所需要做的全部的事情只是更新我们服务器的配置,只要使用HMR插件就行了。我们也将会移除print.js的入口点,由于它现在正在被index.js模块使用。

If you took the route of using webpack-dev-middleware instead of webpack-dev-server, please use the webpack-hot-middleware package to enable HMR on your custom server or application.

       如果你的技术路线是使用webpack-dev-middleware而不是webpack-dev-server,请使用webpack-hot-middleware来使得HMR在你的服务器或者程序中生效。

webpack.config.js

  const path = require('path');
  const HtmlWebpackPlugin = require('html-webpack-plugin');
  const CleanWebpackPlugin = require('clean-webpack-plugin');
+ const webpack = require('webpack');

  module.exports = {
    entry: {
-      app: './src/index.js',
-      print: './src/print.js'
+      app: './src/index.js'
    },
    devtool: 'inline-source-map',
    devServer: {
      contentBase: './dist',
+     hot: true
    },
    plugins: [
      new CleanWebpackPlugin(['dist']),
      new HtmlWebpackPlugin({
        title: 'Hot Module Replacement'
      }),
+     new webpack.NamedModulesPlugin(),
+     new webpack.HotModuleReplacementPlugin()
    ],
    output: {
      filename: '[name].bundle.js',
      path: path.resolve(__dirname, 'dist')
    }
  };

You can use the CLI to modify the webpack-dev-server configuration with the following command: webpack-dev-server --hotOnly.

       你可以使用命令行来修改webpack-dev-server的配置,使用如下的命令:

webpack-dev-server --hotOnly

Note that we've also added the NamedModulesPlugin to make it easier to see which dependencies are being patched. To start, we'll get the dev server up and running by executing an npm start from the command line.

       请注意,我们还添加了这个功能NamedModulesPlugin,以便更轻松地查看哪些依赖关系正在进行修补。首先,我们将通过npm start从命令行执行一个启动并运行开发服务器。

Now let's update the index.js file so that when a change inside print.js is detected we tell webpack to accept the updated module.

       现在,让我们更新index.js,以便当print.js检测到内部更改时,我们告诉webpack接受更新的模块。

index.js

  import _ from 'lodash';
  import printMe from './print.js';

  function component() {
    var element = document.createElement('div');
    var btn = document.createElement('button');

    element.innerHTML = _.join(['Hello', 'webpack'], ' ');

    btn.innerHTML = 'Click me and check the console!';
    btn.onclick = printMe;

    element.appendChild(btn);

    return element;
  }

  document.body.appendChild(component());
+
+ if (module.hot) {
+   module.hot.accept('./print.js', function() {
+     console.log('Accepting the updated printMe module!');
+     printMe();
+   })
+ }

Start changing the console.log statement in print.js, and you should see the following output in the browser console.

       让我们开始改变print.js中的console.log语句,你应当能看到如下的在浏览器控制台的输出:

print.js

  export default function printMe() {
-   console.log('I get called from print.js!');
+   console.log('Updating print.js...')
  }

console

[HMR] Waiting for update signal from WDS...
main.js:4395 [WDS] Hot Module Replacement enabled.
+ 2main.js:4395 [WDS] App updated. Recompiling...
+ main.js:4395 [WDS] App hot update...
+ main.js:4330 [HMR] Checking for updates on the server...
+ main.js:10024 Accepting the updated printMe module!
+ 0.4b8ee77….hot-update.js:10 Updating print.js...
+ main.js:4330 [HMR] Updated modules:
+ main.js:4330 [HMR]  - 20
+ main.js:4330 [HMR] Consider using the NamedModulesPlugin for module names.

Via the Node.js API

When using Webpack Dev Server with the Node.js API, don't put the dev server options on the webpack config object. Instead, pass them as a second parameter upon creation. For example:

       当我们通过Node.js的API来使用Webpack Dev Server时,不要将dev server的选项配置在webpack的对象中。而是应该将这些配置信息作为构造函数的第二个参数传进去。举个例子哈:✧(≖ ◡ ≖✿

new WebpackDevServer(compiler, options)

To enable HMR, you also need to modify your webpack configuration object to include the HMR entry points. The webpack-dev-server package includes a method called addDevServerEntrypoints which you can use to do this. Here's a small example of how that might look:

       要启用HMR,还需要修改webpack配置对象以包含HMR入口点。该webpack-dev-server软件包包含一个addDevServerEntrypoints,您可以用来执行此操作的方法。下面是一个小例子,它可能是这样的:

dev-server.js

const webpackDevServer = require('webpack-dev-server');
const webpack = require('webpack');

const config = require('./webpack.config.js');
const options = {
  contentBase: './dist',
  hot: true,
  host: 'localhost'
};

webpackDevServer.addDevServerEntrypoints(config, options);
const compiler = webpack(config);
const server = new webpackDevServer(compiler, options);

server.listen(5000, 'localhost', () => {
  console.log('dev server listening on port 5000');
});

If you're using webpack-dev-middleware, check out the webpack-hot-middleware package to enable HMR on your custom dev server.

       如果你正在使用webpack-dev-middleware,检查webpack-hot-middleware包,使得HMR可以应用在你的定制化的dev server中。

Gotchas

Hot Module Replacement can be tricky. To show this, let's go back to our working example. If you go ahead and click the button on the example page, you will realize the console is printing the old printMe function.

       模块热重置可能是棘手的。为了展现这个,让我们回到我们工作的例子。如果你单击我们例子的页面上的按钮,你将会意识到控制台正在打印旧的printMe函数的信息。

This is happening because the button's onclick event handler is still bound to the original printMe function.

       这是因为按钮的点击事件的解析器依旧绑定在原始的printMe的函数上。

To make this work with HMR we need to update that binding to the new printMe function using module.hot.accept:

       为了使得HMR起作用,我们需要使用module.hot.accept更新绑定,让它绑定到新的printMe函数:

index.js

  import _ from 'lodash';
  import printMe from './print.js';

  function component() {
    var element = document.createElement('div');
    var btn = document.createElement('button');

    element.innerHTML = _.join(['Hello', 'webpack'], ' ');

    btn.innerHTML = 'Click me and check the console!';
    btn.onclick = printMe;  // onclick event is bind to the original printMe function

    element.appendChild(btn);

    return element;
  }

- document.body.appendChild(component());
+ let element = component(); // Store the element to re-render on print.js changes
+ document.body.appendChild(element);

  if (module.hot) {
    module.hot.accept('./print.js', function() {
      console.log('Accepting the updated printMe module!');
-     printMe();
+     document.body.removeChild(element);
+     element = component(); // Re-render the "component" to update the click handler
+     document.body.appendChild(element);
    })
  }

This is just one example, but there are many others that can easily trip people up. Luckily, there are a lot of loaders out there (some of which are mentioned below) that will make hot module replacement much easier.

       这只是一个例子,但是这里有很多其他的情况会轻易地使得人们感到难缠。幸运的是,在这里有很多加载器(下面我们列举一些)可以使得模块热重置变得更加简易。( ゚∀゚)

HMR with Stylesheets (HMR和样式表)

Hot Module Replacement with CSS is actually fairly straightforward with the help of the style-loader. This loader uses module.hot.accept behind the scenes to patch <style> tags when CSS dependencies are updated.

       实际上,使用style-loader了之后,模块热重置来更新CSS就会相当简单。当CSS依赖发生更新时,该加载器使用module.hot.accept在后台修补<style>标记。

First let's install both loaders with the following command:

       首先,让我们用下面的命令安装这两个加载器:

npm install --save-dev style-loader css-loader

Now let's update the configuration file to make use of the loader.

       现在,让我们更新配置文件以使用加载器。

webpack.config.js

  const path = require('path');
  const HtmlWebpackPlugin = require('html-webpack-plugin');
  const webpack = require('webpack');

  module.exports = {
    entry: {
      app: './src/index.js'
    },
    devtool: 'inline-source-map',
    devServer: {
      contentBase: './dist',
      hot: true
    },
+   module: {
+     rules: [
+       {
+         test: /\.css$/,
+         use: ['style-loader', 'css-loader']
+       }
+     ]
+   },
    plugins: [
      new CleanWebpackPlugin(['dist'])
      new HtmlWebpackPlugin({
        title: 'Hot Module Replacement'
      }),
      new webpack.HotModuleReplacementPlugin()
    ],
    output: {
      filename: '[name].bundle.js',
      path: path.resolve(__dirname, 'dist')
    }
  };

Hot loading stylesheets is as easy as importing them into a module:

       我们只需要导入它们进模块之中,样式表就可以热加载了。

project

  webpack-demo
  | - package.json
  | - webpack.config.js
  | - /dist
    | - bundle.js
  | - /src
    | - index.js
    | - print.js
+   | - styles.css

styles.css

body {
  background: blue;
}

index.js

  import _ from 'lodash';
  import printMe from './print.js';
+ import './styles.css';

  function component() {
    var element = document.createElement('div');
    var btn = document.createElement('button');

    element.innerHTML = _.join(['Hello', 'webpack'], ' ');

    btn.innerHTML = 'Click me and check the console!';
    btn.onclick = printMe;  // onclick event is bind to the original printMe function

    element.appendChild(btn);

    return element;
  }

  let element = component();
  document.body.appendChild(element);

  if (module.hot) {
    module.hot.accept('./print.js', function() {
      console.log('Accepting the updated printMe module!');
      document.body.removeChild(element);
      element = component(); // Re-render the "component" to update the click handler
      document.body.appendChild(element);
    })
  }

Change the style on body to background: red; and you should immediately see the page's background color change without a full refresh.

       现在,改变body的样式为background: red;,然后你应当立即就能看到页面背景颜色的改变,而且不用整体刷新。

styles.css

  body {
-   background: blue;
+   background: red;
  }

Other Code and Frameworks

There are many other loaders and examples out in the community to make HMR interact smoothly with a variety of frameworks and libraries...

       在社区中还有很多其他的加载器和例子可以使HMR与各种框架和库进行顺畅的交互。

  • React Hot Loader: Tweak react components in real time.
  • Vue Loader: This loader supports HMR for vue components out of the box.
  • Elm Hot Loader: Supports HMR for the Elm programming language.
  • Redux HMR: No loader or plugin necessary! A simple change to your main store file is all that's required.
  • Angular HMR: No loader necessary! A simple change to your main NgModule file is all that's required to have full control over the HMR APIs.

P.S.:好了,7以后的部分就比较难懂了,我会在能力提高了再译,前六个指南以及基础概念学会,使用webpack就基本不会遇到什么难题了。


http://www.niftyadmin.cn/n/1664059.html

相关文章

http请求的GET和POST请求:查询和新增(server.php)

<?php //设置页面内容是html编码格式是utf-8 header("Content-Type: text/plain;charsetutf-8"); //header("Content-Type: application/json;charsetutf-8"); //header("Content-Type: text/xml;charsetutf-8"); //header("Content…

vSphere5.1升级5.5 - 升级vCenter Server (1)

背景介绍 某企业原有8台Esxi host组成了一个Cluster&#xff0c;版本为vSphere5.1u2&#xff0c;今年要求将vSphere升级到5.5u3&#xff0c;并要求在虚拟机不中断的情况下完成替换&#xff0c;以下就来介绍该项目的实施计划 准备工作 查看HCL兼容性列表&#xff0c;服务器是否支…

NPOI+SharpZipLib实现压缩多个Excel下载

导出excel是再常见不过的功能&#xff0c;其中NPOI是我一直使用的导出excel的框架。你可以猛击这里了解NPOI&#xff0c;最近有这样一个需求&#xff0c;当我想一次性导出多个excel文件时。我想在内存里面压缩后输出到浏览器进行下载。由此接触到了另外一个框架SharpZipLib&…

C#设计模式之十六观察者模式(Observer Pattern)【行为型】

一、引言 今天是2017年11月份的最后一天&#xff0c;也就是2017年11月30日&#xff0c;利用今天再写一个模式&#xff0c;争取下个月&#xff08;也就是12月份&#xff09;把所有的模式写完&#xff0c;2018年&#xff0c;新的一年写一些新的东西。今天我们开始讲“行为型”设…

java.lang.NoClassDefFoundError: org/apache/ibatis/mapping/DatabaseIdProvider

我用的方案是:mavenstruts2springmybatis 出现上述错误的原因是&#xff1a; <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.0.1</version> …

常用SQL语言概述(DDL、DML、DQL)

众所周知&#xff0c;SQL&#xff08;Structure Query Language&#xff09;是数据库的核心语言&#xff0c;近段时间学习数据库&#xff0c;部分基础概念有点模棱两可&#xff0c;今天索性把这几个常用的SQL概念简单记录下以作区分。分类&#xff1a;DDL&#xff1a;数据定义语…

Linux 6.5增加对高通开源GPU Adreno 690的支持

即将推出的Linux 6.5内核将把对高通Adreno 690 GPU的支持添加到开源的MSM内核图形/显示驱动程序中。A690主要用于骁龙8cx第三代&#xff08;SC8280XP&#xff09;平台&#xff0c;而联想ThinkPad X13s笔记本电脑和其他硬件也采用了该平台。 新的支持将包含近200行代码&#xf…

Clipboard.js : 移动端浏览器实现网页内容复制

最近在项目中遇到这样一个需求&#xff1a; 点击按钮&#xff0c;将指定的URL复制到剪贴板&#xff0c;然后用户可以粘贴到浏览器(Safari为主)自行打开。方案一&#xff1a;zeroClipboard.js github地址&#xff1a;https://github.com/zeroclipboard/zeroclipboard 复制原理&a…