React Compiler
Esta página dará uma introdução ao React Compiler e como experimentá-lo com sucesso.
Você aprenderá
- Começando com o compilador
- Instalando o compilador e o plugin ESLint
- Solução de problemas
React Compiler é um novo compilador que lançamos com código aberto para obter feedback inicial da comunidade. É uma ferramenta somente em tempo de compilação que otimiza automaticamente seu aplicativo React. Ele funciona com JavaScript simples e entende as Regras do React, para que você não precise reescrever nenhum código para usá-lo.
O compilador também inclui um plugin ESLint que mostra a análise do compilador diretamente no seu editor. Recomendamos fortemente que todos usem o linter hoje. O linter não exige que você tenha o compilador instalado, para que você possa usá-lo mesmo que não esteja pronto para experimentar o compilador.
O compilador é lançado atualmente como beta
e está disponível para testes em aplicativos e bibliotecas React 17+. Para instalar o Beta:
Ou, se você estiver usando Yarn:
Se você ainda não estiver usando o React 19, consulte a seção abaixo para obter mais instruções.
O que o compilador faz?
Para otimizar aplicativos, o React Compiler memoriza automaticamente seu código. Você pode estar familiarizado hoje com a memorização por meio de APIs como useMemo
, useCallback
e React.memo
. Com essas APIs, você pode dizer ao React que certas partes do seu aplicativo não precisam ser recalculadas se suas entradas não foram alteradas, reduzindo o trabalho nas atualizações. Embora poderoso, é fácil esquecer de aplicar a memorização ou aplicá-la incorretamente. Isso pode levar a atualizações ineficientes, pois o React precisa verificar partes da sua UI que não possuem nenhuma alteração significativa.
O compilador usa seu conhecimento de JavaScript e as regras do React para memorizar automaticamente valores ou grupos de valores dentro de seus componentes e hooks. Se ele detectar quebras das regras, ele ignorará automaticamente apenas esses componentes ou hooks e continuará compilando outros códigos com segurança.
Se sua base de código já está muito bem memorizada, você pode não esperar ver grandes melhorias de desempenho com o compilador. No entanto, na prática, memorizar as dependências corretas que causam problemas de desempenho é complicado de fazer manualmente.
Deep Dive
A versão inicial do React Compiler está focada principalmente em melhorar o desempenho da atualização (renderizar novamente componentes existentes), portanto, ele se concentra nesses dois casos de uso:
- Ignorando a renderização em cascata de componentes
- Renderizar novamente
<Parent />
faz com que muitos componentes em sua árvore de componentes sejam renderizados novamente, mesmo que apenas<Parent />
tenha mudado
- Renderizar novamente
- Ignorando cálculos caros de fora do React
- Por exemplo, chamar
expensivelyProcessAReallyLargeArrayOfObjects()
dentro do seu componente ou hook que precisa desses dados
- Por exemplo, chamar
Otimizando as Renderizações Novamente
O React permite que você expresse sua UI como uma função de seu estado atual (mais concretamente: suas props, estado e contexto). Em sua implementação atual, quando o estado de um componente muda, o React renderizará novamente esse componente e todos os seus filhos — a menos que você tenha aplicado alguma forma de memorização manual com useMemo()
, useCallback()
ou React.memo()
. Por exemplo, no exemplo a seguir, <MessageButton>
será renderizado novamente sempre que o estado de <FriendList>
mudar:
function FriendList({ friends }) {
const onlineCount = useFriendOnlineCount();
if (friends.length === 0) {
return <NoFriends />;
}
return (
<div>
<span>{onlineCount} online</span>
{friends.map((friend) => (
<FriendListCard key={friend.id} friend={friend} />
))}
<MessageButton />
</div>
);
}
Veja este exemplo no React Compiler Playground
O React Compiler aplica automaticamente o equivalente à memorização manual, garantindo que apenas as partes relevantes de um aplicativo sejam renderizadas novamente à medida que o estado muda, o que às vezes é chamado de “reatividade granular”. No exemplo acima, o React Compiler determina que o valor de retorno de <FriendListCard />
pode ser reutilizado mesmo quando os friends
mudam e pode evitar a recriação deste JSX e evitar a renderização novamente de <MessageButton>
à medida que a contagem muda.
Cálculos caros também são memorizados
O compilador também pode memorizar automaticamente cálculos caros usados durante a renderização:
// **Não** memorizado pelo React Compiler, pois este não é um componente ou hook
function expensivelyProcessAReallyLargeArrayOfObjects() { /* ... */ }
// Memorizado pelo React Compiler, pois este é um componente
function TableContainer({ items }) {
// Essa chamada de função seria memorizada:
const data = expensivelyProcessAReallyLargeArrayOfObjects(items);
// ...
}
Veja este exemplo no React Compiler Playground
No entanto, se expensivelyProcessAReallyLargeArrayOfObjects
for realmente uma função cara, você pode querer considerar a implementação de sua própria memorização fora do React, porque:
- O React Compiler só memoriza componentes e hooks do React, não todas as funções
- A memorização do React Compiler não é compartilhada entre vários componentes ou hooks
Portanto, se expensivelyProcessAReallyLargeArrayOfObjects
fosse usado em muitos componentes diferentes, mesmo que os mesmos itens exatos fossem passados, esse cálculo caro seria executado repetidamente. Recomendamos fazer o perfil primeiro para ver se é realmente tão caro antes de tornar o código mais complicado.
Devo experimentar o compilador?
Observe que o compilador ainda está em Beta e tem muitas arestas. Embora tenha sido usado em produção em empresas como a Meta, a implantação do compilador em produção para seu aplicativo dependerá da integridade da sua base de código e de como você seguiu as Regras do React.
Você não precisa se apressar em usar o compilador agora. Tudo bem esperar até que ele atinja uma versão estável antes de adotá-lo. No entanto, agradecemos experimentar em pequenos experimentos em seus aplicativos para que você possa fornecer feedback para nos ajudar a tornar o compilador melhor.
Começando
Além desses documentos, recomendamos verificar o Grupo de Trabalho do React Compiler para obter informações e discussões adicionais sobre o compilador.
Instalando eslint-plugin-react-compiler
O React Compiler também alimenta um plugin ESLint. O plugin ESLint pode ser usado independentemente do compilador, o que significa que você pode usar o plugin ESLint mesmo que não use o compilador.
Em seguida, adicione-o à sua configuração ESLint:
import reactCompiler from 'eslint-plugin-react-compiler'
export default [
{
plugins: {
'react-compiler': reactCompiler,
},
rules: {
'react-compiler/react-compiler': 'error',
},
},
]
Ou, no formato de configuração eslintrc obsoleto:
module.exports = {
plugins: [
'eslint-plugin-react-compiler',
],
rules: {
'react-compiler/react-compiler': 'error',
},
}
O plugin ESLint exibirá quaisquer violações das regras do React no seu editor. Quando ele faz isso, significa que o compilador ignorou a otimização desse componente ou hook. Isso é perfeitamente aceitável, e o compilador pode se recuperar e continuar otimizando outros componentes em sua base de código.
Implantando o compilador em sua base de código
Projetos existentes
O compilador foi projetado para compilar componentes funcionais e hooks que seguem as Regras do React. Ele também pode lidar com código que quebra essas regras, abandonando (ignorando) esses componentes ou hooks. No entanto, devido à natureza flexível do JavaScript, o compilador não pode detectar todas as violações possíveis e pode compilar com falsos negativos: ou seja, o compilador pode compilar acidentalmente um componente/hook que quebra as Regras do React, o que pode levar a um comportamento indefinido.
Por esse motivo, para adotar o compilador com sucesso em projetos existentes, recomendamos executá-lo primeiro em um diretório pequeno no código do seu produto. Você pode fazer isso configurando o compilador para ser executado apenas em um conjunto específico de diretórios:
const ReactCompilerConfig = {
sources: (filename) => {
return filename.indexOf('src/path/to/dir') !== -1;
},
};
Quando você tiver mais confiança em implantar o compilador, também poderá expandir a cobertura para outros diretórios e implantá-lo lentamente em todo o seu aplicativo.
Novos projetos
Se você estiver iniciando um novo projeto, poderá habilitar o compilador em toda a sua base de código, que é o comportamento padrão.
Como usar o React Compiler com React 17 ou 18
O React Compiler funciona melhor com o React 19 RC. Se você não puder fazer o upgrade, poderá instalar o pacote extra react-compiler-runtime
, que permitirá que o código compilado seja executado em versões anteriores à 19. No entanto, observe que a versão mínima suportada é 17.
Você também deve adicionar o target
correto à sua configuração do compilador, onde target
é a versão principal do React que você está segmentando:
// babel.config.js
const ReactCompilerConfig = {
target: '18' // '17' | '18' | '19'
};
module.exports = function () {
return {
plugins: [
['babel-plugin-react-compiler', ReactCompilerConfig],
],
};
};
Como usar o compilador em bibliotecas
O React Compiler também pode ser usado para compilar bibliotecas. Como o React Compiler precisa ser executado no código-fonte original antes de qualquer transformação de código, não é possível para o pipeline de build de um aplicativo compilar as bibliotecas que ele usa. Portanto, nossa recomendação é que os mantenedores da biblioteca compilem e testem suas bibliotecas de forma independente com o compilador e enviem o código compilado para npm.
Como seu código é pré-compilado, os usuários da sua biblioteca não precisarão ter o compilador ativado para se beneficiarem da memorização automática aplicada à sua biblioteca. Se sua biblioteca tiver como alvo aplicativos que ainda não são no React 19, especifique um target
mínimo e adicione react-compiler-runtime
como uma dependência direta. O pacote de tempo de execução usará a implementação correta das APIs, dependendo da versão do aplicativo, e preencherá as APIs ausentes, se necessário.
O código da biblioteca geralmente pode exigir padrões e uso de saídas de emergência mais complexos. Por esse motivo, recomendamos garantir que você tenha testes suficientes para identificar quaisquer problemas que possam surgir do uso do compilador em sua biblioteca. Se você identificar algum problema, sempre poderá optar por não otimizar componentes ou hooks específicos com a diretiva 'use no memo'
.
De forma semelhante aos aplicativos, não é necessário compilar totalmente 100% de seus componentes ou hooks para ver os benefícios em sua biblioteca. Um bom ponto de partida pode ser identificar as partes mais sensíveis ao desempenho da sua biblioteca e garantir que elas não quebrem as Regras do React, o que você pode usar o eslint-plugin-react-compiler
para identificar.
Uso
Babel
O compilador inclui um plugin Babel que você pode usar em seu pipeline de compilação para executar o compilador.
Após a instalação, adicione-o à sua configuração Babel. Observe que é fundamental que o compilador seja executado primeiro no pipeline:
// babel.config.js
const ReactCompilerConfig = { /* ... */ };
module.exports = function () {
return {
plugins: [
['babel-plugin-react-compiler', ReactCompilerConfig], // must run first!
// ...
],
};
};
babel-plugin-react-compiler
deve ser executado primeiro antes de outros plugins Babel, pois o compilador exige as informações da fonte de entrada para uma análise confiável.
Vite
Se você usar o Vite, poderá adicionar o plugin ao vite-plugin-react:
// vite.config.js
const ReactCompilerConfig = { /* ... */ };
export default defineConfig(() => {
return {
plugins: [
react({
babel: {
plugins: [
["babel-plugin-react-compiler", ReactCompilerConfig],
],
},
}),
],
// ...
};
});
Next.js
Consulte a documentação do Next.js para obter mais informações.
Remix
Instale vite-plugin-babel
e adicione o plugin Babel do compilador a ele:
// vite.config.js
import babel from "vite-plugin-babel";
const ReactCompilerConfig = { /* ... */ };
export default defineConfig({
plugins: [
remix({ /* ... */}),
babel({
filter: /\.[jt]sx?$/,
babelConfig: {
presets: ["@babel/preset-typescript"], // if you use TypeScript
plugins: [
["babel-plugin-react-compiler", ReactCompilerConfig],
],
},
}),
],
});
Webpack
Um carregador Webpack da comunidade está disponível aqui.
Expo
Consulte a documentação do Expo para habilitar e usar o React Compiler em aplicativos Expo.
Metro (React Native)
React Native usa Babel via Metro, portanto, consulte a seção Uso com Babel para obter instruções de instalação.
Rspack
Consulte a documentação do Rspack para habilitar e usar o React Compiler em aplicativos Rspack.
Rsbuild
Consulte a documentação do Rsbuild para habilitar e usar o React Compiler em aplicativos Rsbuild.
Solução de problemas
Para relatar problemas, primeiro crie uma reprodução mínima no React Compiler Playground e inclua-a no seu relatório de bug. Você pode abrir problemas no repositório facebook/react.
Você também pode fornecer feedback no Grupo de Trabalho do React Compiler solicitando ser um membro. Consulte o README para obter mais detalhes sobre como participar.
O que o compilador assume?
O React Compiler assume que seu código:
- É JavaScript semântico válido.
- Teste se valores e propriedades anuláveis/opcionais são definidos antes de acessá-los (por exemplo, habilitando
strictNullChecks
ao usar o TypeScript), ou seja,if (object.nullableProperty) { object.nullableProperty.foo }
ou com encadeamento opcionalobject.nullableProperty?.foo
. - Segue as Regras do React.
O React Compiler pode verificar muitas das Regras do React estaticamente e ignorará com segurança a compilação quando detectar um erro. Para ver os erros, recomendamos também instalar eslint-plugin-react-compiler.
Como sei que meus componentes foram otimizados?
React DevTools (v5.0+) e React Native DevTools têm suporte integrado para o React Compiler e exibirão um selo “Memo ✨” próximo aos componentes que foram otimizados pelo compilador.
Algo não está funcionando após a compilação
Se você tiver o eslint-plugin-react-compiler instalado, o compilador exibirá quaisquer violações das regras do React no seu editor. Quando ele faz isso, significa que o compilador ignorou a otimização desse componente ou hook. Isso é perfeitamente aceitável, e o compilador pode se recuperar e continuar otimizando outros componentes em sua base de código. Você não precisa corrigir todas as violações do ESLint imediatamente. Você pode corrigi-las no seu próprio ritmo para aumentar a quantidade de componentes e hooks sendo otimizados.
No entanto, devido à natureza flexível e dinâmica do JavaScript, não é possível detectar de forma abrangente todos os casos. Bugs e comportamento indefinido, como loops infinitos, podem ocorrer nesses casos.
Se seu aplicativo não funcionar corretamente após a compilação e você não estiver vendo nenhum erro do ESLint, o compilador pode estar compilando seu código incorretamente. Para confirmar isso, tente desfazer o problema desativando agressivamente qualquer componente ou hook que você acha que pode estar relacionado por meio da diretiva "use no memo"
.
function SuspiciousComponent() {
"use no memo"; // desativa este componente de ser compilado pelo React Compiler
// ...
}
Quando você fizer com que o erro desapareça, confirme que a remoção da diretiva de exclusão faz com que o problema volte. Em seguida, compartilhe um relatório de bug conosco (você pode tentar reduzi-lo a uma pequena reprodução ou, se for código de código aberto, também pode colar a fonte inteira) usando o React Compiler Playground para que possamos identificar e ajudar a corrigir o problema.
Outros problemas
Consulte https://github.com/reactwg/react-compiler/discussions/7.