手动实现HMR(热模块替换)

232 阅读2分钟

企业微信20230305-193657@2x.png 热模块替换(Hot Module Replacement,HMR)是一种前端开发中常用的技术,可以使得在不刷新页面的情况下,实时更新修改的代码,提高开发效率。HMRReactVue等现代前端框架中得到了广泛的应用。在本文中,我们将手动实现一个简单的HMR,以便更好地理解框架或库中实现的HMR原理。

实现思路

我们的HMR实现将基于Node.jsWebSocket。WebSocket是一种在单个TCP连接上提供全双工通信的协议。我们将在服务端创建一个WebSocket服务器,客户端通过WebSocket连接到服务器。当服务器监视的文件发生变化时,将通过WebSocket向客户端发送更新的代码,客户端通过WebSocket接收更新的代码,实现热模块替换的效果。

服务端代码

// server.js
const http = require("http");
const fs = require("fs");
const WebSocket = require("ws");
const path = require("path");

// 定义常量,用于指定文件类型对应的 Content-Type
const CONTENT_TYPES = {
  ".html": "text/html",
  ".js": "application/javascript",
};

// 定义 URL 到文件路径的映射
const URL_PATH_MAP = {
  "/": path.resolve(__dirname, "index.html"),
  "/src/app.js": path.resolve(__dirname, "src", "app.js"),
  "/client.js": path.resolve(__dirname, "client.js"),
};

const server = http.createServer((req, res) => {
  const { url } = req;
  let content = null;
  let contentType = "text/plain";

  // 根据请求的 URL 设置对应的 content 和 content-type
  if (url in URL_PATH_MAP) {
    const filePath = URL_PATH_MAP[url];
    content = fs.readFileSync(filePath, "utf-8");
    const extname = path.extname(filePath);
    if (extname in CONTENT_TYPES) {
      contentType = CONTENT_TYPES[extname];
    }
  } else {
    // 如果 URL 不在 URL_PATH_MAP 中,则返回 404 Not Found
    res.statusCode = 404;
    res.statusMessage = "Not Found";
    content = "404 Not Found";
  }

  // 设置响应头的 Content-Type,并返回对应的内容
  res.setHeader("Content-Type", contentType);
  res.end(content);
});

客户端代码

// client.js
const socket = new WebSocket('ws://localhost:3000');

socket.onopen = () => {
  console.log('WebSocket connected');
};

socket.onmessage = (event) => {
  const message = JSON.parse(event.data);
  if (message.type === 'update') {
    console.log(`${message.data.filePath} updated`);
    eval(message.data.content);
  }
};

被监听的代码

// src/app.js
console.log("Hello from app.js");

这篇技术文章向读者展示了如何手动实现简单的热模块替换(HMR)功能。热模块替换是一种实时更新应用程序代码的技术,它可以在不重新加载整个页面的情况下更新应用程序的一部分。通过这个基础的实现,开发人员能够更好地了解 HMR 的工作原理,从而能够在更高层次上应用它们。

例如,在使用 Webpack 进行开发时,可以通过配置 webpack-dev-serverwebpack-hot-middleware 插件来实现 HMR,从而使得开发人员能够在不刷新浏览器的情况下实时预览更改后的页面和应用程序。此外,HMR 也可以应用于其他类型的项目,例如 Node.js 应用程序和 Electron 应用程序等。因此,了解 HMR 的基础实现可以帮助开发人员更好地应用它们于实际项目中,提高开发效率和代码质量。

完整项目地址可在 github.com/itc-1118/hm… 中找到。