[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Modules [Back]  [Original]

Mdulos JavaScript - JavaScript | MDN

Esta pgina foi traduzida do ingls pela comunidade. Saiba mais e junte-se comunidade MDN Web Docs.

View in English Always switch to English

Mdulos JavaScript

Este guia fornece tudo o que voc precisa para comear com a sintaxe de mdulo do JavaScript.

In this article

Um background em mdulos

Os programas JavaScript comearam muito pequenos - a maior parte do seu uso nos primeiros dias era para executar tarefas isoladas de script, fornecendo um pouco de interatividade s suas pginas da Web sempre que necessrio, de modo que scripts grandes geralmente no eram necessrios. Com o avano rpido da tecnologia agora temos aplicativos completos sendo executados em navegadores com muito JavaScript, alm de JavaScript ser usado em outros contextos (Node.js, por exemplo).

Portanto, fez sentido nos ltimos anos comear a pensar em fornecer mecanismos para dividir programas JavaScript em mdulos separados que podem ser importados quando necessrio. O Node.js possui essa capacidade h muito tempo e existem vrias bibliotecas e estruturas JavaScript que permitem o uso do mdulo (por exemplo, outros CommonJS e AMD-sistemas de mdulos baseados em RequireJS, e mais recentemente Webpack e Babel).

A boa notcia que os navegadores modernos comearam a dar suporte nativamente funcionalidade do mdulo, e sobre isso que este artigo trata. Isso s pode ser uma coisa boa - os navegadores podem otimizar o carregamento de mdulos, tornando-o mais eficiente do que ter que usar uma biblioteca e fazer todo esse processamento extra no lado do cliente e viagens de ida e volta extras.

Suporte do navegador

O uso de mdulos JavaScript nativos depende doimport e export afirmaes; estes so suportados nos navegadores da seguinte maneira:

importa

exporta

Apresentando um exemplo

Para demonstrar o uso dos mdulos, criamos um conjunto simples de exemplos que voc pode encontrar no GitHub. Estes exemplos demonstram um conjunto simples de mdulos que criam um<canvas> em uma pgina da Web e desenhe (e relate informaes sobre) formas diferentes na tela.

Estes so bastante triviais, mas foram mantidos deliberadamente simples para demonstrar claramente os mdulos.

Nota: Nota: Se voc deseja fazer o download dos exemplos e execut-los localmente, precisar execut-los por meio de um servidor da web local.

Exemplo de uma estrutura bsica

No nosso primeiro exemplo (consulte basic-modules) ns temos uma estrutura de arquivos da seguinte maneira:

index.html
main.js
modules/
    canvas.js
    square.js

Nota: Nota: Todos os exemplos neste guia tm basicamente a mesma estrutura; o exposto acima deve comear a ficar bem familiar.

Os dois mdulos do diretrio modules so descritos abaixo:

  • canvas.js contm funes relacionadas configurao da tela:

    • create() cria uma tela com uma largura e altura especificadas dentro de um invlucro <div> com um ID especificado, que anexado dentro de um elemento pai especificado. Retorna um objeto que contm o contexto 2D da tela e o ID do wrapper.
    • createReportList() cria uma lista no ordenada anexada dentro de um elemento de wrapper especificado, que pode ser usado para gerar dados de relatrio. Retorna o ID da lista.
  • square.js contm:

    • name uma constante contendo a string 'square'.
    • draw() desenha um quadrado em uma tela especificada, com um tamanho, posio e cor especificados. Retorna um objeto que contm o tamanho, a posio e a cor do quadrado.
    • reportArea() grava a rea de um quadrado em uma lista de relatrios especfica, considerando seu tamanho.
    • reportPerimeter() grava o permetro de um quadrado em uma lista de relatrios especfica, considerando seu comprimento.

Aside .mjs versus .js

Neste artigo, usamos extenses .js para nossos arquivos de mdulo, mas em outros recursos voc pode ver a extenso .mjs usada. A documentao da V8 recomenda isso, por exemplo. Os motivos apresentados so:

  • bom para maior clareza, ou seja, deixa claro quais arquivos so mdulos e quais so JavaScript regulares.
  • Ele garante que seus arquivos de mdulo sejam analisados como um mdulo por tempos de execuo, como Node.js, e construir ferramentas como Babel.

No entanto, decidimos continuar usando .js, pelo menos por enquanto. Para que os mdulos funcionem corretamente em um navegador, voc precisa garantir que seu servidor os esteja servindo com um cabealho Content-Type que contenha um tipo MIME JavaScript, como text / javascript. Caso contrrio, voc receber um erro estrito de verificao do tipo MIME, de acordo com as linhas "O servidor respondeu com um tipo MIME no JavaScript" e o navegador no executar seu JavaScript. A maioria dos servidores j define o tipo correto para arquivos .js, mas ainda no para arquivos .mjs. Servidores que j veiculam arquivos .mjs incluem corretamente GitHub Pages e http-server para Node.js.

Tudo bem se voc j estiver usando esse ambiente ou se no estiver, mas souber o que est fazendo e tiver acesso (ou seja, voc pode configurar o servidor para definir a configurao correta Content-Type para arquivos .mjs). No entanto, isso pode causar confuso se voc no controlar o servidor do qual est servindo arquivos ou publicar arquivos para uso pblico, como estamos aqui.

Para fins de aprendizado e portabilidade, decidimos manter o.js.

Se voc realmente valoriza a clareza de usar .mjs para mdulos versus usar .js para arquivos JavaScript "normais", mas no deseja se deparar com o problema descrito acima, sempre poder usar .mjs durante o desenvolvimento e convert-los em .js durante sua etapa de construo.

Tambm importante notar que:

  • Algumas ferramentas podem nunca suportar .mjs, comoTypeScript.
  • O atributo <script type="module"> usado para indicar quando um mdulo est sendo apontado, como voc ver abaixo.

Exportando recursos do mdulo

A primeira coisa que voc faz para obter acesso aos recursos do mdulo export-los. Isso feito usando o export declarao.

A maneira mais fcil de us-lo coloc-lo na frente de qualquer item que voc queira exportar para fora do mdulo, por exemplo:

js
export const name = "square";

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return {
    length: length,
    x: x,
    y: y,
    color: color,
  };
}

