Node.jsでは、他のファイルから関数を「含める」にはどうすればよいですか?


968

app.jsというファイルがあるとします。ものすごく単純:

var express = require('express');
var app = express.createServer();
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.get('/', function(req, res){
  res.render('index', {locals: {
    title: 'NowJS + Express Example'
  }});
});

app.listen(8080);

「tools.js」内に関数がある場合はどうなりますか。それらをapps.jsで使用するためにどのようにインポートしますか?

または...「ツール」をモジュールにして、それを必要とするのでしょうか?<<難しいようです。tools.jsファイルの基本的なインポートを行います。


4
ここで私をrequire驚かせたのは、Windowsの同じディレクトリにあるフォルダーを使用したことです。:あなたは、アドレッシングUNIX形式を使用するために持っている./mydir代わりに、昔ながらのmydir
ベン・

1
スクリプトをインポートし、ファイルにエクスポートし、外部node_modulesフォルダーからモジュールを含めるためのモジュールを作成しました。npmjs.com/package/node-import役立つことを願っています。ありがとう!
Nanang Mahdaen El-Agung 2015

回答:


1415

任意のjsファイルを要求できます。公開するものを宣言するだけです。

// tools.js
// ========
module.exports = {
  foo: function () {
    // whatever
  },
  bar: function () {
    // whatever
  }
};

var zemba = function () {
}

そしてあなたのアプリファイルで:

// app.js
// ======
var tools = require('./tools');
console.log(typeof tools.foo); // => 'function'
console.log(typeof tools.bar); // => 'function'
console.log(typeof tools.zemba); // => undefined

101
+1うまくできていて、インポートされたコードをそれ自体の名前空間に限定することさえします。これは後で書き留めておきます。
Evan Plaice、2012年

8
外部スクリプトをインポートできるのかしら。require("http://javascript-modules.googlecode.com/svn/functionChecker.js")モジュールを正しくインポートしていないようです。外部スクリプトをインポートする他の方法はありますか?
アンダーソングリーン

