As compilações podem ser feitas mais rapidamente usando ferramentas como esbuild . No entanto, se você investiu em webpack , mas ainda gostaria de aproveitar as vantagens de compilações, há uma maneira.
Neste tutorial, mostraremos como usar esbuild junto com webpack com esbuild-loader .
O mundo do desenvolvimento web está evoluindo
Com desculpas para aqueles que sofrem de fadiga do JavaScript, o mundo do desenvolvimento da web está evoluindo novamente. Há muito tempo é uma prática comum executar seu JavaScript e TypeScript por meio de algum tipo de ferramenta de compilação baseada em Node.js, como webpack ou rollup.js. Essas ferramentas são escritas na mesma linguagem para a qual são compiladas-a saber, JavaScript ou TypeScript.
As novas crianças no blog são ferramentas como esbuild , Vite e swc . A diferença significativa entre eles e seus predecessores é que as ferramentas da nova escola são escritas em linguagens como Go e Rust. Go and Rust desfrute de um desempenho muito melhor do que o JavaScript. Isso se traduz em compilações significativamente mais rápidas .
Essas novas ferramentas são transformadoras e provavelmente representam o futuro da construção de ferramentas para a web. A longo prazo, empresas como esbuild, Vite , e amigos podem vir a substituir as ferramentas de compilação padrão atuais-os webpacks, rollups e assim por diante.
No entanto, esse é o longo prazo. Existem muitos projetos por aí que já estão fortemente investidos em suas ferramentas de construção atuais-principalmente webpack. Migrar para uma nova ferramenta de construção não é uma tarefa fácil. Novos projetos podem começar com o Vite, mas os existentes têm menos probabilidade de serem transferidos. Há uma razão para o webpack ser tão popular; ele faz muitas coisas muito bem. É testado em grandes projetos, é maduro e lida com uma ampla gama de casos de uso.
Então, se sua equipe deseja compilações mais rápidas, mas não tem tempo para fazer uma grande migração, há algo que você possa fazer? Sim, há um meio-termo a ser explorado.
Há um projeto relativamente novo chamado esbuild-loader . Desenvolvido por hiroki osame , esbuild-loader é um carregador de webpack construído em cima do esbuild. Ele permite que os usuários troquem ts-loader
ou babel-loader
com ele mesmo, o que melhora enormemente a velocidade de construção.
Para declarar interesse aqui para divulgação completa, sou o principal mantenedor de ts-loader , um TypeScript popular carregador que é comumente usado com webpack. No entanto, acredito fortemente que o importante aqui é a produtividade do desenvolvedor. Como projetos baseados em Node.js, ts-loader
e babel-loader
nunca serão capazes de competir com esbuild-loader
da mesma maneira. Como uma linguagem, Go realmente, uh, vai!
Embora o esbuild possa não funcionar para todos os casos de uso, ele funcionará para a maioria das tarefas. Como tal, o esbuild-loader
representa um meio-termo-e uma maneira inicial de obter acesso à maior velocidade de compilação que o esbuild oferece sem dizer adeus ao webpack. Este passo a passo explorará o uso do esbuild-loader
na configuração do pacote da web.
Migrando um projeto existente para esbuild
É muito simples migrar um projeto que usa babel-loader
ou ts-loader
para esbuild-loader
. Primeiro, instale a dependência:
npm i-D esbuild-loader
Se você estiver usando o babel-loader
, faça a seguinte alteração em seu webpack.config.js
:
module.exports={ módulo: { as regras: [ -{ -teste:/\.js$/, -use:'babel-loader', -}, + { + teste:/\.js$/, + loader:'esbuild-loader', + opções: { + loader:'jsx',//Remova isto se você não estiver usando JSX + target:'es2015'//Sintaxe para compilar (veja as opções abaixo para valores possíveis) +} +}, ... ], }, }
Ou, se você estiver usando ts-loader
, faça a seguinte alteração em seu webpack.config.js
:
module.exports={ módulo: { as regras: [ -{ -teste:/\.tsx?$/, -use:'ts-loader' -}, + { + teste:/\.tsx?$/, + loader:'esbuild-loader', + opções: { + loader:'tsx',//Ou'ts'se você não precisa de tsx + alvo:'es2015' +} +}, ... ] }, }
Criação de um aplicativo de linha de base
Vamos ver como o esbuild-loader
funciona na prática. Vamos criar um novo aplicativo React usando Criar aplicativo React :
npx create-react-app my-app--template typescript
Isso criará o scaffold de um novo aplicativo React usando TypeScript no diretório my-app
. Vale a pena mencionar que o aplicativo Create React usa o babel-loader
nos bastidores.
O CRA também usa o Plug-in Webpack do Fork TS Checker para fornecer verificação de tipo TypeScript. Isso é muito útil porque o esbuild apenas faz a transpilação e não foi projetado para fornecer suporte à verificação de tipo . Portanto, é uma sorte ainda termos esse plug-in. Caso contrário, perderíamos a verificação de tipo.
Agora que você entende a vantagem de mudar para o esbuild, primeiro precisamos de uma linha de base para entender como é o desempenho com o babel-loader
. Executaremos time npm run build
para executar uma compilação de nosso aplicativo simples:
Nossa compilação completa, verificação de tipo TypeScript, transpilação, minificação e assim por diante, tudo levou 22,08 segundos. A questão agora é: o que aconteceria se incluíssemos o esbuild na mistura?
Apresentando esbuild-loader
Uma maneira de personalizar um build Create React App é executando npm run eject
e, em seguida, personalizando o código que o CRA bombeia. Isso é bom, mas significa que você não pode acompanhar a evolução do CRA. Uma alternativa é usar uma ferramenta como Create React App Configuration Override (CRACO) , que permite ajustar a configuração no local. CRACO se descreve como “um fácil e camada de configuração compreensível para create-react-app
.”
Vamos adicionar esbuild-loader
e CRACO como dependências:
npm install @ craco/craco esbuild-loader--save-dev
Então, vamos trocar nossos vários scripts
em nosso package.json
para usar CRACO
:
"start":"craco start", "build":"craco build", "teste":"teste de craco",
Nosso aplicativo agora usa CRACO, mas ainda não o configuramos. Portanto, vamos adicionar um arquivo craco.config.js
à raiz do nosso projeto. É aqui que trocamos babel-loader
por esbuild-loader
:
const {addAfterLoader, removeLoaders, loaderByName, getLoaders, throwUnexpectedConfigError}=require ('@ craco/craco'); const {ESBuildMinifyPlugin}=require ('esbuild-loader'); const throwError=(mensagem)=> throwUnexpectedConfigError ({ nome do pacote:'craco', githubRepo:'gsoft-inc/craco', mensagem, githubIssueQuery:'webpack', }); module.exports={ webpack: { configurar: (webpackConfig, {caminhos})=> { const {hasFoundAny, corresponde}=getLoaders (webpackConfig, loaderByName ('babel-loader')); if (! hasFoundAny) throwError ('falhou em encontrar o babel-loader'); console.log ('removendo o babel-loader'); const {hasRemovedAny, removedCount}=removeLoaders (webpackConfig, loaderByName ('babel-loader')); if (! hasRemovedAny) throwError ('nenhum carregador de babel para remover'); if (removedCount!==2) throwError ('esperava remover 2 instâncias do carregador do babel'); console.log ('adicionando esbuild-loader'); const tsLoader={ teste:/\.(js|mjs|jsx|ts|tsx)$/, incluem: paths.appSrc, carregador: require.resolve ('esbuild-loader'), opções: { carregador:'tsx', alvo:'es2015' }, }; const {isAdded: tsLoaderIsAdded}=addAfterLoader (webpackConfig, loaderByName ('url-loader'), tsLoader); if (! tsLoaderIsAdded) throwError ('falha ao adicionar esbuild-loader'); console.log ('adicionado esbuild-loader'); console.log ('adicionando de volta o JS babel-loader não-aplicativo'); const {isAdded: babelLoaderIsAdded}=addAfterLoader ( webpackConfig, loaderByName ('esbuild-loader'), corresponde a [1].loader//babel-loader ); if (! babelLoaderIsAdded) throwError ('falha ao adicionar de volta o carregador de babel para JS não-aplicativo'); console.log ('adicionado não-aplicativo JS babel-loader de volta'); console.log ('substituindo TerserPlugin por ESBuildMinifyPlugin'); webpackConfig.optimization.minimizer=[ novo ESBuildMinifyPlugin ({ alvo:'es2015' }) ]; return webpackConfig; }, }, };
Então, o que está acontecendo aqui? O script procura os usos do babel-loader
na configuração padrão Criar aplicativo React. Haverá dois: um para o código de aplicativo TypeScript/JavaScript (queremos substituí-lo) e um para o código de não aplicativo JavaScript. Não está muito claro qual código JavaScript não aplicável existe ou pode haver, então vamos deixá-lo como está; pode ser importante. O código com o qual realmente nos importamos é o código do aplicativo.
Você não pode remover um único carregador usando CRACO
, então, em vez disso, removeremos ambos e adicionaremos de volta o JavaScript não aplicável babel-loader
. Também adicionaremos esbuild-loader
com a opção {loader:'tsx', target:'es2015'}
definida para garantir que possamos processar JSX/TSX.
Finalmente, trocaremos usando Terser para minificação de JavaScript para esbuild como bem.
Uma tremenda melhoria de desempenho
Nossa migração foi concluída. Na próxima vez que construirmos, teremos Create React App rodando usando esbuild-loader
sem ter ejetado. Mais uma vez, vamos executar time npm run build
para executar uma compilação de nosso aplicativo simples e determinar quanto tempo leva:
Nossa compilação completa, verificação de tipo do TypeScript, transpilação, minificação e assim por diante, tudo levou 13,85 segundos. Ao migrar para o esbuild-loader
, reduzimos nosso tempo geral de compilação em aproximadamente um terço. Esta é uma melhoria tremenda!
Conforme sua base de código é dimensionada e seu aplicativo cresce, o tempo de compilação pode disparar. Com o esbuild-loader
, você deve colher benefícios contínuos para o seu tempo de compilação.
A postagem webpack ou esbuild: Por que não ambos? apareceu primeiro no LogRocket Blog .