JavaScriptの名前空間

JavaやPHPなどのプログラミング言語の名前付けに非常に感銘を受けました。どういうわけかHabréにそれらについての記事を書いほどです。それからほぼ2年が経過しましたが、この間、名前名はJavaScriptに表示されていません。そして、もし私が自分のためにJSで名前付けをしたとしたら、それらは何でしょうか?」-私は思った。カットの下で-私の考え、JavaScriptで必要な名前名。

入門

以下の私の推論はすべてES6モジュールに適用され JavaScriptがどこにあるのかでなく、どこに行くのを監視することに関心があるという理由だけで、他の形式(AMD、UMD、CommonJS)には触れませんまた、私の練習では、どういうわけかGWTに非常に密接に遭遇し、その後、さまざまなトランスパイラー(およびヒープ、ミニファイア、オブファキュレータ)の永続的な拒否を開発しました。したがって、バニラJSでTSはありません。さて、そういうものがあります。

ES6モジュール

ESモジュールは、モジュールの外部で使用可能な要素を明示的に定義する別個のソースファイルです。

export function fn() {/*...*/}

したがって、最初に、アプリケーション全体内の個々のESモジュールに何らかの方法で対処する必要があります。

パッケージ

, . . (vendor) , . (, ./src).

node_modules. , nodejs-, , :

* node_modules
    * @vendor
        * package1
            * src
                * module1.js
                * ...
                * moduleN.js
        * ...
        * packageN
            * src
                * module1.mjs
                * ...
                * moduleN.mjs

ES- :

./node_modules/@vendor/package1/src/module1.js
...
./node_modules/@vendor/packageN/src/moduleN.mjs

nodejs-  ./node_modules/ :

import SomeThing from '@vendor/package1/src/module1.js';

, , :

import SomeThing from './module1.js';

web- , web-  node_modules, web- ES-, , nodejs:

<script type="module">
    import {fn} from './@vendor/package1/src/module1.js'
    fn();
</script>

:

<script>
    import('./@vendor/package1/src/module1.js').then((mod) => {
        mod.fn();
    });
</script>

, web'  ./  . :

import {fn} from '@vendor/package1/src/module1.js'

:

Uncaught TypeError: Failed to resolve module specifier "@vendor/package1/src/module1.js". Relative references must start with either "/", "./", or "../".

, ES-:

  • ( ): ./module1.js

  • (nodejs): @vendor/package1/src/module1.js

  • (web): ./@vendor/package1/src/module1.js

./ nodejs-, ./ .

, JS- , , ( - ) , ( ).

" " ( , namespace'), ES- ( ), ES- , , nodejs, .

,  ./, , ( , ):

@vendor/package1/src/module1

- : ./src/./lib/./dist/. - , , :

@vendor/package1/module1

, , .

Namespace mapping

, , . - web-,  node_modules  web- ( - ./packages/):

const node = {
    '@vendor/package1': {path: '/.../node_modules/@vendor/package1/src', ext: 'js'},
    '@vendor/packageN': {path: '/.../node_modules/@vendor/packageN/src', ext: 'mjs'},
};
const browser = {
    '@vendor/package1': {path: 'https://.../packages/@vendor/package1/src', ext: 'js'},
    '@vendor/packageN': {path: 'https://.../packages/@vendor/packageN/src', ext: 'mjs'},
};

Module loader

, '' ( @vendor/package1/module1) ( - ) (node ):

@vendor/package1/module1 => /.../node_modules/@vendor/package1/src/module1.js       // node
@vendor/packageN/moduleN => https://.../packages/@vendor/packageN/src/moduleN.mjs   // browser

モジュールを動的にインポートするために使用します。もちろん、パッケージ内のすべてのモジュールをマップする必要はありません。パッケージのルートをマップするだけです。出力は次のようになります。

const loader = new ModuleLoader();
loader.addNamespace('@vendor/package1', {path: '/.../node_modules/@vendor/package1/src', ext: 'js'});
// ...
loader.addNamespace('@vendor/packageN', {path: '/.../node_modules/@vendor/packageN/src', ext: 'js'});
const module1 = await loader.import('@vendor/package1/module1');

モジュールのインポートは非​​同期である必要があります。非同期関数が内部で使用されimport()ます。

概要

このような洗練された方法で、インポート中のESモジュールの物理アドレス指定から論理アドレス指定(名前空間)に移動し、nodejsアプリケーションとブラウザーの両方で同じモジュールを使用することができます。ここでは新しいものは何も発明されていません(このアイデアが盗まれたところから、PHPでも同様のことがすでに行われています)。




All Articles