6
そして、もし変数を関数Likeに渡さなければならない場合、bar:function(a、b){// some code}
Nishutosh Sharma

5
プロパティを公開しているので、module.exportsの代わりにエクスポートを使用します。:module.exportsは対輸出stackoverflow.com/questions/5311334/...
ファーム

4
foo()関数内で関数bar()を呼び出す方法は、ある関数に別の関数にアクセスする方法を意味します
pitu

303

他のすべての回答にもかかわらず、従来どおりnode.jsソースファイルにファイルを含めたい場合は、これを使用できます。

var fs = require('fs');

// file is included here:
eval(fs.readFileSync('tools.js')+'');
  • +''ファイルの内容をオブジェクトではなく文字列として取得するには、空の文字列連結が必要です(必要に応じて使用することもでき.toString()ます)。
  • eval()は関数内では使用できず、グローバルスコープ内で呼び出す必要あります。そうしないと、関数や変数にアクセスできません(つまり、include()ユーティリティ関数などを作成できません)。

ほとんどの場合、これは悪い習慣であり、代わりにモジュール作成する必要があることに注意してください。ただし、ローカルコンテキスト/名前空間の汚染が本当に必要な状況であるというまれな状況があります。

2015年8月6日更新

「インポートされた」ファイルで定義された関数と変数はインポートを行うコードからアクセスできないため"use strict";、これは(「ストリクトモード」の場合)で機能しないことにも注意してください。厳格モードでは、言語標準の新しいバージョンで定義されているいくつかのルールが適用されます。これは、ここで説明する解決策を回避するもう1つの理由かもしれません。


41
これは、クライアント・サイド用に設計されたJSライブラリーをノード・スタイルのフォークを維持する必要なしにnode.jsアプリに迅速に配置するのに役立ちます。
Kos

18
モジュールを書くのではなく、コードを含めることについての元の質問に答えました。前者特定の状況で利点あります。また、requireに関する仮定が間違っています。コードは確かにevalされていますが、コードは独自の名前空間に残り、呼び出しコンテキストの名前空間を「汚染」する方法がないため、自分でeval()する必要があります。ほとんどの場合、私の回答に記載されている方法を使用することは悪い習慣ですが、それがTIMEX用かどうかを判断するのは私ではありません。
Udo G

14
@EvanPlaice:実際に質問に答えるより良い提案がありますか?モジュールではないファイルを含める必要がある場合、これよりも優れたアプローチがありますか?
2012

8
インクルードが必要な場合と必要な場合がありますが、これらはほとんどのプログラミング言語で根本的に異なる2つの概念であるNode JSです。jsを適所に含める機能は、正直に言うとNodeの一部である必要がありますが、それを評価することは本質的に適切なソリューションです。賛成。
J.マーティン

4
互換性があることに注意してください厳密使用 -として使用厳密には等、評価を介して新しい変数の導入を阻止することにより評価の使用を制限します
チンボ

189

新しい機能や新しいモジュールは必要ありません。名前空間を使用したくない場合は、呼び出すモジュールを実行するだけです。

tools.js

module.exports = function() { 
    this.sum = function(a,b) { return a+b };
    this.multiply = function(a,b) { return a*b };
    //etc
}

app.js

またはmyController.jsのような他の.jsで:

の代わりに

var tools = require('tools.js') 名前空間を使用して、次のようなツールを呼び出す必要があります。 tools.sum(1,2);

私たちは単に呼び出すことができます

require('tools.js')();

その後

sum(1,2);

私の場合、コントローラctrls.jsを含むファイルがあります

module.exports = function() {
    this.Categories = require('categories.js');
}

そして私はCategoriesすべてのコンテキストでパブリッククラスとして使用できますrequire('ctrls.js')()


12
+1が増えないのはなぜですか?これは、質問の質問に対する実際の解決策です(「公式」の質問ではありません)。ノードは、未定義ではなく実際のファイルを指す代わりに、有用なコールスタックを提供できるため、eval()よりも100万倍もデバッグが簡単です。
user3413723

5
インポートしたモジュールでは「strict」モードを使用できないことに注意してください。
David

1
@ニックパノフ:素晴らしい!これはthis機能するので注意してください。これは、関数が直接呼び出された場合(関数にバインドされていない場合)はグローバルスコープであるためです。
Udo G

3
...私は別の方法の変数があるので、別れることができませんでしたすべての相互相関と同じスコープ内のすべてをする必要が必要であろうと1000 +ラインファイルを持っていた-これはちょうど私の人生、冗談を変更require('blah.js')();すべきそれらすべてを同じスコープにインポートできるようにします!!! ありがとう!!!
サムジョンソン

2
これは素晴らしいヒントです!注意:標準のfunction(){}宣言ではなく、()=> {}ショートカット構文を使用してmodule.exports関数を宣言すると、失敗します。問題がどこにあるのかを理解するのに1時間かかりました。(矢印関数には独自の 'this'プロパティがありません:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Ryan Griggs

117

2つのjsファイルを作成する

// File cal.js
module.exports = {
    sum: function(a,b) {
        return a+b
    },
    multiply: function(a,b) {
        return a*b
    }
};

メインjsファイル

// File app.js
var tools = require("./cal.js");
var value = tools.sum(10,20);
console.log("Value: "+value);

コンソール出力

Value: 30

これはどのバージョンのjsで動作しますか?
Mirv-マット

39

以下は、わかりやすく簡単な説明です。

Server.jsコンテンツ:

// Include the public functions from 'helpers.js'
var helpers = require('./helpers');

// Let's assume this is the data which comes from the database or somewhere else
var databaseName = 'Walter';
var databaseSurname = 'Heisenberg';

// Use the function from 'helpers.js' in the main file, which is server.js
var fullname = helpers.concatenateNames(databaseName, databaseSurname);

Helpers.jsコンテンツ:

// 'module.exports' is a node.JS specific feature, it does not work with regular JavaScript
module.exports = 
{
  // This is the function which will be called in the main file, which is server.js
  // The parameters 'name' and 'surname' will be provided inside the function
  // when the function is called in the main file.
  // Example: concatenameNames('John,'Doe');
  concatenateNames: function (name, surname) 
  {
     var wholeName = name + " " + surname;

     return wholeName;
  },

  sampleFunctionTwo: function () 
  {

  }
};

// Private variables and functions which will not be accessible outside this file
var privateFunction = function () 
{
};

34

NodeJSの 'include'関数も探していて、Udo Gによって提案されたソリューションを確認しました。メッセージhttps://stackoverflow.com/a/8744519/2979590を参照してください。彼のコードは、含まれているJSファイルでは動作しません。最後に私はそのような問題を解決しました:

var fs = require("fs");

function read(f) {
  return fs.readFileSync(f).toString();
}
function include(f) {
  eval.apply(global, [read(f)]);
}

include('somefile_with_some_declarations.js');

確かに、それは役立ちます。


2
ハックがいかに醜いかは理解していますが、それは確かに役に立ちました。
lindhe

30

たとえばapp.js、2つのファイルを作成しますtools.js

app.js

const tools= require("./tools.js")


var x = tools.add(4,2) ;

var y = tools.subtract(4,2);


console.log(x);
console.log(y);

tools.js

 const add = function(x, y){
        return x+y;
    }
 const subtract = function(x, y){
            return x-y;
    }

    module.exports ={
        add,subtract
    }

出力

6
2

26

私たちは、関数を呼び出すしたいと言う(Ping)にして(30,20)を追加してあるlib.jsからファイルmain.js

main.js

lib = require("./lib.js")

output = lib.ping();
console.log(output);

//Passing Parameters
console.log("Sum of A and B = " + lib.add(20,30))

lib.js

this.ping=function ()
{
    return  "Ping Success"
}
//Functions with parameters
this.add=function(a,b)
    {
        return a+b
    }

1
これは機能しますが、スクリプトを含めるときにモジュール構文を使用するのではないですか?
ココドコ

25

Node.jsのvmモジュールは、現在のコンテキスト(グローバルオブジェクトを含む)内でJavaScriptコードを実行する機能を提供します。http://nodejs.org/docs/latest/api/vm.html#vm_vm_runinthiscontext_code_filenameを参照してください

現在のところ、vmモジュールには、新しいコンテキストから呼び出されたときにrunInThisContextが正しく動作しないというバグがあることに注意してください。これは、メインプログラムが新しいコンテキスト内でコードを実行し、そのコードがrunInThisContextを呼び出す場合にのみ重要です。https://github.com/joyent/node/issues/898を参照してください

悲しいことに、フェルナンドが提案したwith(global)アプローチは、「function foo(){}」のような名前付き関数では機能しません

簡単に言えば、これは私のために働くinclude()関数です:

function include(path) {
    var code = fs.readFileSync(path, 'utf-8');
    vm.runInThisContext(code, path);
}

私は別のSO回答でvm.runInThisContextを見つけ、それを使用して、「バニラ」Javascriptコードファイルを含めました。しかし、それを使用してノードの機能に依存するコード(たとえば、「var fs = require( 'fs')」)を含めようとしたところ、機能しませんでした。ただし、その場合、いくつかの回答に記載されている「評価」ソリューションは実際に機能します。
Dexygen 2013年

これについてもう少し考えてみます。ノードの機能に依存するコードを含める必要が生じたときは、モジュールを作成するときです。評価ソリューションはそのプロセスの最初のステップになる可能性があります
Dexygen

2019年にnode.jsで機能した唯一のもの
meesern

13

ウド・Gは言った:

  • eval()は関数内では使用できず、グローバルスコープ内で呼び出す必要があります。そうしないと、関数や変数にアクセスできません(つまり、include()ユーティリティ関数などを作成できません)。

彼の言う通りですが、関数からグローバルスコープに影響を与える方法があります。彼の例を改善する:

function include(file_) {
    with (global) {
        eval(fs.readFileSync(file_) + '');
    };
};

include('somefile_with_some_declarations.js');

// the declarations are now accessible here.

それが役に立てば幸い。


12

それは私と一緒に次のように働きました...

Lib1.js

//Any other private code here 

// Code you want to export
exports.function1 = function(params) {.......};
exports.function2 = function(params) {.......};

// Again any private code

Main.jsファイルに、Lib1.jsを含める必要があります

var mylib = requires('lib1.js');
mylib.function1(params);
mylib.function2(params);

Lib1.jsを必ずnode_modulesフォルダー配置してください


11

関数をグローバル変数に入れることもできますが、ツールスクリプトをモジュールに変換することをお勧めします。それほど難しくはありませんexports。パブリックAPIをオブジェクトにアタッチするだけです。見てみましょう理解のNode.jsの輸出モジュールいくつかの詳細については。


1
例はリンクよりも優れています
tno2007

11

私の意見ではこれを行う別の方法は、(function(/ * things here * /){})();を使用してrequire()関数を呼び出すときにlibファイルのすべてを実行することです。これを行うと、eval()ソリューションとまったく同じように、これらすべての関数がグローバルスコープになります

src / lib.js

(function () {
    funcOne = function() {
            console.log('mlt funcOne here');
    }

    funcThree = function(firstName) {
            console.log(firstName, 'calls funcThree here');
    }

    name = "Mulatinho";
    myobject = {
            title: 'Node.JS is cool',
            funcFour: function() {
                    return console.log('internal funcFour() called here');
            }
    }
})();

そして、あなたのメインコードでは、次のような名前で関数を呼び出すことができます:

main.js

require('./src/lib')
funcOne();
funcThree('Alex');
console.log(name);
console.log(myobject);
console.log(myobject.funcFour());

この出力を行います

bash-3.2$ node -v
v7.2.1
bash-3.2$ node main.js 
mlt funcOne here
Alex calls funcThree here
Mulatinho
{ title: 'Node.JS is cool', funcFour: [Function: funcFour] }
internal funcFour() called here
undefined

有料atention 未定義あなたが私を呼び出したときに()object.funcFourをあなたがロードした場合、それは同じになりますのeval() 。それが役に立てば幸い :)


10

私はちょうどあなたがあなたからの輸入だけで特定の機能必要がある場合には、追加したいtools.jsを、あなたが使用することができ、分割代入バージョン以降のNode.jsでサポートされて6.4参照- node.greenを


:( 両方のファイルが同じフォルダーにある)

tools.js

module.exports = {
    sum: function(a,b) {
        return a + b;
    },
    isEven: function(a) {
        return a % 2 == 0;
    }
};

main.js

const { isEven } = require('./tools.js');

console.log(isEven(10));

出力: true


これにより、次の(一般的な)割り当ての場合のように、これらの関数を別のオブジェクトのプロパティとして割り当てることも回避できます。

const tools = require('./tools.js');

あなたが呼び出す必要がある場所tools.isEven(10)


注意:

正しいパスをファイル名の前に付けることを忘れないでください-両方のファイルが同じフォルダーにある場合でも、前に付ける必要があります ./

Node.js docsから:

ファイルを示す先頭の「/」、「./」、または「../」がない場合、モジュールはコアモジュールであるか、node_modulesフォルダーからロードされている必要があります。


10

app.js

let { func_name } = require('path_to_tools.js');
func_name();    //function calling

tools.js

let func_name = function() {
    ...
    //function body
    ...
};

module.exports = { func_name };

3

ファイルをインクルードし、それを特定の(非グローバル)コンテキストで実行する

fileToInclude.js

define({
    "data": "XYZ"
});

main.js

var fs = require("fs");
var vm = require("vm");

function include(path, context) {
    var code = fs.readFileSync(path, 'utf-8');
    vm.runInContext(code, vm.createContext(context));
}


// Include file

var customContext = {
    "define": function (data) {
        console.log(data);
    }
};
include('./fileToInclude.js', customContext);

2

これは私がこれまでに作成した最良の方法です。

var fs = require('fs'),
    includedFiles_ = {};

global.include = function (fileName) {
  var sys = require('sys');
  sys.puts('Loading file: ' + fileName);
  var ev = require(fileName);
  for (var prop in ev) {
    global[prop] = ev[prop];
  }
  includedFiles_[fileName] = true;
};

global.includeOnce = function (fileName) {
  if (!includedFiles_[fileName]) {
    include(fileName);
  }
};

global.includeFolderOnce = function (folder) {
  var file, fileName,
      sys = require('sys'),
      files = fs.readdirSync(folder);

  var getFileName = function(str) {
        var splited = str.split('.');
        splited.pop();
        return splited.join('.');
      },
      getExtension = function(str) {
        var splited = str.split('.');
        return splited[splited.length - 1];
      };

  for (var i = 0; i < files.length; i++) {
    file = files[i];
    if (getExtension(file) === 'js') {
      fileName = getFileName(file);
      try {
        includeOnce(folder + '/' + file);
      } catch (err) {
        // if (ext.vars) {
        //   console.log(ext.vars.dump(err));
        // } else {
        sys.puts(err);
        // }
      }
    }
  }
};

includeFolderOnce('./extensions');
includeOnce('./bin/Lara.js');

var lara = new Lara();

エクスポートするものを通知する必要があります

includeOnce('./bin/WebServer.js');

function Lara() {
  this.webServer = new WebServer();
  this.webServer.start();
}

Lara.prototype.webServer = null;

module.exports.Lara = Lara;

2

あなたがファイルabc.txtなどを持っているように?

2つのファイルを作成します:fileread.jsおよびfetchingfile.js、次にfileread.jsこのコードを記述します。

function fileread(filename) {
    var contents= fs.readFileSync(filename);
        return contents;
    }

    var fs = require("fs");  // file system

    //var data = fileread("abc.txt");
    module.exports.fileread = fileread;
    //data.say();
    //console.log(data.toString());
}

