Keycloak React Admin UI开发模式启动遇404问题求助
我想自定义修改Keycloak的admin-ui,但在开发模式下运行项目时遇到问题:
- 先在
keycloak-26.4.2/bin目录执行kc.bat start-dev启动Keycloak后端 - 进入
keycloak-main/js/apps/admin-ui目录运行pnpm run dev,Vite提示服务就绪:
VITE v7.1.10 ready in 2182 ms ➜ Local: http://localhost:5174/ ➜ Network: http://192.168.61.12:5174/
但直接访问localhost:5174时出现404错误,请求信息:
Request URL http://localhost:5174/ Request Method GET Status Code 404 Not Found Remote Address [::1]:5174 Referrer Policy strict-origin-when-cross-origin
环境信息:Keycloak v26.4.2、Node v22.21.0
相关配置文件
admin-ui/package.json
{"name": "@keycloak/keycloak-admin-ui","version": "999.0.0-SNAPSHOT","type": "module","main": "lib/keycloak-admin-ui.js","types": "./lib/keycloak-admin-ui.d.ts","exports": {".": {"import": "./lib/keycloak-admin-ui.js","types": "./lib/keycloak-admin-ui.d.ts"}},"files": ["lib"],"publishConfig": {"access": "public"},"scripts": {"dev": "wireit","build": "wireit","build-lib": "wireit","preview": "wireit","lint": "wireit","test": "wireit","test:integration": "wireit"},"wireit": {"dev": {"command": "vite --host","dependencies": ["../../libs/ui-shared:build","../../libs/keycloak-admin-client:build"]},"preview": {"command": "vite preview","dependencies": ["../../libs/ui-shared:build","../../libs/keycloak-admin-client:build"]},"build": {"command": "vite build","dependencies": ["../../libs/ui-shared:build","../../libs/keycloak-admin-client:build"],"files": ["public","src","tsconfig.json","vite.config.ts"],"output": ["target/classes/theme/keycloak.v2/admin/resources"]},"build-lib": {"command": "cross-env LIB=true vite build","dependencies": ["../../libs/ui-shared:build","../../libs/keycloak-admin-client:build"]},"lint": {"command": "eslint .","dependencies": ["../../libs/ui-shared:build","../../libs/keycloak-admin-client:build"]},"test": {"command": "vitest","dependencies": ["../../libs/ui-shared:build","../../libs/keycloak-admin-client:build"]},"test:integration": {"command": "playwright test","dependencies": ["../../libs/keycloak-admin-client:build"]}},"dependencies": {"@dagrejs/dagre": "^1.1.5","@keycloak/keycloak-admin-client": "workspace:*","@keycloak/keycloak-ui-shared": "workspace:*","@patternfly/patternfly": "^5.4.2","@patternfly/react-core": "^5.4.14","@patternfly/react-icons": "^5.4.2","@patternfly/react-styles": "^5.4.1","@patternfly/react-table": "^5.4.16","@uiw/react-textarea-code-editor": "^3.1.1","admin-ui": "file:","file-saver": "^2.0.5","flat": "^6.0.1","i18next": "^25.6.0","i18next-fetch-backend": "^6.0.0","jszip": "^3.10.1","keycloak-js": "^26.2.0","lodash-es": "^4.17.21","p-debounce": "^5.0.0","react": "^18.3.1","react-dom": "^18.3.1","react-hook-form": "^7.63.0","react-i18next": "^16.0.1","react-router-dom": "^6.30.1","reactflow": "^11.11.4","use-react-router-breadcrumbs": "^4.0.1"},"devDependencies": {"@axe-core/playwright": "^4.10.2","@playwright/test": "^1.56.0","@testing-library/dom": "^10.4.1","@testing-library/jest-dom": "^6.9.1","@testing-library/react": "^16.3.0","@types/dagre": "^0.7.53","@types/file-saver": "^2.0.7","@types/lodash-es": "^4.17.12","@types/react": "^18.3.18","@types/react-dom": "^18.3.5","@vitejs/plugin-react-swc": "^4.1.0","cross-env": "^10.1.0","jsdom": "^27.0.0","lightningcss": "^1.30.2","properties-file": "^3.6.1","ts-node": "^10.9.2","uuid": "^13.0.0","vite": "^7.1.10","vite-plugin-checker": "^0.11.0","vite-plugin-dts": "^4.5.4","vitest": "^3.2.4"},"author": {"name": "Red Hat, Inc.","url": "https://www.keycloak.org/"},"license": "Apache-2.0","repository": {"type": "git","url": "https://github.com/keycloak/keycloak.git","directory": "js/apps/admin-ui"},"homepage": "https://www.keycloak.org/"}
admin-ui/vite.config.ts
import react from "@vitejs/plugin-react-swc";import { readFileSync } from "node:fs";import path from "path";import { getProperties } from "properties-file";import { defineConfig, loadEnv } from "vite";import { checker } from "vite-plugin-checker";import dts from "vite-plugin-dts";import { configDefaults } from "vitest/config"; // https://vitejs.dev/config/ export default defineConfig(({ mode }) => { const env = loadEnv(mode, process.cwd(), ""); const external = ["react", "react/jsx-runtime", "react-dom"]; const plugins = [ react(), checker({ typescript: true }), { name: "message-bundle-transformer", resolveId(source) { if (source === "message-bundle") { return source; } return null; }, load(id) { if (id === "message-bundle") { let properties = {}; if (process.env.NODE_ENV === "development") { properties = getProperties( readFileSync( "./maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties", ), ); } return { code: `export default ${JSON.stringify(properties)};`, }; } return null; }, }, ]; const input = env.LIB ? undefined : "src/main.tsx"; if (env.LIB) { external.push("react-router-dom"); external.push("react-i18next"); plugins.push(dts({ insertTypesEntry: true })); } const lib = env.LIB ? { outDir: "lib", lib: { entry: path.resolve(__dirname, "src/index.ts"), formats: ["es"], }, } : { outDir: "target/classes/theme/keycloak.v2/admin/resources", external: ["src/index.ts"], }; return { base: "", server: { origin: "http://localhost:5174", port: 5174, }, build: { ...lib, sourcemap: true, target: "esnext", modulePreload: false, cssMinify: "lightningcss", manifest: true, rollupOptions: { input, external, }, }, plugins, test: { watch: false, environment: "jsdom", exclude: [...configDefaults.exclude, "./test/**"], server: { deps: { inline: [/@patternfly\.*/], }, }, }, }; });
直接访问Vite的5174端口会404,因为Keycloak Admin UI依赖Keycloak后端的认证和路由代理,不能独立访问。正确的运行步骤如下:
确保依赖构建完成
在keycloak-main根目录执行pnpm install,安装所有依赖。然后进入js/apps/admin-ui目录运行pnpm run dev,此时Vite会自动构建依赖的ui-shared和keycloak-admin-client库,等待Vite提示服务就绪。修改Keycloak启动命令,指定开发UI的代理地址
停止之前运行的Keycloak后端,重新执行启动命令时添加--admin-ui-dev-url参数,指向Vite的开发服务器地址:kc.bat start-dev --admin-ui-dev-url=http://localhost:5174这个参数会让Keycloak将/admin路径的请求代理到Vite的开发服务器,同时处理认证流程。
通过Keycloak的Admin路径访问
不要直接访问localhost:5174,而是打开浏览器访问Keycloak的Admin页面:http://localhost:8080/admin(默认Keycloak端口是8080,如果修改过端口请对应调整)。此时Keycloak会自动代理到Vite的开发服务器,加载你本地的Admin UI代码,并且支持热更新。额外检查项
- 确认
vite.config.ts中的input配置在非LIB模式下为src/main.tsx,你的配置已经正确设置。 - 检查
maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties文件是否存在,Vite插件需要读取这个文件加载国际化信息,如果不存在可以从Keycloak的主题目录复制一份过来。
- 确认
内容的提问来源于stack exchange,提问作者inred

