Node.jsでファイルを自動再読み込みする方法は?


444

Node.jsでファイルの自動再読み込みを実装する方法に関するアイデアはありますか?ファイルを変更するたびにサーバーを再起動するのにうんざりしています。どうやらNode.jsのrequire()関数は既に必要な場合はファイルをリロードしないので、次のようなことをする必要があります。

var sys     = require('sys'), 
    http    = require('http'),
    posix   = require('posix'),
    json    = require('./json');

var script_name = '/some/path/to/app.js';
this.app = require('./app').app;

process.watchFile(script_name, function(curr, prev){
    posix.cat(script_name).addCallback(function(content){
        process.compile( content, script_name );
    });
});

http.createServer(this.app).listen( 8080 );

そして、私が持っているapp.jsファイルで:

var file = require('./file');
this.app = function(req, res) { 
    file.serveFile( req, res, 'file.js');  
}

しかし、これも機能していません- process.compile()「require」が定義されていないというステートメントでエラーが発生します。process.compileevalingさapp.jsを、しかし、Node.jsのグローバルについての手掛かりを持っていません。


4
あなたはあなただけの要求ごとにこのコードを実行することができます知っている:Object.keys(require.cache).forEach(function(key) { delete require.cache[key]; });
タワー

1
参照してくださいstrongloop.com/strongblog/...
moala

回答:


562

の良い、最新の代替supervisornodemon

node.jsアプリケーションの変更を監視し、サーバーを自動的に再起動-開発に最適

使用するにはnodemon

$ npm install nodemon -g
$ nodemon app.js

2
そしてあなたがそれを使用したい場合Nitrous.io - $ nodemon -L yourfile.js(での十分な説明coderwall.com/p/aqxl_q
drzaus

3
ただし、この場合、サーバープロセスも再起動します。
フィリペ2017年

@Filipe、あなたは正しい。再度ログインするようにリダイレクトされます。特定の変更されたモジュールのみをロードしたいと思います。
ar2015

7
automatically restart the server - perfect for development誇張過ぎです。サーバーをリロードすると、私の場合は長い時間がかかるバックエンドサービスにログインすることになります。「Perfect for development」は、ソースコードを変更したときにandroid studioが行う動作を失うことなく、プロセスがメモリ内で実行されている間にクラスをホットリロードするようなものです。
ヌレティン2018年

2
npm install [--save-dev | -D] nodemonインストールをプロジェクトの範囲に制限するために使用します。
テーマフィールド

312

ノードスーパーバイザーは素晴らしいです

保存時に再開するための使用法:

npm install supervisor -g
スーパーバイザーapp.js

アイザックスによる- http://github.com/isaacs/node-supervisor


3
npm install -g supervisor。グローバルにインストールする必要があります。
カマルレディ

OSx 10.2.8では、sudoで実行する必要がありました
Timopheym

2
Windowsで次のように実行する必要がありました:"C:\Program Files\nodejs\node.exe" C:\Users\Mark\AppData\Roaming\npm\node_modules\supervisor\lib\cli-wrapper.js app.js
mpen

1
アプリのルートに-gまたはsudoなし:npm install supervisornode node_modules/supervisor/lib/cli-wrapper.js app.js(私はノードの非ルートインストールを持っています)
h-kippo '25

1
@Markこれは、ノードがあなたの中にないことを意味しますPATH
ブレイズ

87

私は簡単な方法を見つけました:

delete require.cache['/home/shimin/test2.js']

7
これは、アプリを再起動せずに外部ライブラリ(私の場合はIRCボット)を再ロードする場合に最適です。
Michelle Tilley、2011

これは素晴らしい!とてもシンプルでうまく機能します。リクエストが来たときはいつでも、状態を保持していない一連のファイルをキャッシュ解除します。
ヴォーン2013年

16
delete require.cache[require.resolve('./mymodule.js')]; 実際のパスとの取り決めを解決
エドゥアルド

これは安全ですか、または「悪い習慣」または「開発のみ」と見なされますか?
jocull

2
@jocullクラスや関数などのエクスポートを再作成する可能性があるため、安全だとは思いません。比較すると、参照が異なります===
Kroltan

20

誰かがまだこの質問に来て、標準モジュールのみを使用してそれを解決したい場合、私は簡単な例を作りました:

var process = require('process');
var cp = require('child_process');
var fs = require('fs');

var server = cp.fork('server.js');
console.log('Server started');

fs.watchFile('server.js', function (event, filename) {
    server.kill();
    console.log('Server stopped');
    server = cp.fork('server.js');
    console.log('Server started');
});

process.on('SIGINT', function () {
    server.kill();
    fs.unwatchFile('server.js');
    process.exit();
});

この例は1つのファイル(server.js)のみを対象としていますが、ファイルの配列、forループを使用してすべてのファイル名を取得するか、ディレクトリを監視することで、複数のファイルに適用できます。

fs.watch('./', function (event, filename) { // sub directory changes are not seen
    console.log(`restart server`);
    server.kill();
    server = cp.fork('server.js');    
})

このコードはNode.js 0.8 API用に作成されたもので、特定のニーズに適合していませんが、いくつかの単純なアプリで機能します。

更新:この機能は私のモジュールsimpleRGitHubリポジトリに実装されています


1
これは素晴らしいシンプルなソリューションです。私は、モデレーターから指示されたときにgitから更新することになっているボットに使用しました。問題は、いったんアプリ内に入ると、自分で再起動できないことです。ただし、あなたのメソッドを使用してボットのインスタンスを生成し、ドットファイルを監視することはできます。その後、ボットは自身を更新し、ドットファイルに触れ、ランチャーによって自動的に再起動されます。驚くばかり!
Fred

@フレッド私はこれを聞いてうれしいです:)私はこのソリューションをモジュールに実装します、すぐに、私はその機能を拡張する方法についていくつかのアイデアを持っています
micnic

