MENU

サーバーサイド

【Node.js】 importしたスクリプト内で同じスクリプトをimportするとどうなる?

更新日:2020/05/05

 

 

こちらの記事でNode.jsで同じスクリプトを複数回requireしたときの挙動について調べたので、今回はimportしたときの挙動を調べてみました。

 

■お願い
去年ECMAScript2020を頑張って日本語訳しましたが、誰も見てくれません・・・
誰かみて!!
【JavaScript】 学習のためECMAScript2020を日本語訳してみました

同じスクリプトを2回importする

 

まずは一つのスクリプト内で、同じスクリプトを2回importするとどうなるのか確認してみます。

 

ちなみにNode.jsでimport/exportを使用する場合、呼び出す側・呼び出される側とも、拡張子が『.msj』でないといけないようです。

 

■呼び出されるスクリプト

 

require-test.mjs

 


console.log( "test:load");
export  const test = (()=>{
    let m = "No Message";
    return {
        set message(t){
            m = t;
        },
        get message(){
            return m;
        }
    };
})();

 

■呼び出すスクリプト

 

require-main.mjs

 


console.log( "1回目" );
import {test as test1} from "./require-test.mjs";
test1.message = "hello";

console.log( "2回目" );
import {test as test2} from "./require-test.mjs";
console.log( test2.message );

console.log( "同一?:" + Object.is(test1 ,test2) );

 

■実行結果

 

Node.jsでimport/exportを使用する場合、『--experimental-modules』オプションが必要らしいです。

 

> node --experimental-modules require-main.mjs
(node:19320) ExperimentalWarning: The ESM module loader is experimental.
test:load
1回目
2回目
hello
同一?:true

 

Warningが出ているが…
訳:『ESMモジュールローダーは実験的です』
とりあえず気にしなくてよさそうです。

 

■結論

 

  1. 同じスクリプトがロードされるのは、一度だけ。
  2. importは同じオブジェクトを返す

同じスクリプトを、importしたスクリプト内でも呼び出す

 

次は同じスクリプトを、importしたスクリプト内でも呼び出してみます。

 

具体的には、次のようなことを実行します。

 

  1. require-main.mjsでrequire-test.mjsを呼び出す。
  2. require-test.mjsを呼び出すrequire-sub.mjsを、require-main.mjsで呼び出す。

 

■呼び出されるスクリプト

 

require-test.mjs

 


console.log( "test:load");
export  const test = (()=>{
    let m = "No Message";
    return {
        set message(t){
            m = t;
        },
        get message(){
            return m;
        }
    };
})();

 

■呼び出すスクリプト main

 

require-main.mjs

 


console.log( "test呼び出し" );
import {test as test1} from "./require-test.mjs";
test1.message = "hello";

console.log( "sub呼び出し" );
import {sub as sub1} from "./require-sub.mjs";
console.log( sub1.message );

console.log( "同一?:" + sub1.isObj( test1 ) );

 

■呼び出すスクリプト sub

 

require-sub.js

 


import {test as test1} from "./require-test.mjs";

export  const sub ={
    get message(){
        return test1.message;
    },
    isObj( obj ){
        return Object.is( obj , test1 );
    }
};

 

 

■実行結果

 

> node --experimental-modules require-main.mjs
(node:9124) ExperimentalWarning: The ESM module loader is experimental.
test:load
test呼び出し
sub呼び出し
hello
同一?:true

 

■結論

 

  1. 呼び出す階層に関係なく同じスクリプトがロードされるのは、一度だけ。
  2. importは同じオブジェクトを返す

まとめ

 

importもrequireと同様、親子関係に関係なく同じオブジェクトを参照します。

 

他から入手したライブラリなどで、同じスクリプトを使用していると不具合が出そうです。

 

注意が必要ですね。

記事の内容について

 

こんにちはけーちゃんです。
説明するのって難しいですね。


「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。

そんなときは、ご意見もらえたら嬉しいです。

ご意見はこちら。
https://note.affi-sapo-sv.com/info.php

【お願い】

お願い

■このページのURL


■このページのタイトル


■リンクタグ