Nodejs 有没有办法取消 node.js 对 require 模块的缓存?
Nodejs 有没有办法取消 node.js 对 require 模块的缓存?
譬如我想用 express 写这样一个 router:
function (req, res) {
try {
var title = req.param('title'),
viewTemplate = 'path/to/template',
config = require('path/to/config') || {};
res.render(viewTemplate, config);
} catch (e) {
// handleErr('400', res);
}
};
它的功能是响应 ‘/:title’ URL, 用 ‘path/to/config’ 中的配置数据去渲染 ‘path/to/template’ 里的模板文件,返回页面。
调试的时候遇到一个有点麻烦的地方,就是修改了配置数据之后,必须重启服务器才能看到修改后的结果。
也就是 config = require('path/to/config') || {}
这个值因为 require 的时候模块缓存的存在,刷新页面的时候并不会动态去重新加载一次 ‘path/to/config.js’ 文件,导致这个文件的修改只能通过重启才能体现。
有没有方法可以取消 require 的时候的缓存呢?对我来说,如果可以在开发的时候取消这个,开发起来就方便很多了。
顺便,stackoverflow 上面貌似说不可能(http://stackoverflow.com/questions/9210542/node-js-require-cache-possible-to-invalidate)。期盼大牛现身辟谣。
Nodejs 有没有办法取消 node.js 对 require 模块的缓存?
问题背景
假设你正在使用 Express 编写一个路由处理函数:
function (req, res) {
try {
var title = req.param('title'),
viewTemplate = 'path/to/template',
config = require('path/to/config') || {};
res.render(viewTemplate, config);
} catch (e) {
// handleErr('400', res);
}
}
这个路由的功能是响应 /:title
URL,并使用 path/to/config
文件中的配置数据来渲染 path/to/template
模板文件。
在调试过程中,你发现了一个问题:每次修改了 path/to/config.js
文件后,必须重启服务器才能看到配置的更新。这是因为 Node.js 在 require
模块时会缓存模块,以提高性能。
解决方案
虽然 Node.js 的 require
缓存机制设计初衷是为了提升性能,但在某些场景下,如开发调试中,我们可能需要手动取消这种缓存。以下是几种解决方法:
方法一:删除缓存项
你可以通过手动删除 require.cache
中对应的缓存项来实现这一目的。
const fs = require('fs');
const path = require('path');
function reloadConfig(configPath) {
const modulePath = path.resolve(configPath);
if (modulePath in require.cache) {
delete require.cache[modulePath];
}
return require(modulePath);
}
// 使用示例
function (req, res) {
try {
var title = req.param('title'),
viewTemplate = 'path/to/template',
config = reloadConfig('path/to/config') || {};
res.render(viewTemplate, config);
} catch (e) {
// handleErr('400', res);
}
}
在这个示例中,我们定义了一个 reloadConfig
函数,它接受一个路径参数并删除该路径对应的缓存项,然后重新 require
该模块。这样就可以确保每次调用时都能获取到最新的配置文件内容。
方法二:使用 module.parent.children
另一种方法是遍历 module.parent.children
数组,找到并删除对应的缓存项。
function reloadConfig(configPath) {
const modulePath = require.resolve(configPath);
for (let child of module.parent.children) {
if (child.filename === modulePath) {
module.parent.children.splice(module.parent.children.indexOf(child), 1);
}
}
return require(modulePath);
}
这种方法同样可以确保每次调用时都能重新加载配置文件。
总结
通过上述方法,你可以在开发环境中取消 Node.js 的 require
缓存,从而实现实时查看配置文件的更新。不过请注意,在生产环境中,应避免频繁地清除缓存,以免影响性能。
你需要 nodemon
或者 supervisor
或者 grunt
要么就用fs读文件吧
嗯,在用 grunt,先试试看 谢谢啦!
貌似也不错,可以写成 json
不过果然是不能通过编码的方式来取消 require 的缓存吗?
参考require.cache
代码上很简单
delete require.cache[‘path/to/config’] config = require(‘path/to/config’)
代码背后的东西不这么简单,比如说通知你其他的代码更新引用等等。如果只是配置的话应该还好
谢谢! 我看文档还是不熟啊
谢谢大牛!
我觉得你这样是走进误区了,require,cache是非常节省资源的设计,你那样说明你误用require了,既然需要config.js中的配置来渲染数据,为啥配置要频繁改动,如果config频繁改动为什么不反悔一个对象通过穿进去的参数动态改变配置呢!
代码热更新可以使用 bearcat
watch感觉不可靠…
delete require.cache[require.resolve(path)]
不能简单的直接取消 require
的缓存,因为有些模块在载入的时候会做一些初始化工作,如果 一刀切地 取消 require
的缓存,就会导致这些模块初始化多次,在实际使用的时候就会出问题。
另外,要实现代码热更新,编写程序的时候就必须为热更新而做很多改变,比如不能长期引用某个对象或函数,所有的东西都需要通过一个函数来动态返回最新的引用,然后再操作,总会另代码显得很怪,比如:
// 原来的使用方式
var my = require('./my_module');
my.doSomething1();
my.doSomething2();
// 新的使用方式
require(’./my_module’).doSomethig1();
require(’./my_module’).doSomethig2()
目前最完美稳定的解决方法是 重启进程!!!!
可以取消 Node.js 对 require
模块的缓存。你可以使用 delete require.cache
来手动删除模块缓存,从而实现每次请求时重新加载配置文件。
以下是示例代码:
const path = require('path');
const fs = require('fs');
function loadConfig(configPath) {
delete require.cache[require.resolve(configPath)];
return require(configPath);
}
function (req, res) {
try {
var title = req.param('title'),
viewTemplate = 'path/to/template',
configPath = 'path/to/config';
var config = loadConfig(configPath);
res.render(viewTemplate, config);
} catch (e) {
// handleErr('400', res);
}
}
在这个示例中,我们定义了一个 loadConfig
函数来重新加载配置文件。每次调用 loadConfig
函数时,它会删除当前的缓存,并重新加载配置文件。
这种方法在开发过程中非常有用,因为它允许你在不重启服务器的情况下看到配置文件的更改。但在生产环境中,建议避免频繁地修改配置文件,以确保应用的稳定性和性能。