fetchingfile.js書き込み、このコード:

function myerror(){
    console.log("Hey need some help");
    console.log("type file=abc.txt");
}

var ags = require("minimist")(process.argv.slice(2), { string: "file" });
if(ags.help || !ags.file) {
    myerror();
    process.exit(1);
}
var hello = require("./fileread.js");
var data = hello.fileread(ags.file);  // importing module here 
console.log(data.toString());

さて、ターミナルで:$ node fetchingfile.js --file = abc.txt

引数としてファイル名readfile.jsを渡しているだけでなく、ファイルを渡す代わりにすべてのファイルを含めています。

ありがとう


2

単純にできrequire('./filename')ます。

例えば。

// file: index.js
var express = require('express');
var app = express();
var child = require('./child');
app.use('/child', child);
app.get('/', function (req, res) {
  res.send('parent');
});
app.listen(process.env.PORT, function () {
  console.log('Example app listening on port '+process.env.PORT+'!');
});
// file: child.js
var express = require('express'),
child = express.Router();
console.log('child');
child.get('/child', function(req, res){
  res.send('Child2');
});
child.get('/', function(req, res){
  res.send('Child');
});

module.exports = child;

その点に注意してください:

  1. 子ファイルでPORTをリッスンすることはできません。親ExpressモジュールのみがPORTリスナーを持っています
  2. 子供は親ルーターのエクスプレスではなく、「ルーター」を使用しています。