Voc pode exportar funes, var, let, const, e como veremos mais tarde - classes. Eles precisam ser itens de nvel superior; voc no pode usar a exportao dentro de uma funo, por exemplo.

Uma maneira mais conveniente de exportar todos os itens que voc deseja exportar usar uma nica instruo de exportao no final do arquivo do mdulo, seguida por uma lista separada por vrgula dos recursos que voc deseja exportar envoltos em chaves. Por exemplo:

js
export { name, draw, reportArea, reportPerimeter };

Importando recursos para o seu script

Depois de exportar alguns recursos do seu mdulo, necessrio import-los para o script para poder us-los. A maneira mais simples de fazer isso a seguinte:

js
import { name, draw, reportArea, reportPerimeter } from "./modules/square.js";

Voc usa o import , seguida por uma lista separada por vrgula dos recursos que voc deseja importar agrupados em chaves, seguidos pela palavra-chave de, seguida pelo caminho para o arquivo do mdulo - um caminho relativo raiz do site, que para nossa basic-modules exemplo seria/js-examples/modules/basic-modules.

No entanto, escrevemos o caminho de maneira um pouco diferente - estamos usando a sintaxe de ponto (.) Para significar "o local atual", seguido pelo caminho alm do arquivo que estamos tentando encontrar. Isso muito melhor do que escrever todo o caminho relativo a cada vez, pois mais curto e torna o URL porttil - o exemplo ainda funcionar se voc o mover para um local diferente na hierarquia do site.

Ento, por exemplo:

/js-examples/modules/basic-modules/modules/square.js

torna-se

./modules/square.js

Voc pode ver essas linhas em ao em main.js.

Nota: Nota: Em alguns sistemas de mdulos, voc pode omitir a extenso do arquivo e o ponto(e.g. '/modules/square'). Isso no funciona nos mdulos JavaScript nativos.

