是否可以使用 express.js 清除 node.js 需要缓存?

Posted

技术标签:

【中文标题】是否可以使用 express.js 清除 node.js 需要缓存?【英文标题】:Is it possible to clear node.js require cache using express.js? 【发布时间】:2020-07-19 15:25:21 【问题描述】:

我为自己编写了 node.js 小应用程序,它在处理请求之前使用小 js 代码清除 require 缓存:

let clearCache
if (process.env.NODE_ENV === 'development') 
  const cache = require
  clearCache = (except) => 
    for (let key in cache)
      if (!except.includes(key) && key.indexOf('/node_modules/') === -1)
        delete cache[key]
  
 else 
  clearCache = () => 


const  createServer  = require('http')
const persistentPaths = ['/path/to/my/db/file']
createServer((req, res) => 
  clearCache(persistentPaths)
  require('./handleRequest')(req, res)
).listen(3000, () => )

我相信这是在开发中使用应用的最有效方式。

当我更改代码时,它会立即生效,这对我来说很好。

现在我想使用 express.js,但似乎无法使用这种方法。

好的,看来这是一个自我回答的问题,我需要使用 nodemon。

但我真的不想使用监视所有文件并重新启动整个服务器的工具。恐怕会慢很多。

在我的示例中,您可以看到我重新加载了除 db 文件之外的文件,因此我正在开发的应用程序仅连接到数据库一次并保持该连接。如果使用 nodemon 应用程序还需要加载所有 node_modules 代码,每次代码更改时都与 db 建立新连接,也许每次都会连接到 postgres 和 redis。

问题是:我不能这样做,有没有解决方案为 express.js 重新加载模块?

【问题讨论】:

【参考方案1】:

您无需编写一个实用程序。你可以使用像 chokidar 这样的模块。可以同时指定目录和忽略。

您可以在回调手表时重新加载。

来自 wiki 的示例::https://github.com/paulmillr/chokidar

const chokidar = require("chokidar");

// Full list of options. See below for descriptions.
// Do not use this example!
chokidar.watch("file", 
  persistent: true,

  ignored: "*.txt",
  ignoreInitial: false,
  followSymlinks: true,
  cwd: ".",
  disableGlobbing: false,
  awaitWriteFinish: 
    stabilityThreshold: 2000,
    pollInterval: 100,
  ,

  ignorePermissionErrors: false,
  atomic: true, // or a custom 'atomicity delay', in milliseconds (default 100)
);
// One-liner for current directory
chokidar.watch(".").on("all", (event, path) => 
  // Reload module here.
);

【讨论】:

Chokidar 会产生开销:它是单独的过程,必须查看许多文件,在代码编辑和重新加载之间增加了额外的延迟,这就是我不想使用它的原因 感谢您的回复,但是,您没有展示如何使用 chokidar 重新加载 express 应用代码,仅展示如何使用 chokidar 重新加载很容易再次要求。手表就是这样工作的,拉或推。在这里推送是不可能的,你必须拉上特定的时间戳。您可以在配置中降低频率。 这里是 chokidar 代码,它不会为每个文件创建线程。你在哪里看到节点 js 中的线程?? github.com/paulmillr/chokidar/blob/master/lib/nodefs-handler.js node js 是单线程框架。所以你不要在nodejs代码中创建一个线程。除非你使用工作模块。这里没用过。 但我没有使用word thread,只使用整个chokidar的过程。我看过一篇文章,其中一个节点实例中有 chokidar,它正在发送请求以更新快速节点实例中的代码。知道了,所以在您的示例中,chokidar 和 express 应用程序将在同一进程中运行。在您的示例中,如何在手表回调中重新加载快速应用程序?需要每次都会创建服务器的“server.js”文件吗?并且在要求之前需要杀死正在运行的服务器?或者怎么做?【参考方案2】:

做到了!如果你能分享你的想法,我会很高兴。

因为我只能用谷歌搜索 nodemon 和 chokidar 解决方案,也许我在做一些奇怪的事情,这是我的解决方案:

server.ts:

import express from 'express'
const app = express()
const port = 3000

app.listen(port, () =>
  console.log(`Example app listening at http://localhost:$port`)
)

if (process.env.NODE_ENV === 'development') 
  const cache = require
  const persistentFiles: string[] = []
  const clearCache = (except: string[]) => 
    for (let key in cache)
      if (!except.includes(key) && key.indexOf('/node_modules/') === -1)
        delete cache[key]
  
  app.use((req, res, next) => 
    clearCache(persistentFiles)
    const router = require('config/routes')
    router.handle(req, res, next)
  )
 else 
  const router = require('config/routes')
  app.use(router.handle)

还有 routes.ts:

import Router, Request, Response from 'express'
export const router = Router()

router.get('/', function (req: Request, res: Response) 
  res.send('Hello world')
)

用法:NODE_ENV=development NODE_PATH=src node src/server.js

(我的IDE在编辑的时候把ts编译成js放在那里,如果你使用VS代码可能会更复杂,我猜)

【讨论】:

以上是关于是否可以使用 express.js 清除 node.js 需要缓存?的主要内容,如果未能解决你的问题,请参考以下文章

Node js 或 Express js 的基于角色的授权

我可以在 Node.js/Express 中动态导入 TypeScript 模块吗?

node.js 和 express 的区别

express js 可以做啥

我啥时候应该在独立的 node.js 上使用 express.js

CRUD op Express.js Node.js Mysql 无法使用 MVC 插入