ファイルwatchが必要ない場合はfs、別の信号をリッスンすることにより、なしでリロードを実行できます。
Vladimir Vukanac

18

nodemonはグーグル検索で最初に登場しました、そしてそれはトリックをするようです:

npm install nodemon -g
cd whatever_dir_holds_my_app
nodemon app.js

8

インストールできるNode-Supervisorがあります

npm install supervisor

http://github.com/isaacs/node-supervisorを参照してください


2
クラッシュした場合のサーバーの再起動についてです。また、監視対象ファイルが変更された場合、node-supervisorはプロセス全体を再起動します。厳密にはホットリロードではありません。
nalply

このツールは実際にはホットロードではありませんが、開発中にコードを自動再読み込みするだけで、変更のたびにコマンドラインでノードを再起動する必要がない場合に非常に役立ちます。
Derek Dahmer、

7

編集:私の答えは時代遅れです。Node.jsは非常に急速に変化するテクノロジーです。

モジュールのリロードについても疑問に思いました。node.jsを変更し、Githubのnalply / nodeにソースを公開しました。唯一の違いは機能requireです。オプションの2番目の引数がありますreload

require(url, reload)

app.js現在のディレクトリに再読み込みするには

app = require("./app", true);

このようなものを書くと、自動リロードがあります:

process.watchFile(script_name, function(curr, prev) {
    module = reload(script_name, true);
});

私が目にする唯一の問題は変数ですmoduleが、私は今それで働いています。


7

nodemon素晴らしいです。オプションをデバッグおよび監視するためのパラメーターを追加するだけです。

package.json

  "scripts": {
    "dev": "cross-env NODE_ENV=development nodemon --watch server --inspect ./server/server.js"
  }

コマンド: nodemon --watch server --inspect ./server/server.js

一方:

--watch server変更する場合は、アプリを再起動して.js.mjs.coffee.litcoffee、そして.json内のファイルserverフォルダが(サブフォルダを含みます)。

--inspect リモートデバッグを有効にします。

./server/server.js エントリポイント。

次に、次の構成をlaunch.json(VS Code)に追加して、いつでもデバッグを開始します。

{
    "type": "node",
    "request": "attach",
    "name": "Attach",
    "protocol": "inspector",
    "port": 9229
}

nodemonプロジェクトのdev依存関係としてインストールすることをお勧めします。したがって、チームメンバーはそれをインストールしたり、コマンド引数を覚えたりする必要はありませんnpm run dev。彼らはハッキングを開始します。

nodemonドキュメントの詳細:https : //github.com/remy/nodemon#monitoring-multiple-directories


最新バージョンのnodemon(少なくとも1.19.0)では、グロビングはサポートされていません。代わりに単にnodemon --watch server --inspect ./server/server.jsを使用してください。
Alex

情報をありがとう@Alex。回答を更新しました。
ニンファム

5

node.jsメーリングリストにこの件に関する最近のスレッドがありました。短い答えはノーです。現在、必要なファイルを自動リロードすることはできませんが、何人かの人々がこの機能を追加するパッチを開発しています。