Depois de importar os recursos para o seu script, voc pode us-los exatamente como eles foram definidos no mesmo arquivo. O seguinte encontrado em main.js, abaixo das linhas de importao:

js
let myCanvas = create("myCanvas", document.body, 480, 320);
let reportList = createReportList(myCanvas.id);

let square1 = draw(myCanvas.ctx, 50, 50, 100, "blue");
reportArea(square1.length, reportList);
reportPerimeter(square1.length, reportList);

Nota: Nota: Embora os recursos importados estejam disponveis no arquivo, eles so visualizaes somente leitura do recurso que foi exportado. Voc no pode alterar a varivel importada, mas ainda pode modificar propriedades semelhantes const. Alm disso, esses recursos so importados como ligaes ativas, o que significa que eles podem mudar de valor mesmo que voc no possa modificar a ligao ao contrrio de const.

Aplicando o mdulo ao seu HTML

Agora, apenas precisamos aplicar o mdulo main.js. nossa pgina HTML. Isso muito semelhante ao modo como aplicamos um script regular a uma pgina, com algumas diferenas notveis.

Primeiro de tudo, voc precisa incluir type="module" no <script> elemento, para declarar esse script como um mdulo. Para importar o main.js script, usamos este:

html
<script type="module" src="main.js"></script>

Voc tambm pode incorporar o script do mdulo diretamente no arquivo HTML, colocando o cdigo JavaScript no corpo do elemento <script>:

js
<script type="module">/* JavaScript module code here */</script>

O script para o qual voc importa os recursos do mdulo atua basicamente como o mdulo de nvel superior. Se voc o omitir, o Firefox, por exemplo, exibir um erro "SyntaxError: as declaraes de importao podem aparecer apenas no nvel superior de um mdulo".

Voc s pode usar import e export instrues dentro de mdulos, no scripts regulares.

