Perguntas frequentes & guia de troubleshooting
Aqui reunimos as armadilhas mais comuns no desenvolvimento de plugins do cliente. Se você se deparou com aquela situação de "está tudo certo, mas não funciona", procure aqui antes.
Plugin
Plugin criado, mas não aparece no gerenciador
Confirme que você executou yarn pm create e não criou o diretório manualmente. Além de gerar os arquivos, yarn pm create registra o plugin na tabela applicationPlugins do banco de dados. Se você criou o diretório manualmente, execute yarn nocobase upgrade para reescaneá-los.
Plugin ativado, mas a página não muda
Verifique na seguinte ordem:
- Confirme que executou
yarn pm enable <pluginName> - Atualize o navegador (às vezes é preciso um hard reload
Ctrl+Shift+R) - Verifique se há erros no console do navegador
Alterei o código, mas a página não atualiza
O comportamento de hot reload varia conforme o tipo de arquivo:
Se você alterou código do cliente mas não houve hot reload, primeiro tente atualizar o navegador.
Rotas
Rota de página registrada não acessível
As rotas no NocoBase v2 recebem o prefixo /v por padrão. Por exemplo, se você registrou path: '/hello', o endereço de acesso real é /v/hello:
Veja Router de rotas para detalhes.
Página de configurações de plugin abre em branco
Se o menu da página de configurações apareceu mas o conteúdo está vazio, geralmente é uma das duas razões:
Razão 1: client v1 usou componentLoader
componentLoader é uma forma do client-v2; o client v1 deve usar Component passando o componente diretamente:
Razão 2: o componente da página não usa export default
componentLoader exige que o módulo tenha export default; faltou default e o módulo não será carregado.
Blocos
Bloco personalizado não aparece no menu "Adicionar bloco"
Confirme que registrou o modelo em load():
Se estiver usando registerModels (forma sem carregamento sob demanda), confirme que models/index.ts exporta o modelo corretamente.
Após adicionar o bloco, minha tabela não aparece na lista de seleção de data tables
Tabelas definidas via defineCollection são tabelas internas do servidor; por padrão, não aparecem na lista de data tables da UI.
Abordagem recomendada: na interface do NocoBase, em "Gerenciamento de fontes de dados", adicione a data table correspondente; após configurar campos e tipos de interface, a tabela aparece automaticamente na lista de seleção de data tables do bloco.
Se realmente precisar registrá-la no código do plugin (como em cenários de demonstração de plugins de exemplo), use addCollection para registrar manualmente; veja Construir um plugin de gestão de dados com integração front-back para detalhes. Atenção: deve ser registrado pelo padrão de eventBus; chamá-lo diretamente em load() não funciona — ensureLoaded() é executado após load() e limpa e reconfigura todas as collections.
Quero que meu bloco personalizado se vincule apenas a uma data table específica
Sobrescreva static filterCollection no modelo; apenas as collections em que o retorno for true aparecem na lista:
Campos
Componente de campo personalizado não aparece no menu suspenso "Componente de campo"
Verifique na seguinte ordem:
- Confirme que chamou
DisplayItemModel.bindModelToInterface('ModelName', ['input']), com o tipo de interface combinando — por exemplo,inputpara campo de texto de linha única,checkboxpara checkbox - Confirme que o modelo está registrado em
load()(registerModelsouregisterModelLoaders) - Confirme que o modelo de campo chama
define({ label })
O menu suspenso "Componente de campo" mostra o nome da classe
Você esqueceu de chamar define({ label }) no modelo de campo; basta adicionar:
Garanta também que existe a chave correspondente nos arquivos de tradução em src/locale/; caso contrário, em ambiente em chinês, o texto em inglês ainda será exibido.
Ações
Botão de ação personalizado não aparece em "Configurar ações"
Confirme que o static scene correto está definido no modelo:
Clico no botão de ação e nada acontece
Confirme que on em registerFlow está definido como 'click':
O uiSchema em registerFlow é a UI do painel de configuração (estado de configuração), não uma modal em tempo de execução. Se você quer abrir um formulário ao clicar no botão, use ctx.viewer.dialog() dentro do handler para abrir a modal.
Internacionalização
A tradução não funciona
Causas mais comuns:
- Primeira vez adicionando o diretório
src/locale/ou um arquivo — é preciso reiniciar a aplicação - Chave de tradução inconsistente — confirme que a chave coincide exatamente com a string no código, atenção a espaços e maiúsculas/minúsculas
- Em componentes, está usando
ctx.t()diretamente —ctx.t()não injeta automaticamente o namespace do plugin; em componentes, use o hookuseT()(importado delocale.ts)
Confusão entre tExpr(), useT() e this.t()
Esses três métodos de tradução têm cenários diferentes; usá-los no lugar errado dá erro ou tradução sem efeito:
Veja i18n internacionalização para detalhes.
Requisições de API
Requisição retorna 403 Forbidden
Geralmente o ACL no servidor não foi configurado. Por exemplo, se a sua collection é todoItems, é preciso permitir as ações correspondentes em load() no plugin do servidor:
'loggedIn' indica que usuários logados podem acessar. Sem acl.allow, por padrão, somente administradores podem operar.
Requisição retorna 404 Not Found
Verifique na seguinte ordem:
- Se estiver usando
defineCollection, confirme que o nome da collection está escrito corretamente - Se estiver usando
resourceManager.define, confirme o nome do resource e da action - Confira o formato da URL — o formato da API do NocoBase é
resourceName:actionName, por exemplotodoItems:list,externalApi:get
Build e deploy
yarn build --tar falha com "no paths specified to add to archive"
Ao executar yarn build <pluginName> --tar, ocorre o erro:
Mas executando yarn build <pluginName> (sem --tar) funciona normalmente.
Esse problema costuma acontecer porque o .npmignore do plugin usa sintaxe negativa (prefixo ! do npm). Ao empacotar com --tar, o NocoBase lê cada linha do .npmignore e prefixa com ! para converter em padrões de exclusão do fast-glob. Se o seu .npmignore já usa sintaxe negativa, por exemplo:
após o processamento vira ['!*', '!!dist', '!!package.json', '**/*']. Aqui, !* exclui todos os arquivos do nível raiz (incluindo package.json), e !!dist não é interpretado pelo fast-glob como "reincluir dist" — a negação não funciona. Se o diretório dist/ estiver vazio ou se o build não produzir arquivos, a lista final coletada fica vazia, e o tar lança esse erro.
Solução: não use sintaxe negativa no .npmignore; liste apenas os diretórios a excluir:
A lógica de empacotamento converte isso em padrões de exclusão (!./node_modules, !./src) e adiciona **/* para casar com todos os outros arquivos. É simples e evita os problemas com a negação.
Plugin enviado para produção falha ao ativar (funciona localmente)
Em desenvolvimento local o plugin funciona, mas após enviar para produção pelo "Gerenciador de plugins" e ativá-lo, o log mostra um erro como:
Esse problema costuma ocorrer porque o plugin empacotou dependências internas do NocoBase em seu próprio node_modules/. O sistema de build do NocoBase mantém uma lista external; pacotes nessa lista (como react, antd, axios, lodash etc.) são fornecidos pelo host do NocoBase e não devem ser empacotados no plugin. Se o plugin trouxer uma cópia privada, em tempo de execução pode haver conflito com a versão já carregada pelo host, causando erros estranhos.
Por que localmente funciona: durante o desenvolvimento local, o plugin está em packages/plugins/ sem node_modules/ privado; as dependências são resolvidas para a versão já carregada na raiz do projeto, sem conflito.
Solução: mova as dependencies do package.json do plugin para devDependencies — o sistema de build do NocoBase trata as dependências do plugin automaticamente:
Em seguida, reconstrua e empacote. Assim, dist/node_modules/ do plugin não conterá esses pacotes, e em tempo de execução será usada a versão fornecida pelo host do NocoBase.
O sistema de build do NocoBase mantém uma lista external; pacotes nessa lista (como react, antd, axios, lodash etc.) são fornecidos pelo host do NocoBase e não devem ser empacotados pelo plugin. Todas as dependências do plugin devem ficar em devDependencies; o sistema de build decide automaticamente quais empacotar em dist/node_modules/ e quais ficam por conta do host.
Links relacionados
- Plugin — entrada do plugin e ciclo de vida
- Router de rotas — registro de rotas e prefixo
/v - Visão geral do FlowEngine — uso básico do FlowModel
- FlowEngine → Extensão de blocos — BlockModel, TableBlockModel, filterCollection
- FlowEngine → Extensão de campos — FieldModel, bindModelToInterface
- FlowEngine → Extensão de ações — ActionModel, ActionSceneEnum
- i18n internacionalização — arquivos de tradução, useT, uso de tExpr
- Context → Capacidades comuns — ctx.api, ctx.viewer etc.
- Server → Collections — defineCollection e addCollection
- Server → Controle de permissões ACL — configuração de permissões de API
- Build de plugin — configuração de build, lista external, fluxo de empacotamento

