Depurar FiveM NUI: nui_devtools, erros de console e retornos de chamada falhados

Depure uma FiveM NUI: abra as ferramentas de desenvolvedor Chromium com nui_devtools, leia erros Uncaught TypeError, corrija uma busca falhada para https://resource/cb e teste a UI em um navegador.

Sua NUI abre como um painel em branco, um botão não faz nada, ou o cursor aparece e nenhuma tela segue. Geralmente não há erro de Lua, porque a falha está na página web. Você precisa do console do navegador, e FiveM tem um. Este guia cobre como abri-lo, como ler seus erros e como testar sua UI sem o jogo.

Abra as ferramentas de desenvolvedor: nui_devtools

NUI é uma página Chromium dentro do jogo. Pressione F8 para abrir o console FiveM e execute:

text
nui_devtools

Uma janela de ferramentas de desenvolvedor abre para a camada NUI, como a que você conhece de um navegador. Use estas abas:

  • Console: Erros JavaScript e suas próprias linhas console.log.
  • Network: toda requisição que a página faz, incluindo os retornos de chamada para Lua.
  • Elements: o HTML e CSS ao vivo. Use-o para ver se seu elemento existe, qual é seu tamanho e se está oculto.
  • Sources: defina pontos de interrupção em seu script.

Atenção: se nui_devtools está disponível depende de suas configurações e da compilação do cliente que você executa. Se o comando não fizer nada, verifique se seu cliente do jogo está atualizado, e teste a UI em um navegador normal como mostrado abaixo.

Se sua UI é visível apenas após um SendNUIMessage, abra as ferramentas de desenvolvedor primeiro e dispare a ação depois, para que você veja as mensagens que chegam.

Leia os erros do console

Erros na aba Console mostram o arquivo e a linha do seu script. Os que você verá mais frequentemente:

text
Uncaught TypeError: Cannot read properties of undefined (reading 'items')

Seu código leu .items em algo que é undefined. Em NUI isso quase sempre vem da mensagem:

js
window.addEventListener('message', (event) => {
  const { action, data } = event.data
  if (action === 'open') {
    render(data.items)   // data is undefined
  }
})

Verifique o que Lua realmente enviou. Imprima a mensagem inteira primeiro:

js
window.addEventListener('message', (event) => {
  console.log('NUI message', JSON.stringify(event.data))
})

Depois compare com a chamada Lua:

lua
SendNUIMessage({ action = 'open', data = { items = items } })

As chaves devem corresponder exatamente, incluindo maiúsculas e minúsculas. Um campo definido como nil em Lua está faltando na mensagem, então é undefined em JavaScript.

Outros erros comuns:

Mensagem do console Causa usual
Uncaught ReferenceError: x is not defined Um arquivo de script não carregou, ou um erro de digitação em um nome
Uncaught SyntaxError Um arquivo de script quebrado, ou uma saída do bundler com o caminho errado
Failed to load resource: 404 Um arquivo não está listado em files no fxmanifest, ou o caminho está errado
Uncaught (in promise) TypeError: Failed to fetch Uma solicitação de retorno de chamada falhou, veja abaixo

Se a aba Network mostrar um 404 para seu JS, CSS ou imagens, adicione cada arquivo que a página carrega a files no manifesto, e aponte ui_page para o HTML correto:

lua
ui_page 'web/index.html'

files {
  'web/index.html',
  'web/**/*',
}

Para uma compilação Vite ou React, use a pasta de saída, veja FiveM NUI with React and Vite.

Busca falhada para https://resource/cb

NUI envia mensagens para Lua com uma solicitação para https://<resource name>/<callback name>:

js
fetch(`https://${GetParentResourceName()}/close`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({}),
})

Na aba Network uma solicitação falhada mostra em vermelho:

text
POST https://my_script/close net::ERR_FAILED

Verifique isto em ordem:

  1. O retorno de chamada não está registrado. O nome após a barra deve corresponder a um RegisterNUICallback no cliente, exatamente:
lua
RegisterNUICallback('close', function(data, cb)
    SetNuiFocus(false, false)
    cb('ok')
end)
  1. O nome do recurso está errado. O host na URL é o nome da pasta do recurso. Se você renomeou a pasta, um https://old_name/close codificado falha. Use GetParentResourceName() na página, como acima, para que o nome siga a pasta.
  2. O retorno de chamada nunca responde. Sempre chame cb(...), mesmo com cb('ok'). Um manipulador que retorna sem chamá-lo deixa a solicitação pendente, e a página pode esperar para sempre.
  3. O manipulador Lua erra antes de cb. Verifique o console F8 para um erro de script no mesmo momento. Um erro antes de cb significa que a resposta nunca é enviada.
  4. O recurso não está em execução. Retornos de chamada vivem enquanto o script do cliente que os registrou estiver em execução.

Foco e o cursor

Se a UI mostra mas não pode ser clicada, ou o mouse fica preso após fechar, o problema é SetNuiFocus, não a página. Veja NUI focus stuck cursor.

Teste a UI em um navegador normal

Depurar no jogo é lento. A maior parte de uma NUI pode ser testada em um navegador, com o recarregamento ao vivo do seu editor.

Abra index.html através de um servidor local, ou execute npm run dev para um projeto Vite. Depois simule as duas coisas que o jogo normalmente fornece.

Primeiro, um falso GetParentResourceName e retornos de chamada que não falham:

js
if (!window.GetParentResourceName) {
  window.GetParentResourceName = () => 'my_script'
  window.fetch = async (url, options) => {
    console.log('NUI callback', url, options && options.body)
    return { ok: true, json: async () => ({}) }
  }
}

Segundo, envie as mensagens que Lua enviaria. Do console do navegador, ou um botão apenas para desenvolvimento:

js
window.postMessage({ action: 'open', data: { items: [{ name: 'water', count: 3 }] } }, '*')

Isto chama seu listener message exatamente como SendNUIMessage faz. Você pode projetar, corrigir layout e verificar tratamento de dados no navegador, e manter o jogo para a verificação final de foco, dados reais e retornos de chamada reais.

Dica: remova as simulações da compilação de produção, ou envolva-as para que só funcionem quando a página é aberta fora do jogo, como acima com o if em GetParentResourceName.

Lista de verificação

Sintoma Solução
NUI em branco Abra nui_devtools, leia as abas Console e Network
nui_devtools não faz nada Atualize o cliente e verifique suas configurações; teste em um navegador normal
Uncaught TypeError ... of undefined Registre event.data e corresponda as chaves enviadas por SendNUIMessage
404 para um arquivo Liste-o em files e verifique ui_page
POST https://resource/name falha Registre o retorno de chamada com RegisterNUICallback e use o nome exato
Nome do recurso errado na URL Use GetParentResourceName()
Botão funciona, nada acontece em Lua Certifique-se de que o retorno de chamada chama cb('ok')
Cursor preso após fechar Chame SetNuiFocus(false, false)

Respostas rápidas

Como abro as ferramentas de desenvolvedor para uma NUI FiveM?

Abra o console F8 no jogo e execute nui_devtools. Uma janela de ferramentas de desenvolvedor Chromium abre para a camada NUI. A disponibilidade pode depender de suas configurações e compilação do cliente.

Por que meu retorno de chamada NUI falha?

A solicitação para https://resource_name/callback não alcançou Lua. O retorno de chamada não está registrado com RegisterNUICallback, o nome do recurso na URL está errado, ou o retorno de chamada nunca responde com cb.

Posso testar minha NUI sem iniciar o jogo?

Sim. Abra a página em um navegador normal ou execute o servidor de desenvolvimento Vite, envie mensagens falsas com window.postMessage e simule os retornos de chamada. Apenas o jogo real lhe dá foco, dados reais e retornos de chamada reais.

Scripts sem esse problema

Mic PhoneUm celular dobrável que abre em tablet e chega ao celular de verdade do jogador.Ver script →Arcade MachinesSete jogos de fliperama jogáveis em máquinas de verdade, com rankings e apostas.Ver script →CCTV Security CamerasCâmeras posicionáveis, um tablet com várias telas ao vivo e fotos impressas como prova.Ver script →

Continue lendo