Outras diferenas entre mdulos e scripts padro

  • Voc precisa prestar ateno nos testes locais - se voc tentar carregar o arquivo HTML localmente (i.e. com um arquivo:// URL), voc encontrar erros do CORS devido a requisitos de segurana do mdulo JavaScript. Voc precisa fazer seus testes atravs de um servidor.
  • Alm disso, observe que voc pode obter um comportamento diferente das sees de script definidas dentro dos mdulos e no nos scripts padro. Isso ocorre porque os mdulos usam strict mode automaticamente.
  • No h necessidade de usar o atributo deferir (consulte <script> attributes) ao carregar um script de mdulo; mdulos so adiados automaticamente.
  • Os mdulos so executados apenas uma vez, mesmo que tenham sido referenciados em vrias tags <script>.
  • Por ltimo, mas no menos importante, vamos esclarecer: os recursos do mdulo so importados para o escopo de um nico script - eles no esto disponveis no escopo global. Portanto, voc poder acessar apenas os recursos importados no script para o qual eles foram importados e no poder acess-los no console JavaScript, por exemplo. Voc ainda receber erros de sintaxe mostrados no DevTools, mas no poder usar algumas das tcnicas de depurao que voc esperava usar.

Exportaes padro versus exportaes nomeadas

A funcionalidade que exportamos at agora foi composta por named exports cada item (seja uma funo, const, etc.) foi referido por seu nome na exportao e esse nome tambm foi usado para se referir a ele na importao.

H tambm um tipo de exportao chamado default export isso foi projetado para facilitar a funo padro fornecida por um mdulo e tambm ajuda os mdulos JavaScript a interoperar com os sistemas de mdulos CommonJS e AMD existentes (conforme explicado em ES6 In Depth: Modules por Jason Orendorff; procure por "Exportaes padro").

Vejamos um exemplo ao explicar como ele funciona. Nos nossos mdulos bsicos square.js voc pode encontrar uma funo chamada randomSquare() que cria um quadrado com cor, tamanho e posio aleatrios. Queremos exportar isso como padro, portanto, na parte inferior do arquivo, escrevemos isso:

js
export default randomSquare;

Note a falta dos colchetes.

Em vez disso, poderamos acrescentar export default na funo e defina-a como uma funo annima, assim:

js
export default function(ctx) {
  ...
}

No nosso arquivo main.js., importamos a funo padro usando esta linha:

js
import randomSquare from "./modules/square.js";

Isso ocorre porque h apenas uma exportao padro permitida por mdulo e sabemos que randomSquare isso.

js
import { default as randomSquare } from "./modules/square.js";

Nota: Nota: A sintaxe as para renomear itens exportados explicada abaixo no Renaming imports and exports seo.

Evitando conflitos de nomenclatura

At agora, nossos mdulos de desenho de forma de tela parecem estar funcionando bem. Mas o que acontece se tentarmos adicionar um mdulo que lide com o desenho de outra forma, como um crculo ou tringulo? Essas formas provavelmente teriam funes associadas, como draw(), reportArea(), etc. tambm; se tentssemos importar diferentes funes com o mesmo nome para o mesmo arquivo de mdulo de nvel superior, acabaramos com conflitos e erros.

Felizmente, existem vrias maneiras de contornar isso. Veremos isso nas prximas sees.

Renomeando importaes e exportaes

Dentro dos colchetes da instruo de importao e exportao, voc pode usar a palavra-chave junto com um novo nome de recurso, para alterar o nome de identificao que ser usado para um recurso dentro do mdulo de nvel superior.

Por exemplo, os dois itens a seguir executariam o mesmo trabalho, embora de uma maneira ligeiramente diferente:

js
// inside module.js
export { function1 as newFunctionName, function2 as anotherNewFunctionName };

// inside main.js
import { newFunctionName, anotherNewFunctionName } from "./modules/module.js";
js
// inside module.js
export { function1, function2 };

// inside main.js
import {
  function1 as newFunctionName,
  function2 as anotherNewFunctionName,
} from "./modules/module.js";

Vejamos um exemplo real. Na nossa renaming diretrio, voc ver o mesmo sistema de mdulos do exemplo anterior, exceto que adicionamos circle.js e triangle.js mdulos para desenhar e relatar crculos e tringulos.

Dentro de cada um desses mdulos, temos recursos com os mesmos nomes sendo exportados e, portanto, cada um tem o mesmo export declarao na parte inferior:

js
export { name, draw, reportArea, reportPerimeter };

Ao import-los para o main.js, se tentarmos usar

js
import { name, draw, reportArea, reportPerimeter } from "./modules/square.js";
import { name, draw, reportArea, reportPerimeter } from "./modules/circle.js";
import { name, draw, reportArea, reportPerimeter } from "./modules/triangle.js";

O navegador geraria um erro como "SyntaxError: redeclaration of import name" (Firefox).

Em vez disso, precisamos renomear as importaes para que sejam nicas:

js
import {
  name as squareName,
  draw as drawSquare,
  reportArea as reportSquareArea,
  reportPerimeter as reportSquarePerimeter,
} from "./modules/square.js";

import {
  name as circleName,
  draw as drawCircle,
  reportArea as reportCircleArea,
  reportPerimeter as reportCirclePerimeter,
} from "./modules/circle.js";

import {
  name as triangleName,
  draw as drawTriangle,
  reportArea as reportTriangleArea,
  reportPerimeter as reportTrianglePerimeter,
} from "./modules/triangle.js";

Observe que voc pode resolver o problema nos arquivos do mdulo, e.g.

js
// in square.js
export {
  name as squareName,
  draw as drawSquare,
  reportArea as reportSquareArea,
  reportPerimeter as reportSquarePerimeter,
};
js
// in main.js
import {
  squareName,
  drawSquare,
  reportSquareArea,
  reportSquarePerimeter,
} from "./modules/square.js";

E funcionaria da mesma forma. Qual o estilo que voc usa depende de voc, no entanto, sem dvida faz mais sentido deixar o cdigo do mdulo em paz e fazer as alteraes nas importaes. Isso faz especialmente sentido quando voc est importando de mdulos de terceiros sobre os quais voc no tem controle.

24/5000

Criando um objeto de mdulo

O mtodo acima funciona bem, mas um pouco confuso e longo. Uma soluo ainda melhor importar os recursos de cada mdulo dentro de um objeto de mdulo. O seguinte formulrio de sintaxe faz isso:

js
import * as Module from "./modules/module.js";

Isso captura todas as exportaes disponveis no module.js e as torna disponveis como membros de um objeto Module, efetivamente dando o seu prprio namespace. Ento, por exemplo:

js
Module.function1()
Module.function2()
etc.

Novamente, vejamos um exemplo real. Se voc for ao nosso module-objects diretrio, voc ver o mesmo exemplo novamente, mas reescrito para aproveitar essa nova sintaxe. Nos mdulos, as exportaes so todas da seguinte forma simples:

js
export { name, draw, reportArea, reportPerimeter };

As importaes, por outro lado, so assim:

js
import * as Canvas from "./modules/canvas.js";

import * as Square from "./modules/square.js";
import * as Circle from "./modules/circle.js";
import * as Triangle from "./modules/triangle.js";

Em cada caso, agora voc pode acessar as importaes do mdulo abaixo do nome do objeto especificado, por exemplo:

js
let square1 = Square.draw(myCanvas.ctx, 50, 50, 100, "blue");
Square.reportArea(square1.length, reportList);
Square.reportPerimeter(square1.length, reportList);

Agora voc pode escrever o cdigo da mesma forma que antes (contanto que inclua os nomes dos objetos quando necessrio) e as importaes sejam muito mais limpas.

Mdulos e classes

Como sugerimos anteriormente, voc tambm pode exportar e importar classes; essa outra opo para evitar conflitos no seu cdigo e especialmente til se voc j tiver o cdigo do mdulo gravado em um estilo orientado a objetos.

Voc pode ver um exemplo do nosso mdulo de desenho de forma reescrito com as classes ES em nosso classes diretrio. Como exemplo, o square.js O arquivo agora contm todas as suas funcionalidades em uma nica classe:

js
class Square {
  constructor(ctx, listId, length, x, y, color) {
    ...
  }

  draw() {
    ...
  }

  ...
}

que exportamos ento:

js
export { Square };

No main.js, ns o importamos assim:

js
import { Square } from "./modules/square.js";

E ento use a classe para desenhar nosso quadrado:

js
let square1 = new Square(myCanvas.ctx, myCanvas.listId, 50, 50, 100, "blue");
square1.draw();
square1.reportArea();
square1.reportPerimeter();

Mdulos de agregao

Haver momentos em que voc desejar agregar mdulos. Voc pode ter vrios nveis de dependncias, nos quais deseja simplificar as coisas, combinando vrios submdulos em um mdulo pai. Isso possvel usando a sintaxe de exportao dos seguintes formulrios no mdulo pai:

js
export * from "x.js";
export { name } from "x.js";

Por exemplo, veja nosso module-aggregation diretrio. Neste exemplo (com base no exemplo de classes anteriores), temos um mdulo extra chamado shapes.js, que agrega toda a funcionalidade de circle.js, square.js e triangle.js juntos. Tambm movemos nossos submdulos para dentro de um subdiretrio dentro do diretrio modules chamado shapes. Portanto, a estrutura do mdulo neste exemplo :

modules/
  canvas.js
  shapes.js
  shapes/
    circle.js
    square.js
    triangle.js

Em cada um dos submdulos, a exportao da mesma forma, e.g.

js
export { Square };

Em seguida, vem a parte de agregao. Dentro de shapes.js, inclumos as seguintes linhas:

js
export { Square } from "./shapes/square.js";
export { Triangle } from "./shapes/triangle.js";
export { Circle } from "./shapes/circle.js";

Eles capturam as exportaes dos submdulos individuais e os disponibilizam efetivamente no mdulo shapes.js.

Nota: Nota: As exportaes mencionadas no shapes.js so basicamente redirecionadas pelo arquivo e realmente no existem nele, portanto, voc no poder escrever nenhum cdigo relacionado til dentro do mesmo arquivo.

Portanto, agora no arquivo main.js., podemos obter acesso s trs classes de mdulos substituindo

js
import { Square } from "./modules/square.js";
import { Circle } from "./modules/circle.js";
import { Triangle } from "./modules/triangle.js";

com a seguinte linha nica:

js
import { Square, Circle, Triangle } from "./modules/shapes.js";

Carregamento dinmico do mdulo

A parte mais recente da funcionalidade dos mdulos JavaScript a estar disponvel nos navegadores o carregamento dinmico de mdulos. Isso permite que voc carregue mdulos dinamicamente somente quando eles forem necessrios, em vez de precisar carregar tudo antecipadamente. Isso tem algumas vantagens bvias de desempenho; vamos ler e ver como isso funciona.

Essa nova funcionalidade permite que voc ligue import() como uma funo, passando o caminho para o mdulo como um parmetro. Retorna umPromise, que cumpre com um objeto de mdulo (consulte Creating a module object) dando acesso s exportaes desse objeto, e.g.

js
import("./modules/myModule.js").then((module) => {
  // Do something with the module.
});

Vejamos um exemplo. No dynamic-module-imports diretrio, temos outro exemplo baseado em nosso exemplo de classes. Desta vez, no entanto, no estamos desenhando nada na tela quando o exemplo carregado. Em vez disso, inclumos trsbuttons "Circle", "Square", e "Triangle" que, quando pressionado, carrega dinamicamente o mdulo necessrio e, em seguida, usa-o para desenhar os shape.

Neste exemplo, fizemos apenas alteraes em nossa index.html e main.js arquivos - as exportaes do mdulo permanecem as mesmas de antes.

No main.js, pegamos uma referncia a cada boto usando umDocument.querySelector() chamada, por exemplo:

js
let squareBtn = document.querySelector(".square");

Em seguida, anexamos um ouvinte de evento a cada boto para que, quando pressionado, o mdulo relevante seja carregado dinamicamente e usado para desenhar a forma(shape):

js
squareBtn.addEventListener("click", () => {
  import("./modules/square.js").then((Module) => {
    let square1 = new Module.Square(
      myCanvas.ctx,
      myCanvas.listId,
      50,
      50,
      100,
      "blue",
    );
    square1.draw();
    square1.reportArea();
    square1.reportPerimeter();
  });
});

Observe que, como o cumprimento da promessa retorna um objeto de mdulo, a classe ento transformada em uma sub-caracterstica do objeto, portanto, agora precisamos acessar o construtor com Module. anexado a ele, e.g. Module.Square( ... ).

Soluo de problemas

Aqui esto algumas dicas que podem ajud-lo se voc estiver com problemas para fazer seus mdulos funcionarem. Sinta-se livre para adicionar lista se descobrir mais!

  • Mencionamos isso antes, mas para reiterar: arquivos.js precisa ser carregado com um tipo MIME de text/javascript (ou outro tipo MIME compatvel com JavaScript, mas text/javascript recomendvel), caso contrrio, voc receber um erro estrito de verificao do tipo MIME como "O servidor respondeu com um tipo MIME no JavaScript".
  • Se voc tentar carregar o arquivo HTML localmente (i.e. com um arquivo:// URL), voc encontrar erros do CORS devido a requisitos de segurana do mdulo JavaScript. Voc precisa fazer seus testes atravs de um servidor. As pginas do GitHub so ideais, pois tambm servem arquivos .js com o tipo MIME correto.
  • Como .mjs uma extenso de arquivo no padro, alguns sistemas operacionais podem no reconhec-lo ou tentar substitu-lo por outra. Por exemplo, descobrimos que o macOS estava adicionando silenciosamente .js ao final dos arquivos .mjs e ocultando automaticamente a extenso do arquivo. Ento, todos os nossos arquivos foram lanados como x.mjs.js. Depois de desativarmos ocultar automaticamente as extenses de arquivo e trein-lo para aceitar .mjs, tudo bem.

Veja tambm


Web Proxy Viewer  |  New URL  |  Original Page