1

同様に、モジュールを作成せずにコードを含めるオプションも探していました。Node.jsサービスには別のプロジェクトからテストされた同じスタンドアロンのソースを使用します-そしてjmparatteの答えは私のためにそれをしました。

利点は、名前空間を汚染しないこと、私は問題がなく、"use strict";うまく機能することです。

ここに完全なサンプルがあります:

ロードするスクリプト-/lib/foo.js

"use strict";

(function(){

    var Foo = function(e){
        this.foo = e;
    }

    Foo.prototype.x = 1;

    return Foo;

}())

SampleModule-index.js

"use strict";

const fs = require('fs');
const path = require('path');

var SampleModule = module.exports = {

    instAFoo: function(){
        var Foo = eval.apply(
            this, [fs.readFileSync(path.join(__dirname, '/lib/foo.js')).toString()]
        );
        var instance = new Foo('bar');
        console.log(instance.foo); // 'bar'
        console.log(instance.x); // '1'
    }

}

これが何とか役に立ったことを願っています。


1

node.jsおよびexpress.jsフレームワークを使用する別の方法

var f1 = function(){
   console.log("f1");
}
var f2 = function(){
   console.log("f2");
}

module.exports = {
   f1 : f1,
   f2 : f2
}

これをsという名前のjsファイルとstaticsフォルダーに保存します

