Aguarde...

23 de junho de 2021

Como usar importações dinâmicas em JavaScript

Como usar importações dinâmicas em JavaScript

As importações dinâmicas são um dos recursos introduzidos na especificação JavaScript ES020. Este recurso torna os módulos introduzidos no ES2015, ou ES6, mais utilizáveis ​​e poderosos. Este tutorial ajudará você a entender o que são importações dinâmicas em JavaScript, como funcionam e como usá-las.

Módulos ES e chunking

Os módulos foram introduzidos como parte da especificação ES2015 (ES6). Isso deu aos desenvolvedores de JavaScript uma maneira nativa e agradável de dividir seu código JavaScript em pedaços menores. Os módulos também facilitaram o gerenciamento desses fragmentos, tornando até mesmo a base de código grande mais amigável ao desenvolvedor.

A melhor parte disso é que esse processo de agrupamento é muito simples e fácil. Quando o desenvolvedor JavaScript deseja usar módulos, existem basicamente apenas duas coisas que ela precisa fazer. Primeiro, ela precisa se lembrar de exportar alguns pedaços de seu código que deseja usar em outro lugar. Para fazer isso, ela precisa usar a instrução de exportação .

A segunda coisa a fazer é quando ela deseja usar um dos pedaços que exportou. Ela precisa usar a instrução import para importar um pedaço específico de código em um arquivo onde deseja usá-lo. Isso fará com que esse pedaço de código exportado fique disponível no escopo do arquivo com o qual ela está trabalhando no momento.

// File file1.js
// Export some function with "export" statement:
export const sumTwoNumbers = (numA, numB) => numA + numB


// File file2.js
// Import exported function sumTwoNumbers with "import" statement:
import { sumTwoNumbers } from './file1'

// Use imported function:
sumTwoNumbers(15, 98)
// Output:
// 113


// NOTE:
// You can also export something with default export
export default (numA, numB) => numA + numB

// File file2.js
// Import exported function sumTwoNumbers with default "import" statement:
import sumTwoNumbers from './file1'

Apenas duas instruções com uma sintaxe muito simples e fácil de lembrar e você pode usar seu código onde quiser. Infelizmente, nada geralmente é perfeito e até mesmo os módulos têm algumas desvantagens.

O problema com as importações estáticas

Uma grande desvantagem dos módulos ES é que eles são estáticos. Isso significa que ao importar algum módulo ele será sempre importado, independente se o código for executado ou não. Vamos voltar ao exemplo acima com sumTwoNumbersfunção. Imagine que essa função seja chamada apenas sob alguma condição específica.

Existe alguma instrução if… else e a função é chamada apenas dentro dela. Ao executar este código, o módulo com a sumTwoNumbersfunção será importado. JavaScript não se importará se a if...elseinstrução chama a função ou não. Ele importará o módulo e se a função não for executada não é problema de JavaScript.

O que isso significa para você e para qualquer outra pessoa que execute seu código é simples. Você terá que baixar e executar tudo o que é importado em algum lugar, independentemente se é realmente usado ou não. Isso pode funcionar na maioria das situações. No entanto, às vezes, você pode querer economizar parte da largura de banda do usuário.

Uma maneira de fazer isso é carregando esses módulos importados condicionalmente. Em vez de carregá-los sempre, por padrão, você os carregará apenas quando souber que serão usados. No caso da sumTwoNumbersfunção e if...elseinstrução, você pode importar a função dentro da instrução.

Nesse momento, quando o contexto de execução entra na instrução, você tem certeza de que a função será chamada. É aqui que as importações dinâmicas podem ser úteis.

Importações dinâmicas para o resgate

A ideia das importações dinâmicas é importar algum pedaço de código apenas quando você sabe que precisará dele. Por exemplo, para carregar a sumTwoNumbersfunção dentro da if...elseinstrução onde a função é chamada. Se o bloco de código dentro da instrução nunca for executado, o módulo com sumTwoNumbersnunca será importado.

Soa bem? É ainda melhor. Na verdade, não há uma nova sintaxe. As importações dinâmicas usam quase a mesma sintaxe das importações estáticas. Uma diferença é que em vez de usar importcomo uma instrução, você usa importcomo uma função. Essa função aceita um parâmetro, o caminho para o módulo, e retorna uma promessa .

// Dynamic import syntax:
const module = import('path')

// Examples:
const module1 = import('./myModule')

const modulePath = './myModule'
const module2 = import(modulePath)

Quando o módulo é carregado com sucesso, a promessa é resolvida para o conteúdo do módulo. Quando há algum problema, a promessa é rejeitada. Como a import()função retorna uma promessa, a sintaxe async / await (função async e operador await) pode ser útil e tornar seu código mais curto.

// await example with global await:
const module1 = await import('./myModule')

const modulePath = './myModule'
const module2 = await import(modulePath)

// Use what imported from module2
module2.someExportedFunction()

// await example with async function:
async function loadImport() {
  const module1 = await import('./myModule')

  // ... use the module
  module1.someExportedFunction()
}

Importando com importações dinâmicas

Da mesma forma que as importações estáticas, as importações dinâmicas também permitem importar exportações padrão, nomeadas e combinadas entre as duas.

Exportações padrão

Você exportou algo usando a exportação padrão. Quando você deseja importá-lo dinamicamente, você pode simplesmente usar a defaultpropriedade do objeto retornado pela promessa de importação. Bem, quase. O problema é que defaulté uma palavra-chave reservada em JavaScript. Isso também significa que você não pode usá-lo para declarar variáveis, como para o módulo importado.