1
+1はい。ディスカッションに参加しました。私の解決策は単純すぎることを認めました。ホットモジュール自体がそれ以上のモジュールを必要としない場合にのみ機能します。Felixのソリューションはよりよく考え抜かれていますが、auto -reloadが本当にコアに属しているかどうかは議論されています。
nalply、2010年

5

この問題のさらに別の解決策は、永久に使用することです

Foreverのもう1つの便利な機能は、ソースファイルが変更されたときに、オプションでアプリケーションを再起動できることです。これにより、機能を追加したりバグを修正したりするたびに手動で再起動する必要がなくなります。このモードでForeverを起動するには、-wフラグを使用します。

forever -w start server.js

奇妙なことに-wフラグを使用すると、私のexpress.jsアプリはCSSを使用しません。
コスタ

5

node-devはうまく機能します。npminstall node-dev

サーバーがリロードされたときにデスクトップに通知し、メッセージで成功またはエラーを表示します。

次のコマンドラインでアプリを起動します。

node-dev app.js


3

これは、ノードのホットリロードに関するブログ投稿です。これは、ホットリロードを有効にするためにノードのインストールを置き換えるために使用できるgithubノードブランチを提供します。

ブログから:

var requestHandler = require('./myRequestHandler');

process.watchFile('./myRequestHandler', function () {
  module.unCacheModule('./myRequestHandler');
  requestHandler = require('./myRequestHandler');
}

var reqHandlerClosure = function (req, res) {
  requestHandler.handle(req, res);
}

http.createServer(reqHandlerClosure).listen(8000);

これで、myRequestHandler.jsを変更するたびに、上記のコードがローカルのrequestHandlerに気づき、新しいコードに置き換えます。既存のリクエストは引き続き古いコードを使用しますが、新しい着信リクエストは新しいコードを使用します。サーバーをシャットダウンしたり、リクエストをバウンスしたり、リクエストを途中で強制終了したり、インテリジェントなロードバランサーに依存したりすることなく、すべてを実行できます。


このソリューションの唯一の点は、それが古いバージョンのノードのフォークであるため、使用する前に微調整し、最新バージョンとマージする必要があることです(古いバージョンのノードの使用を気にしない限り)。
Chetan

3

私はモジュールを自由にロード/アンロードできるかなり小さなノード「もの」を作ることに取り組んでいます(つまり、アプリケーション全体を停止せずにアプリケーションの一部を再起動することができます)。(非常に愚かな)依存関係管理を組み込んでいるので、モジュールを停止したい場合、それに依存するすべてのモジュールも停止します。

これまでのところ良いですが、モジュールをリロードする方法の問題に偶然遭遇しました。どうやら、「require」キャッシュからモジュールを削除して、ジョブを完了することもできます。ノードのソースコードを直接変更する必要がないので、次のような非常にハックなハックを思いつきました。「require」関数の最後の呼び出しをスタックトレースで検索し、その「キャッシュ」フィールドへの参照を取得します。そして、ノードへの参照を削除します。

    var args = arguments
    while(!args['1'] || !args['1'].cache) {
        args = args.callee.caller.arguments
    }
    var cache = args['1'].cache
    util.log('remove cache ' + moduleFullpathAndExt)
    delete( cache[ moduleFullpathAndExt ] )

さらに簡単に、実際には:

var deleteCache = function(moduleFullpathAndExt) {
  delete( require.cache[ moduleFullpathAndExt ] )
}

どうやら、これはうまく動作します。私はその引数["1"]が何を意味するのか全く分かりませんが、それはその仕事をしています。私はノード担当者がいつかリロード機能を実装すると信じているので、今のところこの解決策も受け入れられると思います。(ところで、私の「もの」はここにあります:https : //github.com/cheng81/wirez、数週間でそこに行くと、私が話していることを確認できます)


..もちろん、そんなに簡単ではありません。これは、呼び出しスタックにrequireする呼び出しある場合のみ機能します。まあ、ハックの上に簡単なハック:一時スクリプトにそのようなものを記述し、実行時にそれを要求します。それはうまくいきました。キャッシュから自分自身を削除することもできます
cheng81

そして実際にはそれはより簡単でした:delete(require.cache [moduleFullpathAndExt])
cheng81

Node.jsモジュールは実際には、モジュールのカプセル化が行われる方法である無名関数にラップされています。各モジュールは実際にはのようになりfunction (module, require) { /* your code */ }ます。これを考慮に入れると、をarguments[1]指しrequireます。そして、whileループは、モジュール内の別の関数内からこれを呼び出す状況のために存在します(関数階層を上に移動して、それぞれに渡される引数値をチェックします)。
JK

3

NPMからnodemonを使用できます。また、Expressジェネレーターを使用している場合は、プロジェクトフォルダー内で次のコマンドを使用できます。

nodemon npm start

またはデバッグモードを使用する

DEBUG=yourapp:* nodemon npm start

直接実行することもできます

nodemon your-app-file.js

この助けを願っています。


1

ソリューション:http : //github.com/shimondoodkin/node-hot-reload

使用される参照については、自分で注意する必要があることに注意してください。

つまり、次の場合を意味します。var x = require( 'foo'); y = x; z = x.bar; ホットリロードしました。

つまり、x、y、zに格納されている参照を置き換える必要があります。ホット再読み込みコールバック関数で。

一部の人々は、ホットリロードと自動再起動を混同します。私のnodejs-autorestartモジュールには、起動時に自動起動を有効にするアップスタート統合もあります。アプリが小さい場合は自動再起動で問題ありませんが、アプリが大きい場合はホットリロードの方が適しています。単にホットリロードが速いからです。

また、ノードインフローモジュールも気に入っています。


1

nodemonなどのツールを使用する必要はありません。IDEの機能を使用するだけです。

おそらく最も良いのは、node.jsのホットリロード機能(サーバーとブラウザの自動リロード)を備えたIntelliJ WebStormです。


1

以下は、Windowsで使用するローテクな方法です。これを次のバッチファイルに入れますserve.bat

@echo off

:serve
start /wait node.exe %*
goto :serve

ここでnode app.js、cmdシェルから実行する代わりに、を実行しますserve app.js

これにより、サーバーを実行する新しいシェルウィンドウが開きます。バッチファイルはブロックされます(/waitシェルウィンドウを閉じるまで)。この時点で、元のcmdシェルは「バッチジョブを終了しますか(Y / N)?」「N」と答えると、サーバーが再起動されます。

サーバーを再起動するたびに、サーバーウィンドウを閉じ、コマンドシェルで「N」と答えます。


1

私のアプリの構造:

NodeAPP (folder)
   |-- app (folder)
      |-- all other file is here
   |-- node_modules (folder)
   |-- package.json
   |-- server.js (my server file)

最初に次のコマンドでreloadをインストールします。

npm install [-g] [--save-dev] reload

次に、package.jsonを変更します。

"scripts": {
    "start": "nodemon -e css,ejs,js,json --watch app"
}

ここで、サーバーファイルで reloadを使用する必要があります

var express = require('express');
var reload = require('reload');
var app = express();

app.set('port', process.env.PORT || 3000);

var server = app.listen(app.get('port'), function() {
    console.log( 'server is running on port ' + app.get('port'));
});

reload(server, app);

最後の変更については、応答の最後に次のスクリプトを送信します

<script src="/reload/reload.js"></script>

次のコードでアプリを開始します。

npm start

このアプローチは機能しませんが、npmjs.com / package / reload(Expressアプリの場合)で導かれたアプローチは機能します。
Maxie Berkmann

0

これを使って:

function reload_config(file) {
  if (!(this instanceof reload_config))
    return new reload_config(file);
  var self = this;

  self.path = path.resolve(file);

  fs.watchFile(file, function(curr, prev) {
    delete require.cache[self.path];
    _.extend(self, require(file));
  });

  _.extend(self, require(file));
}

あなたが今しなければならないすべてはです:

var config = reload_config("./config");

そして設定は自動的にリロードされます:)


Nodeの一部ではないフレームワークに依存しないバージョンを手に入れましたか?
エイドリアン

0

loaddirは、ディレクトリを再帰的にすばやくロードするための私のソリューションです。

戻ることができます

{ 'path/to/file': 'fileContents...' } または { path: { to: { file: 'fileContents'} } }

それは持っています callback、ファイルが変更されたときに呼び出されます。

ファイルが十分に大きく、watch書き込みが完了する前に呼び出される状況を処理します。

私はそれをプロジェクトで1年ほど使用しており、つい最近、約束が追加されました。

戦闘テストを手伝ってください!

https://github.com/danschumann/loaddir


0

自動リロードを使用して、サーバーをシャットダウンせずにモジュールをリロードできます。

インストール

npm install auto-reload

data.json

{ "name" : "Alan" }

test.js

var fs = require('fs');
var reload = require('auto-reload');
var data = reload('./data', 3000); // reload every 3 secs

// print data every sec
setInterval(function() {
    console.log(data);
}, 1000);

// update data.json every 3 secs
setInterval(function() {
    var data = '{ "name":"' + Math.random() + '" }';
    fs.writeFile('./data.json', data);
}, 3000);

結果:

{ name: 'Alan' }
{ name: 'Alan' }
{ name: 'Alan' }
{ name: 'Alan' }
{ name: 'Alan' }
{ name: '0.8272748321760446' }
{ name: '0.8272748321760446' }
{ name: '0.8272748321760446' }
{ name: '0.07935990858823061' }
{ name: '0.07935990858823061' }
{ name: '0.07935990858823061' }
{ name: '0.20851597073487937' }
{ name: '0.20851597073487937' }
{ name: '0.20851597073487937' }

0

別の簡単な解決策は、requireを使用する代わりにfs.readFileを使用することです ことですオブジェクトを含むテキストファイルを保存し、サーバーに間隔を作成してこのオブジェクトを再できます。

長所:

  • 外部ライブラリを使用する必要はありません
  • プロダクションに関連(変更時に構成ファイルをリロード)
  • 実装が簡単

短所:

  • モジュールをリロードすることはできません-Key-Valueデータを含むjsonのみ

0

VagrantとPHPStormを使用している人にとって、File Watcherはより速いアプローチです

  • ファイルの即時同期を無効にして、保存時にのみコマンドを実行し、*。jsファイルと作業ディレクトリのスコープを作成して、このコマンドを追加する

    vagrant ssh -c "/var/www/gadelkareem.com/forever.sh restart"

forever.shのような場所

#!/bin/bash

cd /var/www/gadelkareem.com/ && forever $1 -l /var/www/gadelkareem.com/.tmp/log/forever.log -a app.js

0

いつもの容疑者がリンクされたパッケージを扱っていなかったので、私は最近この質問に行きました。私と同じようnpm linkに、開発中に多くのパッケージで構成されるプロジェクトで効果的に作業するために利用している場合、依存関係で発生した変更がリロードをトリガーすることも重要です。

node-monとpm2を試した後、node_modulesフォルダーをさらに監視するための指示に従っても、変更を取得しませんでした。ここでの回答にはカスタムソリューションがいくつかありますが、このようなものについては、個別のパッケージの方がきれいです。node-devに出会いました今日、オプションや設定なしで完全に機能します。

Readmeから:

スーパーバイザやノードモンなどのツールとは異なり、監視対象のファイルがないかファイルシステムをスキャンしません。代わりに、ノードのrequire()関数にフックして、実際に必要なファイルのみを監視します。


0
const cleanCache = (moduleId) => {
    const module = require.cache[moduleId];
    if (!module) {
        return;
    }
    // 1. clean parent
    if (module.parent) {
        module.parent.children.splice(module.parent.children.indexOf(module), 1);
    }
    // 2. clean self
    require.cache[moduleId] = null;
};

0

browser-refreshでそれを行うことができます。ノードアプリが自動的に再起動し、ブラウザーの結果ページも自動的に更新されます。欠点は、生成されたページにjsスニペットを配置する必要があることです。これが実際の例のリポジトリです。

const http = require('http');
const hostname = 'localhost';
const port = 3000;

const server = http.createServer((req, res) => {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/html; charset=UTF-8');
    res.write('Simple refresh!');
    res.write(`<script src=${process.env.BROWSER_REFRESH_URL}></script>`);
    res.end();
})

server.listen(port, hostname, () => {
    console.log(`Server running at http://${hostname}:${port}/`);

    if (process.send) {
        process.send({ event: 'online', url: `http://${hostname}:${port}/` })
    }

});

0

私はpm2を試しました:インストールも簡単で使いやすいです。結果は満足のいくものです。ただし、必要なpm2のエディションを管理する必要があります。pm 2ランタイムは無料版ですが、pm2 plusとpm2 enterpriseは無料ではありません。

Strongloop、私のインストールが失敗したか、私はそれを使用することができませんでしたので、完全ではありませんでした。


-1

現在、ホットオプション付きのWebPack開発サーバーが使用されています。次のようなスクリプトをpackage.jsonに追加できます。"hot": "cross-env NODE_ENV=development webpack-dev-server --hot --inline --watch-poll",

そして、ファイルのすべての変更は自動的に再コンパイルをトリガーします


2
この答えは問題ではありません。Webpackはフロントエンドアプリケーション用で、開発サーバーはそれ自体がWebサーバーです。問題は、Nodeに実装されたサーバーアプリケーションに関するものでした。ウェブサーバーは必要ありません。もう一つです。
DanielKhan 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.