Desde a sua criação, ninguém nunca considerou o JavaScript como uma linguagem de programação. Na era da Web 1.0, essa linguagem de script foi usada principalmente para verificação de formulários e efeitos especiais da página da web. Não foi até o ERA da Web 2.0 que os engenheiros de front-end o usaram para melhorar bastante a experiência do usuário na página da web que o JS era amplamente valorizado. À medida que o JS se torna cada vez mais popular, ele passa aproximadamente mudanças na biblioteca de ferramentas, biblioteca de componentes, estrutura front-end e aplicativos front-end. O JavaScript não tem um recurso: módulos e o surgimento da especificação Commonjs compensa essa falha. Este artigo introduzirá o mecanismo de especificação Commonjs e módulo do nó.
Em outros idiomas de alto nível, o Java possui arquivos de classe, o Python possui mecanismo de importação e o PHP inclui e exige. A maneira como o JS apresenta o código através da tag <Script> parece confuso. No passado, as pessoas tinham que usar namespaces e outros métodos para restringir artificialmente o código. Não foi até a especificação Commonjs surgir que o JavaScript de front-end e back-end foi capaz de alcançar uma grande unidade. O NODE toma a especificação dos módulos da CommonJS para implementar um sistema de módulos muito fácil de usar.
1. Especificação do módulo Commonjs
A especificação do módulo Commonjs é dividida em 3 partes:
1). Referência do módulo: Introduzir a API de um módulo no contexto atual através do método requer () e passar em um identificador de módulo, como var matemática = requer ('matemática');
2). Definição do Módulo: Exportar os métodos ou variáveis do módulo atual através do objeto Exportação. Há também um objeto de módulo no módulo, e as exportações são na verdade o atributo do módulo. No nó, um arquivo é um módulo e as "variáveis globais" no módulo são invisíveis para o mundo exterior. Somente os atributos montados nas exportações são públicos, como exports.add = function () {}; exports.pi = 3.1415926;
3). Module ID: Na verdade, é o parâmetro passado para exigir (). Por exemplo, a 'matemática' mencionada acima, deve ser uma string que esteja em conformidade com a nomenclatura de camelo, ou um caminho relativo ou absoluto começando com "". ".." ele não pode ter o sufixo de nome do arquivo ".js"
2. Processo de implementação do módulo de nó
No nó, os módulos são divididos em duas categorias: um é o módulo principal fornecido pelo próprio nó e o outro é o módulo de arquivo escrito pelo próprio usuário. Alguns dos módulos principais são compilados em arquivos binários durante a compilação do código -fonte do nó. Quando o nó é iniciado, o módulo do núcleo é carregado diretamente na memória, portanto sua velocidade de carregamento é a mais rápida. O módulo de arquivo é carregado dinamicamente no tempo de execução e requer três etapas: análise de caminho, localização do arquivo e compilação e execução. Observe que os caches do nó introduziram módulos para reduzir a sobrecarga durante a introdução secundária e adota a estratégia mais preferida para o carregamento secundário do mesmo módulo.
2.1 Análise de caminho
Análise de caminho analisa principalmente os identificadores do módulo mencionados acima, que são divididos principalmente nas seguintes categorias:
1) Módulos principais, como HTTP, FS, Path, etc.
2) Módulo de arquivo de caminho relativo que está começando. ou .
3) Módulo de arquivo de caminho absoluto começando com /
4) Módulo de arquivo personalizado, que pode estar na forma de um arquivo ou pacote. O nó tentará encontrar o arquivo de destino um por um de acordo com o módulo de matriz de caminho do módulo.
2.2 Localização do arquivo
Com base na análise do caminho, os seguintes detalhes precisam receber atenção a:
1) Análise de extensão de arquivo: Como a especificação Commonjs permite que os identificadores de módulo não sejam preenchidos, o nó tentará em ordem de .js, .json e .node
2) Análise e pacote de diretórios: se nenhum arquivo correspondente for encontrado após a análise de extensão de arquivo acima, mas um diretório for obtido, o nó tratará o diretório como um pacote.
2.3 Compilação e execução
Depois de localizar o arquivo específico, o Node criará um novo objeto de módulo, carregará e compilará de acordo com o caminho. Para extensões diferentes, o método de carregamento é diferente:
1) .js Arquivo: Leia o arquivo de forma síncrona através do módulo FS e compile e execute -o
2) Arquivo de Nó: Este é um arquivo de extensão escrito em C/C ++, carregado através do método dlopen ()
3) .json Arquivo: Leia o arquivo de maneira síncrona através do módulo FS e use json.parse () para analisar e retornar o resultado
4) Outros arquivos de extensão: eles são carregados como arquivos .js
Sabemos que cada arquivo do módulo possui três variáveis: exigir, exportações e módulo por padrão. Mesmo no documento da API do nó, sabemos que cada módulo também possui duas variáveis: nome do arquivo e Dirname. De onde eles vêm? Como o módulo do nó consegue que as "variáveis globais" declaradas não poluem outros módulos? De fato, o Node envolverá o conteúdo do arquivo no início e terminará durante a compilação do módulo JS. Aqui está um exemplo de um arquivo JS sendo embrulhado pela cabeça e cauda:
A cópia do código é a seguinte:
(função (exporta, requer, módulo, __filename, __dirname) {
/* O meio é o conteúdo real do arquivo JS*/
var matemática = requer ('matemática');
exports.area = função (raio) {
retornar math.pi * raio * raio;
};
/* O conteúdo real do arquivo JS termina*/
});
Dessa forma, cada arquivo de módulo é o isolamento escopo, e variáveis como requisitos, exportações, módulos etc. também são injetados no contexto do módulo. Esta é a implementação da especificação do módulo CommonJS do Node. O processo de compilação do módulo C/C ++ e do módulo núcleo do nó é relativamente complicado, por isso não o repetirei novamente.
3. Pilha de chamada do módulo
É necessário esclarecer as relações de chamada de vários módulos no nó, como mostrado na figura abaixo:
O módulo interno de C/C ++ é o módulo de nível mais baixo e pertence ao módulo principal. Ele fornece principalmente APIs para chamar os módulos de núcleo JavaScript e os módulos de arquivo JavaScript de terceiros. De fato, quase não há contato com esses módulos. Existem duas responsabilidades principais dos módulos do núcleo JavaScript: um é servir como a camada de encapsulamento e a camada de ponte do módulo interno de C/C ++ para chamadas de módulo de arquivo, e o outro é um módulo funcional puro que não precisa lidar com a camada subjacente. Os módulos de arquivo geralmente são gravados por terceiros, incluindo módulos JavaScript comuns e módulos de extensão C/C ++.
4. Pacote e NPM
4.1 Estrutura do pacote
O pacote é essencialmente um arquivo de arquivo (geralmente .zip ou .tar.gz), que é descomprimido e restaurado para um diretório após a instalação. A especificação do pacote Commonjs consiste em duas partes: estrutura do pacote e arquivo de descrição do pacote. Uma estrutura de pacotes que cumpre totalmente a especificação CommonJS deve conter os seguintes arquivos:
1) .package.json: pacote Descrição Arquivo
2) .bin: o diretório onde arquivos binários executáveis são armazenados
3) .lib: o diretório onde o código JavaScript é armazenado
4) .doc: o diretório onde o documento é armazenado
5) .Test: o diretório em que os casos de teste de unidade são armazenados
4.2 Arquivo de descrição do pacote
O arquivo de descrição do pacote é um arquivo json - package.json, localizado no diretório raiz do pacote, é uma parte importante do pacote e é usado para descrever as informações de visão geral do pacote. Todos os comportamentos dos NPMs que serão mencionados posteriormente estão intimamente relacionados aos campos deste arquivo. Abaixo, usaremos o arquivo package.json de um conhecido projeto da Web Framework Express como exemplo para ilustrar o significado de alguns campos comumente usados.
1) .Nome: Nome do pacote
2) .Description: Introdução do pacote
3) .Versão: o número da versão deve cumprir com "Controle de versão semântica", consulte http://semver.org/
4). Dependências: use a lista de pacotes dos quais o pacote atual precisa depender. Esta propriedade é muito importante. NPM carregará automaticamente o pacote dependente através desta propriedade
5). Repositórios: Lista de locais para hospedagem de código -fonte
O uso de outros campos pode ser encaminhado para a descrição do NPM Package.json
4.3 Funções comuns de NPM
NPM (Node Package Manager), conhecido como Node Package Manager. Sua principal função é gerenciar pacotes de nó, incluindo: instalação, desinstalação, atualização, visualização, pesquisa, publicação, etc.
4.3.1 Instalação do pacote NPM
Existem dois tipos de instalação de pacotes de nós: instalação local e instalação global. A diferença entre os dois é a seguinte:
1). Instalação local NPM Instalação <Nome-Name>: O pacote será baixado no diretório atual e só poderá ser usado no diretório atual.
2). INSTALAÇÃO GLOBAL NPM Install -g <Nome -Name>: O pacote será baixado em um diretório específico do sistema, e o pacote instalado pode ser usado em todos os diretórios.
4.3.2 Gerenciamento de pacotes npm
A seguir, é apresentada uma lista de comandos de gerenciamento de pacotes comumente usados usando Grunt-Cli (Grunt Command Line Tool) como exemplo:
1) .npm Instale: Instale todos os pacotes declarados pelos campos de dependências e dependências do arquivo package.json
2) .npm Instale [email protected]: Instale a versão específica do Grunt-cli
3) .npm Instale o cópia grunhido--SAVE: Instale o cópia grunhido e salve a dependência no arquivo package.json
4) .NPM Desinstala Grunt-Cli: Pacote de desinstalação
5) .npm Lista: Verifique quais pacotes estão instalados
6) .npm Publish <Palder>: Pacote de publicação