Bom dia amigosApresento a você a tradução do artigo “Noções básicas sobre (todos) os formatos e ferramentas do módulo JavaScript” de Dixin.Ao criar um aplicativo, geralmente existe o desejo de dividir o código em partes, blocos lógicos ou funcionais (módulos). No entanto, o JavaScript inicialmente não tinha suporte ao módulo. Isso levou ao surgimento de várias tecnologias modulares. Este artigo discute todos os conceitos básicos, modelos, bibliotecas, sintaxe e ferramentas para trabalhar com módulos em JavaScript.Módulo IIFE: modelo de módulo JS
Ao definir uma variável em JS, nós a definimos como uma variável global. Isso significa que essa variável estará disponível em todos os arquivos JS carregados na página atual:
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log(' .')
}
increase()
reset()
Para evitar a poluição do espaço para nome global, você pode usar uma função anônima: (() => {
let count = 0
})
Voila, não há mais variáveis globais. No entanto, o código dentro da função não é executado.IIFE: expressão imediata da função
Para executar o código dentro de uma função f
, ela deve ser chamada usando ()
como f()
. Para executar código dentro de uma função anônima (() => {})
também deve ser usado ()
. É assim (() => {})()
: (() => {
let count = 0
})()
Isso é chamado de IIFE (imediatamente chamado de expressão de função). Um módulo pode ser definido da seguinte maneira:
const iifeCounterModule = (() => {
let count = 0
return {
increase: () => ++count,
reset: () => {
count = 0
console.log(' .')
}
}
})()
iifeCounterModule.increase()
iifeCounterModule.reset()
Envolvemos o código do módulo em IIFE. Uma função anônima retorna um objeto. Isso substitui a interface de exportação. Existe apenas uma variável global - o nome do módulo (ou seu espaço para nome). Posteriormente, o nome do módulo pode ser usado para chamá-lo (exportação). Isso é chamado de modelo de módulo JS.Impurezas de importação
Ao definir um módulo, algumas dependências podem ser necessárias. Ao usar um modelo modular, cada módulo dependente é uma variável global. Módulos dependentes podem ser definidos dentro de uma função anônima ou passados para ela como argumentos:
const iifeCounterModule = ((dependencyModule1, dependencyModule2) => {
let count = 0
return {
increase: () => ++count,
reset: () => {
count = 0
console.log(' .')
}
}
})(dependencyModule1, dependencyModule2)
Versões anteriores de bibliotecas populares, como o jQuery, usavam esse modelo (a versão mais recente do jQuery usa o módulo UMD).Módulo aberto: modelo de módulo JS aberto
O modelo de módulo aberto foi criado por Christian Heilmann. Este modelo também é IIFE, mas a ênfase está na definição de todas as interfaces como variáveis locais dentro de uma função anônima:
const revealingCounterModule = (() => {
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log(' .')
}
return {
increase,
reset
}
})()
revealingCounterModule.increase()
revealingCounterModule.reset()
Essa sintaxe facilita a compreensão pelo que cada interface é responsável (ou pelo que faz).Módulo CJS: módulo CommonJS ou módulo Node.js
CommonJS, originalmente chamado ServerJS, é um modelo para definir e usar módulos. Está embutido no Node.js. Por padrão, cada arquivo JS é um CJS. Variáveis module
também exports
fornecem exportação do módulo (arquivo). A função require
fornece carregamento e uso do módulo. O código a seguir demonstra a definição de um módulo de contador na sintaxe CommonJS:
const dependencyModule1 = require('./dependencyModule1')
const dependencyModule2 = require('./dependencyModule2')
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log(' .')
}
exports.increase = increase
exports.reset = reset
module.exports = {
increase,
reset
}
Aqui está como este módulo é usado:
const {
increase,
reset
} = require('./commonJSCounterModule')
increase()
reset()
const commonJSCounterModule = require('./commonJSCounterModule')
commonJSCounterModule.increase()
commonJSCounterModule.reset()
No tempo de execução do Node.js. (mecanismo), esse modelo é usado envolvendo o código dentro do arquivo em uma função, para a qual variáveis exports, module
e uma função são passadas como parâmetros require
:
(function(exports, require, module, __filename, __dirname) {
const dependencyModule1 = require('./dependencyModule1')
const dependencyModule2 = require('./dependencyModule2')
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log(' .')
}
module.exports = {
increase,
reset
}
return module.exports
}).call(thisValue, exports, require, module, filename, dirname)
(function(exports, require, module, __filename, __dirname) {
const commonJSCounterModule = require('./commonJSCounterModule')
commonJSCounterModule.increase()
commonJSCounterModule.reset()
}).call(thisValue, exports, require, module, filename, dirname)
Módulo AMD ou módulo RequireJS
AMD ( definição de módulo assíncrono ) é um modelo para definir e usar módulos. É usado na biblioteca RequireJS . A AMD contém uma função de define
definição de módulo que aceita o nome do módulo, nomes de dependência e função de fábrica:
define('amdCounterModule', ['dependencyModule1', 'dependencyModule2'], (dependencyModule1, dependencyModule2) => {
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log(' .')
}
return {
increase,
reset
}
})
Ele também contém uma função require
para usar o módulo:
require(['amdCounterModule'], amdCounterModule => {
amdCounterModule.increase()
amdCounterModule.reset()
})
require
A AMD difere do require
CommonJS por considerar os nomes dos módulos e dos módulos como argumentos para a função.Carregamento dinâmico
A função define
também tem uma finalidade diferente. Ele pega uma função de retorno de chamada e passa uma require
função do tipo CommonJS para essa função. Dentro da função de retorno de chamada, require é chamado para carregar dinamicamente o módulo:
define(require => {
const dynamicDependencyModule1 = require('dependencyModule1')
const dynamicDependencyModule2 = require('dependencyModule2')
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log(' .')
}
return {
increase,
reset
}
})
Módulo AMD do módulo CommonJS
A função acima define
, além disso require
, pode levar as variáveis exports
e como argumentos module
. Portanto, o define
código do CommonJS pode ser executado dentro de :
define((require, exports, module) => {
const dependencyModule1 = require('dependencyModule1')
const dependencyModule2 = require('dependencyModule2')
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log(' .')
}
exports.increase = increase
exports.reset = reset
})
define(require => {
const counterModule = require('amdCounterModule')
counterModule.increase()
counterModule.reset()
})
Módulo UMD: definição de módulo universal ou módulo UmdJS
UMD ( definição universal de módulo ) - um conjunto de modelos para garantir a operação do módulo em diferentes ambientes de tempo de execução.UMD para AMD (RequireJS) e navegador
O código a seguir fornece o módulo na AMD (RequireJS) e no navegador:
((root, factory) => {
if (typeof define === 'function' && define.amd) {
define('umdCounterModule', ['dependencyModule1', 'dependencyModule2'], factory)
} else {
root.umdCounterModule = factory(root.dependencyModule1, root.dependencyModule2)
}
})(typeof self !== undefined ? self : this, (dependencyModule1, dependencyModule2) => {
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log(' ')
}
return {
increase,
reset
}
})
Parece complicado, mas é apenas IIFE. Uma função anônima determina se há uma função define
do AMD / RequireJS.- Se
define
detectada, a função de fábrica é chamada através dela. - Se
define
não encontrado, a função de fábrica é chamada diretamente. Neste ponto, o argumento root
é o objeto Window do navegador. Ele recebe módulos dependentes de variáveis globais (propriedades do objeto Window). Quando um factory
módulo retorna, ele também se torna uma variável global (uma propriedade do objeto Window).
UMD para AMD (RequireJS) e CommonJS (Node.js)
O código a seguir fornece o módulo no AMD (RequireJS) e no CommonJS (Node.js): (define => define((require, exports, module) => {
const dependencyModule1 = require("dependencyModule1")
const dependencyModule2 = require("dependencyModule2")
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log("Count is reset.")
}
module.export = {
increase,
reset
}
}))(
typeof module === 'object' && module.exports && typeof define !== 'function'
?
factory => module.exports = factory(require, exports, module)
:
define)
Não se assuste, é apenas IIFE novamente. Quando uma função anônima é chamada, seu argumento é “avaliado”. Avaliando o argumento para determinar o ambiente de execução (definido pela presença de variáveis module
e exports
do CommonJS / Node.js e as funções define
do AMD / RequireJS).- Se o tempo de execução for CommonJS / Node.js, o argumento da função anônima criará a função manualmente
define
. - Se o tempo de execução for AMD / RequireJS, o argumento para a função anônima é uma função
define
desse ambiente. A execução de uma função anônima garante que a função funcione define
. Dentro de uma função anônima, uma função é chamada para criar o módulo define
.
Módulo ES: módulo ECMAScript2015 ou ES6
Em 2015, a versão 6 da especificação JS introduziu uma nova sintaxe modular. Isso é chamado de ECMAScript 2015 (ES2015) ou ECMAScript 6 (ES6). A base da nova sintaxe são as palavras import
- chave e export
. O código a seguir demonstra o uso do módulo ES para importação / exportação nomeada e padrão (padrão):
import dependencyModule1 from './dependencyModule1.mjs'
import dependencyModule2 from './dependencyModule2.mjs'
let count = 0
export const increase = () => ++count
export const reset = () => {
count = 0
console.log(' .')
}
export default {
increase,
reset
}
Para usar o arquivo de módulo no navegador, adicione a tag <script>
e identificá-lo como um módulo: <script type="module" src="esCounterModule.js"></script>
. Para usar este módulo no Node.js, altere sua extensão para .mjs
:
import {
increase,
reset
} from './esCounterModule.mjs'
increase()
reset()
import esCounterModule from './esCounterModule.mjs'
esCounterModule.increase()
esCounterModule.reset()
Para compatibilidade com versões anteriores no navegador, você pode adicionar uma tag <script>
com o atributo nomodule
: <nomodule de script>
alerta ('Não suportado')
</script>
Módulo dinâmico ES: módulo dinâmico ECMAScript2020 ou ES11
A última versão 11 da especificação JS 2020 apresenta uma função interna import
para o uso dinâmico de módulos ES. Essa função retorna uma promessa, para que você possa usar o módulo com then
:
import('./esCounterModule.js').then(({
increase,
reset
}) => {
increase()
reset()
})
import('./esCounterModule.js').then(dynamicESCounterModule => {
dynamicESCounterModule.increase()
dynamicESCounterModule.reset()
})
Devido ao fato de a função import
retornar uma promessa, ela pode usar a palavra await
- chave :
(async () => {
const {
increase,
reset
} = await import('./esCounterModule.js')
increase()
reset()
const dynamicESCounterModule = await import('./esCounterModule.js')
dynamicESCounterModule.increase()
dynamicESCounterModule.reset()
})
Módulo do Sistema: Módulo SystemJS
O SystemJS é uma biblioteca para suportar módulos ES em navegadores mais antigos. Por exemplo, o seguinte módulo é gravado usando a sintaxe ES6:
import dependencyModule1 from "./dependencyModule1.js"
import dependencyModule2 from "./dependencyModule2.js"
dependencyModule1.api1()
dependencyModule2.api2()
let count = 0
export const increase = function() {
return ++count
}
export const reset = function() {
count = 0
console.log("Count is reset.")
}
export default {
increase,
reset
}
Este código não funcionará em navegadores que não suportam a sintaxe ES6. Uma solução para esse problema é converter o código usando a System.register
interface da biblioteca SystemJS:
System.register(['./dependencyModule1', './dependencyModule2'], function(exports_1, context_1) {
'use strict'
var dependencyModule1_js_1, dependencyModule2_js_1, count, increase, reset
var __moduleName = context_1 && context_1.id
return {
setters: [
function(dependencyModule1_js_1_1) {
dependencyModule1_js_1 = dependencyModule1_js_1_1
},
function(dependencyModule2_js_1_1) {
dependencyModule2_js_1 = dependencyModule2_js_1_1
}
],
execute: function() {
dependencyModule1_js_1.default.api1()
dependencyModule2_js_1.default.api2()
count = 0
exports_1('increase', increase = function() {
return ++count
})
exports_1('reset', reset = function() {
count = 0
console.log(' .')
})
exports_1('default', {
increase,
reset
})
}
}
})
A nova sintaxe modular do ES6 desapareceu. Mas o código funcionará bem em navegadores mais antigos. Essa transpilação pode ser feita automaticamente usando Webpack, TypeScript, etc.Carregamento dinâmico do módulo
O SystemJS também contém uma função import
para importação dinâmica:
System.import('./esCounterModule.js').then(dynamicESCounterModule => {
dynamicESCounterModule.increase()
dynamicESCounterModule.reset()
})
Módulo Webpack: compilação e montagem de módulos CJS, AMD e ES
Webpack é um construtor de módulos. Seu transpiler combina os módulos CommonJS, AMD e ES em um único modelo modular balanceado e coleta todo o código em um único arquivo. Por exemplo, nos 3 arquivos a seguir, 3 módulos são definidos usando uma sintaxe diferente:
define('amdDependencyModule1', () => {
const api1 = () => {}
return {
api1
}
})
const dependencyModule2 = require('./commonJSDependencyModule2')
const api2 = () => dependencyModule1.api1()
exports.api2 = api2
import dependencyModule1 from './amdDependencyModule1'
import dependencyModule2 from './commonJSDependencyModule2'
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log(' .')
}
export default {
increase,
reset
}
O código a seguir demonstra o uso deste módulo:
import counterModule from './esCounterModule'
counterModule.increase()
counterModule.reset()
O Webpack é capaz de combinar esses arquivos, apesar de serem sistemas modulares diferentes, em um arquivo main.js
: raiz
dist
main.js (montagem de arquivos localizados na pasta src)
src
amdDependencyModule1.js
commonJSDependencyModule2.js
esCounterModule.js
index.js
webpack.config.js
Como o Webpack é baseado no Node.js, ele usa a sintaxe modular do CommonJS. Em webpack.config.js
: const path = require('path')
module.exports = {
entry: './src/index.js',
mode: 'none',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
},
}
Para compilar e construir, você deve executar os seguintes comandos: npm install webpack webpack-cli --save-dev
npx webpack --config webpack.config.js
Como resultado, o Webpack criará o arquivo main.js
. O código a seguir está main.js
formatado para melhorar a legibilidade: (function(modules) {
var installedModules = {}
function require(moduleId) {
if (installedModules[moduleId]) {
return installedModules[moduleId].exports
}
var module = installedModules[moduleId] = {
i: moduleId,
l: false,
exports: {}
}
modules[moduleId].call(module.exports, module, module.exports, require)
module.l = true
return module.exports
}
require.m = modules
require.c = installedModules
require.d = function(exports, name, getter) {
if (!require.o(exports, name)) {
Object.defineProperty(exports, name, {
enumerable: true,
get: getter
})
}
}
require.r = function(exports) {
if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
Object.defineProperty(exports, Symbol.toStringTag, {
value: 'Module'
})
}
Object.defineProperty(exports, '__esModule', {
value: true
})
}
require.t = function(value, mode) {
if (mode & 1) value = require(value)
if (mode & 8) return value
if ((mode & 4) && typeof value === 'object' && value && value.__esModule) return value
var ns = Object.create(null)
require.r(ns)
Object.defineProperty(ns, 'default', {
enumerable: true,
value: value
})
if (mode & 2 && typeof value !== 'string')
for (var key in value) require.d(ns, key, function(key) {
return value[key]
}.bind(null, key))
return ns
}
require.n = function(module) {
var getter = module && module.__esModule ?
function getDefault() {
return module['default']
} :
function getModuleExports() {
return module
}
require.d(getter, 'a', getter)
return getter
}
require.o = function(object, property) {
return Object.prototype.hasOwnProperty.call(object, property)
}
require.p = ''
return require(require.s = 0)
})([
function(module, exports, require) {
'use strict'
require.r(exports)
var esCounterModule = require(1)
esCounterModule['default'].increase()
esCounterModule['default'].reset()
},
function(module, exports, require) {
'use strict'
require.r(exports)
var amdDependencyModule1 = require.n(require(2))
var commonJSDependencyModule2 = require.n(require(3))
amdDependencyModule1.a.api1()
commonJSDependencyModule2.a.api2()
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log(' .')
}
exports['default'] = {
increase,
reset
}
},
function(module, exports, require) {
var result!(result = (() => {
const api1 = () => {}
return {
api1
}
}).call(exports, require, exports, module),
result !== undefined && (module.exports = result))
},
function(module, exports, require) {
const dependencyModule1 = require(2)
const api2 = () => dependencyModule1.api1()
exports.api2 = api2
}
])
E, novamente, isso é apenas IIFE. O código de 4 arquivos é convertido em uma matriz de 4 funções. E essa matriz é passada para a função anônima como parâmetro.Módulo Babel: transpilação do módulo ES
Babel é outro transportador para oferecer suporte ao código ES6 + em navegadores mais antigos. O módulo ES6 + acima pode ser convertido em um módulo Babel da seguinte maneira:
Object.defineProperty(exports, '__esModule', {
value: true
})
exports['default'] = void 0
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
'default': obj
}
}
var dependencyModule1 = _interopRequireDefault(require('./amdDependencyModule1'))
var dependencyModule2 = _interopRequireDefault(require('./commonJSDependencyModule2'))
dependencyModule1['default'].api1()
dependencyModule2['default'].api2()
var count = 0
var increase = function() {
return ++count
}
var reset = function() {
count = 0
console.log(' .')
}
exports['default'] = {
increase: increase,
reset: reset
}
E aqui está o código index.js
, demonstrando o uso deste módulo:
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
'default': obj
}
}
var esCounterModule = _interopRequireDefault(require('./esCounterModule.js'))
esCounterModule['default'].increase()
esCounterModule['default'].reset()
Esta é a transpilação padrão. Babel também sabe como trabalhar com outras ferramentas.Babel e SystemJS
O SystemJS pode ser usado como um plugin para Babel: Instalação do npm --save-dev @ babel / plugin-transform-modules-systemjs
Este plugin deve ser adicionado a babel.config.json
: {
'plugins': ['@ babel / plugin-transform-modules-systemjs'],
'presets': [
[
'@ babel / env',
{
'segmentações': {
'ie': '11'
}
}
]
]
}
Agora o Babel pode trabalhar com o SystemJS para transpilar os módulos CommonJS / Node.js, AMD / RequireJS e ES: npx babel src --out-dir lib
Resultado: raiz
lib
amdDependencyModule1.js (transpilado usando SystemJS)
commonJSDependencyModule2.js (transpilado usando SystemJS)
esCounterModule.js (transpilado usando SystemJS)
index.js (transpilado usando SystemJS)
src
amdDependencyModule1.js
commonJSDependencyModule2.js
esCounterModule.js
index.js
babel.config.json
Toda a sintaxe dos módulos AMD, CommonJS e ES é transposta para a sintaxe SystemJS:
System.register([], function(_export, _context) {
'use strict'
return {
setters: [],
execute: function() {
define('amdDependencyModule1', () => {
const api1 = () => {}
return {
api1
}
})
}
}
})
System.register([], function(_export, _context) {
'use strict'
var dependencyModule1, api2
return {
setters: [],
execute: function() {
dependencyModule1 = require('./amdDependencyModule1')
api2 = () => dependencyModule1.api1()
exports.api2 = api2
}
}
})
System.register(['./amdDependencyModule1', './commonJSDependencyModule2'], function(_export, _context) {
var dependencyModule1, dependencyModule2, count, increase, reset
return {
setters: [function(_amdDependencyModule) {
dependencyModule1 = _amdDependencyModule.default
}, function(_commonJSDependencyModule) {
dependencyModule2 = _commonJSDependencyModule.default
}],
execute: function() {
dependencyModule1.api1()
dependencyModule1.api2()
count = 0
increase = () => ++count
reset = () => {
count = 0
console.log(' .')
}
_export('default', {
increase,
reset
})
}
}
})
System.register(['./esCounterModule'], function(_export, _context) {
var esCounterModule
return {
setters: [function(_esCounterModule) {
esCounterModule = _esCounterModule.default
}],
execute: function() {
esCounterModule.increase()
esCounterModule.reset()
}
}
})
Módulo TypeScript: transpilação dos módulos CJS, AMD, ES e SystemJS
O TypeScript suporta todos os tipos de sintaxe JS, incluindo o ES6. Durante a transpilação, a sintaxe do módulo ES6 pode ser salva ou convertida para outro formato, incluindo CommonJS / Node.js, AMD / RequireJS, UMD / UmdJS ou SystemJS de acordo com as configurações da transpilação em tsconfig.json
: {
'compilerOptions': {
'module': 'ES2020' // Nenhum, CommonJS, AMD, Sistema,
UMD, ES6, ES2015, ESNext
}
}
Por exemplo:
import dependencyModule from './dependencyModule'
dependencyModule.api()
let count = 0
export const increase = function() {
return ++count
}
var __importDefault = (this && this.__importDefault) || function(mod) {
return (mod && mod.__esModule) ? mod : {
'default': mod
}
}
exports.__esModule = true
var dependencyModule_1 = __importDefault(require('./dependencyModule'))
dependencyModule_1['default'].api()
var count = 0
exports.increase = function() {
return ++count
}
var __importDefault = (this && this.__importDefault) || function(mod) {
return (mod && mod.__esModule) ? mod : {
'default': mod
}
}
define(['require', 'exports', './dependencyModule'], function(require, exports, dependencyModule_1) {
'use strict'
exports.__esModule = true
dependencyModule_1 = __importDefault(dependencyModule_1)
dependencyModule_1['default'].api()
var count = 0
exports.increase = function() {
return ++count
}
})
var __importDefault = (this & this.__importDefault) || function(mod) {
return (mod && mod.__esModule) ? mod : {
'default': mod
}
}
(function(factory) {
if (typeof module === 'object' && typeof module.exports === 'object') {
var v = factory(require, exports)
if (v !== undefined) module.exports = v
} else if (typeof define === 'function' && define.amd) {
define(['require', 'exports', './dependencyModule'], factory)
}
})(function(require, exports) {
'use strict'
exports.__esModule = true
var dependencyModule_1 = __importDefault(require('./dependencyModule'))
dependencyModule_1['default'].api()
var count = 0
exports.increase = function() {
return ++count
}
})
System.register(['./dependencyModule'], function(exports_1, context_1) {
'use strict'
var dependencyModule_1, count, increase
car __moduleName = context_1 && context_1.id
return {
setters: [
function(dependencyModule_1_1) {
dependencyModule_1 = dependencyModule_1_1
}
],
execute: function() {
dependencyModule_1['default'].api()
count = 0
exports_1('increase', increase = function() {
return ++count
})
}
}
})
A sintaxe modular do ES suportada pelo TypeScript é chamada de módulos externos.Módulos internos e espaço para nome
TypeScript também possui palavras-chave module
e namespace
. Eles são chamados de módulos internos: module Counter {
let count = 0
export const increase = () => ++count
export const reset = () => {
count = 0
console.log(' .')
}
}
namespace Counter {
let count = 0
export const increase = () => ++count
export const reset = () => {
count = 0
console.log(' .')
}
}
Ambos são transpostos para objetos JS: var Counter;
(function(Counter) {
var count = 0
Counter.increase = function() {
return ++count
}
Counter.reset = function() => {
count = 0
console.log(' .')
}
})(Counter || (Counter = {}))
O módulo TypeScript e o namespace podem ter vários níveis de aninhamento por meio do separador .
: module Counter.Sub {
let count = 0
export const increase = () => ++count
}
namespace Counter.Sub {
let count = 0
export const increase = () => ++count
}
O submódulo e o sub namespace são transpostos para as propriedades do objeto: var Counter;
(function(Counter) {
var Sub;
(function(Sub) {
var count = 0
Sub.increase = function() {
return ++count
}
})(Sub = Counter.Sub || (Counter.Sub = {}))
})(Counter || (Counter = {}))
O módulo TypeScript e o espaço para nome também podem ser usados em uma instrução export
: module Counter {
let count = 0
export module Sub {
export const increase = () => ++count
}
}
module Counter {
let count = 0
export namespace Sub {
export const increase = () => ++count
}
}
O código acima também se traduz em submódulo e sub namespace: var Counter;
(function(Counter) {
var count = 0
var Sub;
(function(Sub) {
Sub.increase = function() {
return ++count
}
})(Sub = Counter.Sub || (Counter.Sub = {}))
})(Counter || (Counter = {}))
Conclusão
Bem-vindo ao JS, que possui mais de 10 sistemas / formatos de modulação / espaços para nome:- Módulo IIFE: modelo de módulo JS
- Módulo aberto: modelo de módulo JS aberto
- Módulo CJS: módulo CommonJS ou módulo Node.js
- Módulo AMD: definição de módulo assíncrono ou módulo RequireJS
- Módulo UMD: definição de módulo universal ou módulo UmdJS
- Módulo ES: módulo ECMAScript2015 ou ES6
- Módulo dinâmico ES: módulo dinâmico ECMAScript2020 ou ES11
- Módulo do Sistema: Módulo SystemJS
- Módulo Webpack: compilação e montagem de módulos CJS, AMD e ES
- Módulo Babel: transpilação do módulo ES
- Módulo TypeScript e espaço para nome
Felizmente, o JS atualmente possui ferramentas internas padrão para trabalhar com módulos suportados pelo Node.js. e todos os navegadores modernos. Para navegadores mais antigos, você pode usar a nova sintaxe modular do ES, convertendo-a em sintaxe compatível usando Webpack / Babel / SystemJS / TypeScript.Obrigado pelo seu tempo. Espero que tenha sido bem gasto.