Espacios de nombres en JavaScript

Estoy muy impresionado con los espacios de nombres en lenguajes de programaci贸n como Java y PHP. Tanto es as铆 que incluso de alguna manera escrib铆 un art铆culo sobre ellos en Habr茅. Han pasado casi dos a帽os desde entonces, pero los espacios de nombres no han aparecido en JavaScript durante este tiempo. " Y si hiciera espacios de nombres en JS para m铆, 驴cu谩les ser铆an? " - pens茅. Debajo del corte: mis pensamientos, qu茅 espacios de nombres necesito en JavaScript.

Introductorio

Todo mi razonamiento a continuaci贸n se aplica a los m贸dulos ES6 y no toca otros formatos (AMD, UMD, CommonJS) simplemente porque estoy interesado en ver hacia d贸nde va JavaScript, no hacia d贸nde estaba . Adem谩s, en mi pr谩ctica, de alguna manera me encontr茅 con GWT bastante de cerca, despu茅s de lo cual desarroll茅 un rechazo persistente de varios transpiladores (as铆 como, a un mont贸n, minificadores y ofuscadores). Por lo tanto vainilla JS y no TS. Bueno, tengo esos art铆culos.

M贸dulos ES6

Un m贸dulo ES es un archivo fuente independiente que define expl铆citamente los elementos disponibles fuera del m贸dulo:

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

Por lo tanto, para empezar, debe abordar de alguna manera m贸dulos ES individuales dentro de toda la aplicaci贸n.

Paquetes

, . . (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

y util铆celo para importar m贸dulos din谩micamente. Por supuesto, no es necesario mapear todos los m贸dulos del paquete, solo necesita mapear la ra铆z del paquete. La salida es algo como esto:

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');

La importaci贸n de m贸dulos debe ser asincr贸nica, ya que se utilizar谩 una funci贸n asincr贸nica en el interior import().

Resumen

De una manera tan elegante, ser铆a posible cambiar del direccionamiento f铆sico de los m贸dulos ES durante la importaci贸n a su direccionamiento l贸gico (espacios de nombres) y usar los mismos m贸dulos tanto para las aplicaciones nodejs como en el navegador. Aqu铆 no se ha inventado nada nuevo ( ya se ha hecho algo similar en PHP, de donde se roba esta idea).




All Articles