次に、関数を使用します

var s = require('../statics/s');
s.f1();
s.f2();

1

私はこれをHTMLテンプレートのために処理するかなり大まかな方法​​を考え出しました。PHPと同様<?php include("navigation.html"); ?>

server.js

var fs = require('fs');

String.prototype.filter = function(search,replace){
    var regex = new RegExp("{{" + search.toUpperCase() + "}}","ig");
    return this.replace(regex,replace);
}

var navigation = fs.readFileSync(__dirname + "/parts/navigation.html");

function preProcessPage(html){
    return html.filter("nav",navigation);
}

var express = require('express');
var app = express();
// Keep your server directory safe.
app.use(express.static(__dirname + '/public/'));
// Sorta a server-side .htaccess call I suppose.
app.get("/page_name/",function(req,res){
    var html = fs.readFileSync(__dirname + "/pages/page_name.html");
    res.send(preProcessPage(html));
});

page_name.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>NodeJS Templated Page</title>
    <link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css">
    <link rel="stylesheet" type="text/css" href="/css/font-awesome.min.css">
    <!-- Scripts Load After Page -->
    <script type="text/javascript" src="/js/jquery.min.js"></script>
    <script type="text/javascript" src="/js/tether.min.js"></script>
    <script type="text/javascript" src="/js/bootstrap.min.js"></script>
