Desde que comecei a estudar o Deno, tenho migrado meus projetos pessoais aos poucos para essa runtime. Isso não significa abandonar o Node.js ou fingir que ele deixou de ser importante. Boa parte do mercado de JavaScript ainda gira em torno dele, e entender esse ecossistema continua valendo muito.
Mas eu queria fazer um teste mais honesto: tirar o Node.js da máquina e ver até onde a compatibilidade do Deno com pacotes npm: chegava sozinha. Foi aí, em um projeto com Next.js, Turbopack, Tailwind CSS e PostCSS, que apareceu um erro bem específico.
O projeto iniciava, o servidor de desenvolvimento subia, mas ao abrir a página inicial o Next.js quebrava com um erro fatal do Turbopack.
O detalhe curioso é que a resposta estava na própria documentação do Deno, só que não na página que eu tinha seguido primeiro.
Quando eu seguia apenas a página geral de Web development do Deno, eu criava uma aplicação Next.js que parecia correta, mas ainda podia cair no erro do Turbopack. Já o tutorial específico Build a Next.js App traz uma etapa a mais: configurar a chave unstable no deno.json antes de instalar as dependências. Com esse ajuste, o Next.js rodou normalmente no Deno, sem a flag experimental do Next.js.
No meu caso, a primeira versão testada foi o Next.js 16.1.6. Nessa versão, o caminho com unstable no deno.json já fazia a aplicação funcionar; eu só ainda não tinha seguido essa parte da documentação. O workaround com a flag experimental do Turbopack só entrou depois, quando atualizei o Next.js para 16.2.9. Mesmo nessa versão mais nova, porém, o caminho com unstable continua sendo suficiente para uma aplicação nova.
O erro
O erro que aparecia no terminal era algo parecido com isto:
FATAL: An unexpected Turbopack error occurred.
A panic log has been written to /tmp/next-panic-49160c9dd04e97c5b07ba4f139aa8086.log
Dentro do arquivo de log, a parte importante era esta:
Failed to write app endpoint /page
Caused by:
- [project]/src/app/globals.css [app-client] (css)
- creating new process
- spawning node pooled process
- No such file or directory (os error 2)
O problema não estava no componente React da página. Ele aparecia antes, quando o Turbopack tentava processar o globals.css, passando por Tailwind CSS e PostCSS.
A pista principal era esta linha:
spawning node pooled process
Mesmo com o Next.js sendo iniciado pelo Deno, alguma parte do pipeline do Turbopack estava tentando criar um processo separado chamado node. Como eu estava justamente em um ambiente sem Node.js instalado, esse processo não era encontrado.
Por que eu não tinha Node.js instalado?
Foi proposital.
Eu queria entender até onde a compatibilidade do Deno funcionava sem que algum comando caísse silenciosamente no Node.js. Se o Node.js estivesse instalado, o erro talvez passasse despercebido, porque o Turbopack conseguiria chamar o executável node.
Sem Node.js, a falha ficou explícita.
Isso também explica por que o erro pode parecer raro: muita gente usa Deno em uma máquina onde Node.js também está instalado. Nesse caso, o problema pode não aparecer.
Como reproduzir do zero
Vou deixar o passo a passo inteiro aqui para não depender de abrir três abas de documentação só para reproduzir o cenário.
Os comandos abaixo foram pensados para um ambiente Linux ou WSL. Também deixei uma opção para Windows com PowerShell.
1. Instale o Deno
curl -fsSL https://deno.land/install.sh | sh
No Windows, usando PowerShell:
irm https://deno.land/install.ps1 | iex
Confirme a instalação:
deno --version
Você deve ver algo parecido com:
deno 2.x.x
v8 ...
typescript ...
2. Crie uma aplicação Next.js usando o tutorial específico do Deno
Em vez de montar a aplicação manualmente, vamos usar o próprio create-next-app, executado pelo Deno através de um pacote npm:.
Na página geral de Web development, a seção React/Next mostra um fluxo curto: criar o projeto, entrar na pasta e rodar deno task dev. Foi seguindo esse tipo de caminho direto que eu bati no problema.
O tutorial específico Build a Next.js App é mais completo. Ele cria a aplicação com o create-next-app, mas também orienta a ajustar o deno.json antes de instalar as dependências. Esse detalhe muda o resultado.
Crie a aplicação assim:
deno run -A npm:create-next-app@latest my-next-app
O -A libera as permissões necessárias para o comando criar o projeto, baixar pacotes e preparar a estrutura inicial.
Essas foram as opções que usei no create-next-app:
Would you like to use the recommended Next.js defaults? No, customize settings
Would you like to use TypeScript? Yes
Which linter would you like to use? None
Would you like to use React Compiler? No
Would you like to use Tailwind CSS? Yes
Would you like your code inside a `src/` directory? Yes
Would you like to use App Router? Yes
Would you like to customize the import alias? No
Depois entre na pasta criada:
cd my-next-app
Depois disso, você já terá a estrutura básica do Next.js, incluindo package.json, src/app/layout.tsx, src/app/page.tsx e src/app/globals.css.
3. Ajuste o deno.json antes de instalar as dependências
Esta é a etapa que faltou no caminho mais curto da página geral de web dev. Antes de rodar deno install, crie ou ajuste o arquivo deno.json na raiz do projeto:
{
"unstable": [
"detect-cjs",
"node-globals",
"unsafe-proto",
"sloppy-imports"
]
}
Essa chave unstable é recomendada pelo tutorial específico de Next.js no Deno. Ela melhora a compatibilidade com dependências que ainda usam CommonJS, globais do Node.js, Object.prototype.__proto__ e alguns imports menos rígidos.
Na prática, essas flags deixam o ambiente do Deno mais próximo do que o Next.js e parte do ecossistema npm ainda esperam encontrar durante o desenvolvimento e o build.
Agora instale as dependências liberando scripts de instalação:
deno install --allow-scripts
Alguns pacotes do ecossistema do Next.js precisam executar scripts durante a instalação. Por isso, neste passo, liberamos esses scripts explicitamente no comando em vez de manter essa permissão fixa no deno.json.
4. Rode o servidor de desenvolvimento
Agora rode:
deno task dev
Abra:
http://localhost:3000
Seguindo esse fluxo completo do tutorial específico, com o bloco unstable no deno.json, o Next.js deve iniciar normalmente no Deno, inclusive em uma máquina sem Node.js instalado.
O erro fatal do Turbopack apareceu para mim quando o projeto foi criado seguindo apenas o caminho resumido da página geral de web dev, sem essa configuração de compatibilidade no deno.json.
O caminho que eu seguiria hoje
Para uma aplicação nova, eu começaria pelo tutorial específico de Next.js no Deno e configuraria o deno.json antes de instalar as dependências:
{
"unstable": [
"detect-cjs",
"node-globals",
"unsafe-proto",
"sloppy-imports"
]
}
Depois disso:
deno install --allow-scripts
deno task dev
Esse é o caminho que eu recomendaria hoje. Ele resolve o problema no lugar certo: a aplicação passa a rodar no Deno com as compatibilidades que o Next.js precisa atualmente.
O workaround que encontrei durante a investigação
Antes de perceber a diferença entre as duas páginas da documentação do Deno, eu cheguei por outro caminho: trocar a estratégia de execução dos plugins do Turbopack.
No meu teste inicial, o problema apareceu usando [email protected]. Essa versão não tinha a configuração experimental necessária para trocar a estratégia de runtime dos plugins do Turbopack. Porém, ela funciona normalmente quando o projeto é configurado com o bloco unstable no deno.json.
O workaround com turbopackPluginRuntimeStrategy só ficou disponível depois de atualizar para [email protected]. Nessa versão, a flag ajuda a entender e contornar o problema, mas o fluxo correto com unstable também funciona sem ela.
Se você já tem um projeto quebrando com o erro spawning node pooled process e não consegue resolver apenas com o unstable no deno.json, esse workaround pode ajudar. Primeiro, atualize o Next.js:
deno add [email protected] [email protected] [email protected]
Depois adicione a configuração experimental no next.config.ts:
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
experimental: {
turbopackPluginRuntimeStrategy: "workerThreads",
},
};
export default nextConfig;
Depois de salvar o arquivo, pare o servidor e rode novamente:
deno task dev
No meu caso, depois dessa alteração, a rota / retornou 200 OK.
Mas vale reforçar: para uma aplicação nova, eu começaria pelo ajuste do deno.json indicado no tutorial específico do Deno. A flag experimental do Next.js fica mais como ferramenta de diagnóstico ou como saída para um projeto que já entrou nesse estado.
Por que isso funciona?
O nome da flag não ajuda muito:
turbopackPluginRuntimeStrategy;
Mas a ideia por trás dela é simples.
O Turbopack precisa executar trabalhos de plugins e loaders. Isso inclui coisas como processar CSS, rodar PostCSS, aplicar Tailwind CSS e resolver partes do pipeline de build.
Por padrão, a estratégia usada era:
turbopackPluginRuntimeStrategy: "childProcesses";
Um child process é um processo separado. Nesse caso, o Turbopack tentava iniciar um processo Node.js separado para executar parte desse trabalho.
O problema é que eu não tinha Node.js instalado.
Quando trocamos para:
turbopackPluginRuntimeStrategy: "workerThreads";
o Turbopack deixa de depender desse processo externo chamado node para esse tipo de execução e passa a usar worker threads.
No meu caso, a diferença importante era esta:
Node.js.
separado.
childProcesses: tentava criar outro processo, e esse processo esperavaworkerThreads: executava esse trabalho sem procurar um executávelnode
Por isso a aplicação continua rodando pelo Deno, mas sem quebrar no momento em que o Turbopack processa o CSS.
Onde essa opção aparece no código do Next.js?
A referência que usei está no código-fonte do Next.js:
Ali aparece a configuração experimental relacionada ao runtime usado pelo Turbopack para executar plugins.
Também vale olhar a documentação oficial do Turbopack:
Um detalhe importante
Essa não é uma solução de "instale mais um pacote". Também não é um plugin externo.
É uma configuração do próprio Next.js. O termo "plugin runtime" aqui fala do modo como o Turbopack executa internamente plugins e loaders, como PostCSS e Tailwind CSS.
Conclusão
Eu comecei esse teste querendo entender se o Deno realmente conseguiria rodar um projeto Next.js sem depender do Node.js instalado na máquina.
A resposta curta é: sim, consegue. Só que o passo a passo importa.
Se você seguir apenas a página geral de web development do Deno, pode acabar com uma aplicação Next.js criada corretamente, mas sem as configurações de compatibilidade que o tutorial específico de Next.js recomenda. Foi aí que eu me deparei com o erro fatal do Turbopack.
A correção mais limpa para uma aplicação nova é configurar o unstable no deno.json antes de instalar as dependências e rodar deno install --allow-scripts. A flag experimental turbopackPluginRuntimeStrategy: "workerThreads" continua sendo uma descoberta útil na versão 16.2.9, especialmente para entender por que o erro acontecia e para destravar projetos que já estão quebrando nesse ponto.
No fim, o aprendizado não foi só sobre uma flag. Foi sobre escolher a página certa da documentação para o nível de detalhe que o framework exige. A página geral dá o caminho rápido. O tutorial específico entrega a parte que faz o Next.js rodar bem no Deno hoje.
Referências
- Deno
- Instalação do Deno
- Deno com APIs e pacotes Node/npm
- Web development no Deno
- Tutorial oficial: Build a Next.js App com Deno
- Next.js
- Turbopack no Next.js
- Config experimental no código do Next.js
- React
- Tailwind CSS
- PostCSS
- Node.js
- JavaScript
- TypeScript
- Linux
- macOS
- Windows
- PowerShell
- npm
- pnpm
- Yarn
- Bun
- Worker threads no Node.js
- Child process no Node.js
- WSL

