【问题标题】:How to reload a required module at runtime?如何在运行时重新加载所需的模块?
【发布时间】:2017-04-18 05:01:10
【问题描述】:

我想知道如何在运行时重新加载 Node.js 模块。

假设我有以下代码:

index.js

var myModule = require("./app.js");

app.js

var express = require("express");
express.listen(3000, function() {
    console.log("app listening on port 3000");
});

我尝试了多种方法来重新加载 index.js 模块中所需的模块。但 Express 应用不会重新启动。

我想让 index.js 继续运行,因为它可以即时处理重新编译 Babel 模块。并且带有 express 服务器的 app.js 模块需要完全重启。

有没有办法在不为 app.js 启动第二个进程的情况下做到这一点?

【问题讨论】:

  • 通过 npm install -g browser-sync 尝试浏览器同步

标签: javascript node.js express babeljs


【解决方案1】:

require-uncached 是一个 npm 模块,它每次都会清除缓存并从源代码中加载一个新模块,根据您的标题,这正是您似乎感兴趣的内容。要使用它,您可以简单地使用以下代码:

const requireUncached = require('require-uncached');
requireUncached('./app.js');

在执行此操作之前,可能需要确保停止所有以前的 app.js 代码(包括 Express 服务器),以免它们在同一端口上发生冲突。

另外,我建议考虑这种方法是否是真的最好的答案 - 我确信像 pm2 这样的库可以处理停止和重新启动节点实例,而不会产生不需要数据的风险徘徊,这可能会导致内存泄漏。

【讨论】:

  • 我正在使用 browserify 编译我的客户端代码,当我在 babel 中编写服务器代码时,我也想重新加载它。我的目标是避免开发多个nodejs窗口,一个用于客户端代码捆绑器,一个用于快速服务器。我会对此进行调查,并尽快检查您的答案。谢谢!
  • @Azarus 我能理解你为什么不想同时运行两个 Node 实例(如果我能帮忙的话,我也不想这样做!),我只是有点担心这个方法可能会中断。不过,试一试,让我知道它是怎么回事 - 我会尽力帮助您解决您在遵循我的回答时遇到的任何问题。
【解决方案2】:

如果您只想重新启动服务器而不重新启动进程,我建议您使用http.Server.close 方法。根据 express docs app.listen 方法返回一个 http.Server 对象,所以重新加载看起来像这样:

app.js

const express = require("express");

app = express();

// Define the listener function separately so it can be used on restart
function listener() {
  console.log("app listening on port 3000");
}

// start the server and save a reference to it for our restart function
const server = app.listen(3000, listener);

// Export a restart function to be used by index.js
exports.restart = function() {
  server.close(function() {
    // Server is closed, start listening again
    server.listen(3000, listener) // Use the same listener function as app.listen
  });
};

index.js

const myModule = require("./app.js"); // Output: "app listening on port 3000"

// Restart the server, keep the process
myModule.restart(); // Output: "app listening on port 3000"

【讨论】:

    【解决方案3】:

    我建议你在 web pack 中使用 lazyload,我在 link 中有我自己的帖子。

    第一个应用程序

    angular.module('myApp', ['ui.router','oc.lazyLoad'])
        .config(function ($stateProvider, $locationProvider, $ocLazyLoadProvider) {
                $stateProvider
                    .state("home", {
                        url: "/home",
                        templateUrl: "Home.html",
                        controller: 'homeCtrl',
                        resolve: { 
                            loadMyCtrl: ['$ocLazyLoad', function ($ocLazyLoad) {
                                return $ocLazyLoad.load('homeCtrl.js');
                            }]
                        }
                    })
                .state("profile", {
                    url:"/profile",
                    templateUrl: "profile.html",
                     resolve: {
                          loadMyCtrl: ['$ocLazyLoad', function ($ocLazyLoad) {
                          return $ocLazyLoad.load('someModule.js');
                            }]
                        }
                })
    
        });
    

    第二个应用

    (function () {
    var mynewapp=angular.module('someApp',['myApp']);
    
    mynewapp.config(function(){
    
      //your code to route from here! 
    
    });
          mynewapp.controller("profileCtrl", function ($scope) {
    
                console.log("reached profile controller");
            });
    
    })();
    

    也是直播Plunker

    【讨论】:

    • 这是一个仅限 Angular 的解决方案吗?如果是这样,我认为这不会特别有用,因为 OP 想要重新启动服务器端 ExpressJS 服务器。
    • 我的问题与角度无关,它是一个 nodejs 问题。
    【解决方案4】:

    现在很简单,我更喜欢自己写,减少依赖。

    
    function clearModule(moduleName) {
      let mp = require.resolve(moduleName)
      if (require.cache[mp]) {
        delete require.cache[mp]
        console.log(`[clear] module: ${mp}`)
      }
    }
    
    function requireReload(moduleName) {
      clearModule(moduleName);
      return require(moduleName);
    }
    
    

    【讨论】:

    • 并非所有东西都必须是箭头函数。您可以随心所欲地使用 function 关键字。
    • 你说得对,我上一份工作被逼使用箭头功能,我应该改变。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-18
    • 2018-01-06
    • 2017-03-30
    • 2011-02-20
    • 1970-01-01
    • 2016-01-02
    相关资源
    最近更新 更多