</head>
<body>
    {{NAV}}
    <!-- Page Specific Content Below Here-->
</body>
</html>

navigation.html

<nav></nav>

ロードされたページの結果

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>NodeJS Templated Page</title>
    <link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css">
    <link rel="stylesheet" type="text/css" href="/css/font-awesome.min.css">
    <!-- Scripts Load After Page -->
    <script type="text/javascript" src="/js/jquery.min.js"></script>
    <script type="text/javascript" src="/js/tether.min.js"></script>
    <script type="text/javascript" src="/js/bootstrap.min.js"></script>
</head>
<body>
    <nav></nav>
    <!-- Page Specific Content Below Here-->
</body>
</html>

0

複数のCPUとマイクロサービスアーキテクチャを活用してスピードアップしたい場合...フォークされたプロセスでRPCを使用します。

複雑に聞こえますが、タコを使用すれば簡単です。

次に例を示します。

tools.jsに追加:

const octopus = require('octopus');
var rpc = new octopus('tools:tool1');

rpc.over(process, 'processRemote');

var sum = rpc.command('sum'); // This is the example tool.js function to make available in app.js

sum.provide(function (data) { // This is the function body
    return data.a + data.b;
});

app.jsに、次を追加します。

const { fork } = require('child_process');
const octopus = require('octopus');
const toolprocess = fork('tools.js');

var rpc = new octopus('parent:parent1');
rpc.over(toolprocess, 'processRemote');

var sum = rpc.command('sum');

// Calling the tool.js sum function from app.js
sum.call('tools:*', {
    a:2, 
    b:3
})
.then((res)=>console.log('response : ',rpc.parseResponses(res)[0].response));

開示-私はタコの作者です。軽量のライブラリが見つからなかったため、同様のユースケースのために作成しました。


0

「ツール」をモジュールに変えるために、私はまったく難しいとは思いません。他のすべての回答にもかかわらず、私はまだmodule.exportsの使用をお勧めします:

//util.js
module.exports = {
   myFunction: function () {
   // your logic in here
   let message = "I am message from myFunction";
   return message; 
  }
}

次に、このエクスポートをグローバルスコープ(app | index | server.js内)に割り当てる必要があります

var util = require('./util');

これで、次のように関数を参照して呼び出すことができます。

//util.myFunction();
console.log(util.myFunction()); // prints in console :I am message from myFunction 

-3

使用する:

var mymodule = require("./tools.js")

app.js:

module.exports.<your function> = function () {
    <what should the function do>
}

1
ディレクトリ全体を使用することはほとんどありません。あなたは次のように相対パスを使用することを検討すべきである:./tools.js
マシュー・Dオールド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.