require 动态加载_TS/JS 模块自加载与热重载

本文介绍了如何在 NodeJS 应用中实现动态加载和热重载模块,通过弱引用避免强引用问题,利用模块代理实现自动加载。详细探讨了强引用和弱引用的概念,以及如何利用文件监听和缓存重载机制实现热重载。最后,展示了创建根实例和命名空间的方法,以及注意事项和最终实现。
摘要由CSDN通过智能技术生成

427cc5ad625b42bb5382c8c6fae70fcc.png

很多时候,特别是在开发过程中,我们希望能够不需要频繁重启服务就立即应用改动的代码。但在常驻内存的服务器应用中,要实现这种需求并不简单。

强引用和弱引用

因为常驻内存的自然特性,变量存在强引用的问题,特别是在像 CommonJS 这样的模块加载方案中,一旦 `require/import` 的模块被赋值到了新的变量中,它就自动形成了对模块的“拷贝”,即原模块发生改变之后,在导入的地方,这个改变将毫无作用。例如下面的例子:

// app.ts
const app = {
     name: "app" /* ... */ };
export default app;


// index.ts
import app from "./app";

console.log(app.name); // => app

现在,修改 app.ts 中的代码为如下这样子:

const app = {
     name: "my-app" /* ... */ };
export default app;

这并没有任何作用,因为如果不重启进程,新代码将不会被运行。但 NodeJS 提供了重载模块的方案。默认地,NodeJS 将模块缓存到 `require.cache` 中,因此,理论上,只要删除缓存,并重新导入即可。因此,开发者可以实现下面这样的逻辑,用来监听文件改变,并自动重载模块。

import {
     watch } from "chokidar"; // chokidar 是一个兼容更多平台的文件监听模块

watch(__dirname).on("change", (filename) => {
    
    delete require.cache[filename];
    require(filename);
});

但实际上这毫无作用,因为在 index.ts 中,`import app from "./app";` 创建了一个对模块的
强引用(不完整的拷贝),当模块本身发生了改变并重载(重新赋值到缓存中),强引用就会立即变成完整的拷贝,就像下面这样:

var cache = {
     name: "app" };
var copy = cache;

// 如果 cahce 被重载
cache = {
     name: "my-app" };

// copy 将不会有任何改变
console.log(capy.name) // => app

要实现缓存重载后原来的引用也能够发生改变,则需要通过"弱引用"导入。即每一处使用导入对象的地方,都重新检查缓存,例如重新调用 `require`,类似下面这样:

console.log(require("./app").default.name);

如此一来,当缓存被重载,`require` 就会返回新的对象。

自动加载与热重载:模块代理

<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值