Trabalhando com módulos em Node.js
Vamos examinar alguns aspectos do trabalho com módulos no Node.js. Antes de tudo, é importante notar que os módulos carregados são armazenados em cache. Em particular, no arquivo loader.js
, há as seguintes linhas:
const filename = Module._resolveFilename(request, parent, isMain);
const cachedModule = Module._cache[filename];
if (cachedModule !== undefined) {
updateChildren(parent, cachedModule, true);
if (!cachedModule.loaded) {
const parseCachedModule = cjsParseCache.get(cachedModule);
if (!parseCachedModule || parseCachedModule.loaded) {
return getExportsForCircularRequire(cachedModule);
}
parseCachedModule.loaded = true;
} else {
return cachedModule.exports;
}
}
Por um lado, isso aumenta o desempenho, mas por outro, pode criar alguns problemas se não levarmos esse aspecto em consideração. Por exemplo, vamos definir o arquivo greeting.js
da seguinte forma:
module.exports.name = "Alice";
No arquivo, há apenas uma linha que define a propriedade name
.
Em seguida, vamos definir o arquivo principal da aplicação app.js
:
const greeting1 = require("./greeting.js");
console.log(`Hello ${greeting1.name}`); // Hello Alice
const greeting2 = require("./greeting.js");
greeting2.name = "Bob";
console.log(`Hello ${greeting2.name}`); // Hello Bob
// greeting1.name também mudou
console.log(`Hello ${greeting1.name}`); // Hello Bob
Apesar de usarmos a função require
duas vezes para obter o módulo, ambas as variáveis greeting1
e greeting2
apontam para o mesmo objeto.
Executamos o comando:
c:\app> node app.js Hello Alice Hello Bob Hello Bob
Isso ocorre porque o módulo greeting.js
é carregado apenas uma vez e, em seguida, armazenado em cache. Portanto, ao alterar a propriedade name
de greeting2
, a propriedade name
de greeting1
também é alterada.
Estrutura de Módulos
Frequentemente, os módulos de uma aplicação formam conjuntos ou áreas específicas. Esses conjuntos de módulos devem ser colocados em diretórios separados. Por exemplo, suponha que temos a seguinte estrutura de projeto:
Pasta
messages
, contendo os seguintes arquivos:index.js
morning.js
evening.js
- Arquivo principal da aplicação
app.js
No arquivo morning.js
, colocamos a seguinte linha:
module.exports = "Good morning!";
De forma semelhante, no arquivo evening.js
:
module.exports = "Good evening!";
Esses dois arquivos definem mensagens de saudação conforme o período do dia.
No arquivo index.js
, definimos o seguinte código:
const morning = require("./morning");
const evening = require("./evening");
module.exports = {
getMorningMessage: function () {
console.log(morning);
},
getEveningMessage: function () {
console.log(evening);
},
};
Este módulo define um objeto que possui duas funções para exibir as saudações.
Agora, usamos esse módulo no arquivo app.js
:
const messages = require("./messages");
messages.getMorningMessage();
messages.getEveningMessage();
Apesar de não haver um arquivo chamado messages.js
, se houver um diretório messages
contendo um arquivo chamado index.js
, podemos referenciar o módulo pelo nome do diretório, como neste caso.
Executando a aplicação, as saudações serão exibidas no console:
c:\app> node app.js Good morning! Good evening!