O que você pode fazer para resolver esse problema é usar a atribuição de desestruturação e criar um alias para essa importação padrão. Em seguida, você pode usar esse alias para usar com segurança tudo o que importou.

// File 1:
// Use default export to export a function:
export default (numA, numB) => numA * numB


// File 2:
// Create async function:
async function loadModule() {
  // Use dynamic import to import function from "file1"
  // and use destructuring assignment with alias:
  const { default: defaultExport } = await import('./file1')

  // Use the imported function by using the alias:
  defaultExport(315, 414)
}

// Call the loadModule() function:
loadModule()
// Output:
// 130410

Outra opção é atribuir o módulo a uma variável sem usar a atribuição de desestruturação. Isso atribuirá todo o módulo como um objeto à variável. Agora, você pode usar a defaultpropriedade deste objeto para acessar a exportação padrão.

// File 1:
// Use default export to export a function:
export default (numA, numB) => numA * numB


// File 2:
// Create async function:
async function loadModule() {
  // Assign the module to a variable:
  const myExport = await import('./file1')

  // Use the imported function by using the alias:
  myExport.default(56, 89)
}

// Call the loadModule() function:
loadModule()
// Output:
// 4984

Exportações nomeadas

Importar exportações nomeadas com importações dinâmicas é ainda mais fácil. Não há necessidade de usar apelidos. Tudo que você precisa fazer é atribuir o módulo a uma variável, com ou sem atribuição de desestruturação. Em seguida, você pode usar tudo o que importou. Você pode fazer isso acessando o objeto de módulo se não tiver usado a atribuição de desestruturação.

Se você usou atribuição de desestruturação, você pode simplesmente usar o nome da variável que você usou durante a desestruturação do objeto.

// Example without destructuring:
// File 1:
// Use default export to export a function:
export const divideNumbers = (numA, numB) => numA / numB


// File 2:
// Create async function:
async function loadModule() {
  // Assign the module to a variable:
  const myNExport = await import('./file1')

  // Use the imported function by using the alias:
  myNExport.divideNumbers(996598, 15)
}

// Call the loadModule() function:
loadModule()
// Output:
// 66439.86666666667


// Example with destructuring:
// File 1:
export const divideNumbers = (numA, numB) => numA / numB


// File 2:
// Create async function:
async function loadModule() {
  // Use destructuring to assign the divideNumbers() function:
  const { divideNumbers } = await import('./file1')

  // Use the imported function by using the alias:
  divideNumbers(477575, 66)
}

// Call the loadModule() function:
loadModule()
// Output:
// 7235.984848484848

Exportações mistas

A importação de exportações mistas, uma padrão e outras nomeadas, consiste basicamente em combinar as duas abordagens anteriores. Novamente, você pode usar a atribuição de desestruturação para atribuir todas as exportações a variáveis. Lembre-se de criar um alias para a exportação padrão. Caso contrário, o JavaScript irá reclamar da defaultpalavra – chave.

Caso contrário, você pode atribuir todas as exportações, o objeto de módulo inteiro, a uma única variável. Então, cada exportação se tornará uma propriedade deste objeto de módulo e você poderá usá-las através deste objeto de módulo.

// Example with destructuring:
// File 1:
export default (numA, numB) => numA % numB
export const subtractNumbers = (numA, numB) => numA - numB


// File 2:
async function loadModule() {
  // Use destructuring to assign the named and default exports:
  const { default: getModulo, subtractNumbers } = await import('./file1')

  // Use the imported functions:
  subtractNumbers(477575, 66)
  getModulo(537, 8)
}

// Call the loadModule() function:
loadModule()
// Output:
// 477509
// 1


// Example without destructuring:
// File 1:
export default (numA, numB) => numA % numB
export const subtractNumbers = (numA, numB) => numA - numB


// File 2:
// Create async function:
async function loadModule() {
  // Assign the whole module to a single variable:
  const myModule = await import('./file1')

  // Use the imported functions:
  myModule.subtractNumbers(976532, 321)
  myModule.default(9872, 11)
}

// Call the loadModule() function:
loadModule()
// Output:
// 976211
// 5

Quando usar importações dinâmicas

Pode parecer que as importações dinâmicas são uma substituição dos módulos estáticos e devem ser usadas com frequência. Isso não é verdade. Eles não estão substituindo nada. Eles são apenas uma ferramenta que pode ajudá-lo a resolver alguns problemas. Isso também significa que eles não devem se tornar seu novo padrão. Você ainda deve usar principalmente importações estáticas.

A maioria de suas importações será para pequenos módulos, geralmente dezenas de linhas de código. Carregar esses módulos dinamicamente não fará tanta diferença. A situação em que as importações dinâmicas podem ser uma boa escolha é quando você trabalha com grandes módulos. Quando algum módulo demora para carregar, carregá-lo dinamicamente pode ajudar no desempenho.

Isso ocorre principalmente se esse módulo não for imediatamente necessário para o programa. Outros bons casos de uso são quando a) um módulo pode não estar disponível desde o início eb) o caminho para o módulo é construído dinamicamente. As importações dinâmicas podem facilitar o tratamento dessas situações raras. Além dessas situações, fique com as importações estáticas.

Conclusão: como usar importações dinâmicas em JavaScript

Os módulos podem ajudá-lo a tornar seu trabalho mais fácil, seu código mais gerenciável e limpo. As importações dinâmicas podem levar isso mais longe, ajudando você a carregar módulos apenas quando necessário. Isso pode ajudá-lo a melhorar o desempenho do seu código. Espero que este tutorial tenha ajudado você a aprender o que são importações dinâmicas, como funcionam e como usá-las.

Postado em Blog
Escreva um comentário