Como o Webpack resolve imports dinâmicos com paths variáveis

Não é mágica, eu prometo

Escrito em 11 de abril de 2022 - 🕒 3 min. de leitura

Webpack é o bundler de módulos mais popular para JavaScript, é uma ferramenta para agrupar módulos em um único arquivo e mais.

Uma coisa que sempre me deixou curioso foi como ele resolve os imports dinâmicos, quer dizer, eu sabia que não era mágica, mas não sabia como funcionava, e sempre esquecia de pesquisar depois… até agora.

Mágica?
Mágica?

Como funciona o import de arquivos

Sempre que você importar um arquivo em seu código, o Webpack irá procurá-lo na pasta do projeto e copiá-lo para a pasta de build com um novo nome, então o Webpack substituirá o código que importa esse arquivo em seu arquivo JavaScript pelo path para o arquivo recém-copiado.

Aqui está um exemplo super simplificado:

// import on your app.js file
import utils from './helpers/utils.js';

// import on the bundled file
import utils from './build/09wdj0wjd.bundle.0.js';

O que é um import dinâmico?

Às vezes você não quer que o browser baixe o arquivo imediatamente, você quer carregá-lo apenas quando for necessário, e para isso, você pode usar um import dinâmico.

const button = document.createElement('button');
button.innerHTML = 'Click me';
// when the button is clicked, a dynamic import will happen
button.onclick = () => import('./helpers/utils.js').then(() => console.log('Dynamic import'));

É possível usar import dinâmicos com praticamente qualquer arquivo, por isso é bastante útil para imagens ou arquivos de áudio grandes, por exemplo.

Mas o que acontece quando você quer importar um arquivo com um path variável?

const fileName = 'image.jpg';
const button = document.createElement('button');
button.innerHTML = 'Click me';
button.onclick = () => import(`./assets/images/${fileName}`);

Como o Webpack sabe qual arquivo copiar para a pasta build? Bem, existe uma maneira de dizer ao Webpack para ignorar o import e deixar o browser resolve-lo como quiser com o comentário /* webpackIgnore: true */.

const path = 'assets/images/image.jpg';
// the browser will resolve this import and fail if the file doesn't exist
const module = await import(/*webpackIgnore: true*/ path);

Isso é bem maneiro, mas de alguma forma também é possível não fazer isso e deixar o Webpack descobrir o path para o arquivo. Mas como?

Magic

O truque de mágica

Na verdade, não é tão complicado, mas vem com algumas ressalvas. Por exemplo, se você importar um arquivo com um path variável, pelo menos uma parte desse path precisa ser explícito no código, por exemplo:

// this works
const fileName = 'image.jpg';
let module = await import(`./assets/images/${fileName}`);

// this doesn't work
const path = './assets/images/image.jpg';
module = await import(path);

Por que isso? A maneira como o Webpack faz isso é analisando o path da string interpolada durante o processo de compilação, e ele obterá a parte explícita da string, neste exemplo assets/images/, e então copiará todos os arquivos dessa pasta para a pasta build.

O Webpack faz isso de uma maneira muito inteligente também, se o import incluir a extensão do arquivo, ele copiará apenas os arquivos com essa extensão, por exemplo import(`./assets/images/${fileName}.png`) só copiará arquivos PNG.

Como o Webpack faz isso analisando a string no import, ele não é capaz de saber quais arquivos copiar quando o path inteiro é uma variável sem uma parte explícita.

Conclusão

O Webpack pode ter uma configuração complicada e, às vezes, pode parecer feitiçaria, mas é uma ferramenta muito poderosa com muitos recursos e, se você se aprofundar o suficiente, descobrirá que sua implementação não é tão complicada.

Se você quiser saber mais sobre o Webpack, você pode conferir a documentação oficial, e você pode ler mais sobre Module Methods aqui e Dynamic Imports aqui.

Tags:


Publicar um comentário

Comentários

Nenhum comentário.