配置与 CLI
karin.template.ts 的全部配置项,以及 ktr create / init / sync / dev / build 命令的用法
配置文件 karin.template.ts
放在项目根目录,只配置工具链自身行为;模板、mock、JSON 数据按 ktr/template/ 约定自动发现,不要手写模板清单。按 .ts → .mts → .js → .mjs 顺序查找,取第一个存在的:
import { } from '@karinjs/template-react'
export default ({
: {
: 5180,
: true
}
})合并优先级:CLI 命令行覆盖 > karin.template.ts > 内置默认值。
配置项一览
顶层字段(由源码 JSDoc 自动生成):
Prop
Type
dir 目录配置:
Prop
Type
dev 开发面板配置:
Prop
Type
配置项实际使用场景
dir.template
场景:调整模板目录位置,适配现有项目结构。
export default ({
: {
: 'src/templates' // 使用 src/templates 代替 ktr/template
}
})修改后,模板文件从 src/templates/<板块>/<模板>/index.tsx 读取,style.css 从 src/templates/style.css 读取。
dir.assets
场景:存放字体、图标、背景图等静态资源。
export default ({
: {
: 'public' // 使用项目根的 public/ 目录
}
})模板中引用资源:
<img src="/assets/avatar.png" alt="头像" />引用约定只有一条:/ 开头的路径始终等于 <dir.assets>/ 下的相对路径(上例即 public/assets/avatar.png)。这条不变量在三种环境下由不同机制保证,模板写法不用变:
- 开发:
ktr dev把dir.assets作为 publicDir 挂在根路径,引用直接可访问; - 构建:
ktrBuildPlugin/ktr build把dir.assets原样复制到<产物目录>/assets/,目录结构不变; - 渲染:SSR 产出 HTML 时框架自动改写这些引用——资源根目录开发态取
dir.assets、生产态自动发现产物里的assets/(与 chunk 落点无关,单 chunk 打包也不影响),不超过html.assetsInlineLimit的内联为 base64,超过的转为file://绝对路径,截图引擎用file://打开也能正确加载。
dir.copyAssets
场景:资源目录已随 npm 包发布,构建时避免重复复制。
export default ({
: {
: false // 不复制资源,假设 ktr/public 已在 package.json files 中
}
})适用于资源体积大、或资源目录本身就在产物目录的场景。设为 false 时构建会在产物根额外生成一份 ktr-assets.json 位置清单,渲染时据此定位随包发布的资源目录(无需随包发布 karin.template.ts)——包里始终只有一份资源,模板里的 /xxx 引用照常工作。
dir.cssEntry
场景:自定义 Tailwind CSS 入口位置,或使用多个样式文件。
export default ({
: {
: 'src/styles/main.css' // 自定义入口
}
})main.css 内容示例:
@import 'tailwindcss';
@import './custom-utilities.css';extraStylePaths
场景:注入字体、图标库、自定义 CSS 到 SSR HTML。
export default ({
: ['ktr/public/fonts.css', 'ktr/public/icons.css']
})这些文件会在渲染时内联到 HTML 的 <style> 标签中,确保截图包含完整样式。
dev.port
场景:端口冲突时固定使用特定端口,或多个项目同时开发。
export default ({
: {
: 3000 // 使用 3000 端口,被占用时自动尝试 3001、3002...
}
})dev.host
场景:局域网内其他设备访问开发面板(手机预览、多屏调试)。
export default ({
: {
: '0.0.0.0' // 监听所有网络接口
}
})启动后可通过局域网 IP 访问,如 http://192.168.1.100:5180。
dev.open
场景:CI 环境或无头服务器启动时不打开浏览器。
export default ({
: {
: false // 启动后不自动打开浏览器
}
})或通过命令行覆盖:
pnpm ktr dev --no-openhtml.headExtra
场景:注入 Google Fonts、外部脚本、meta 标签到 SSR HTML。
export default ({
: {
: `
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
<meta name="author" content="Karin Team">
`
}
})所有 SSR HTML 都会包含这些内容。
headExtra 注入的内容在截图时不会生效(无网络请求),仅用于开发面板预览。字体等资源应使用 extraStylePaths 内联。
html.assetsInlineLimit
类型:number | ((filePath: string) => boolean),默认:4096
模板标记里本地资源引用(<img src="/..."> 等,对应 <dir.assets>/ 下的文件)的内联阈值,语义同 Vite 的 assetsInlineLimit:SSR 产出 HTML 时,不超过阈值(字节)的资源内联为 base64 data URI,超过的转为 file:// 绝对路径;函数形式按文件自行决定是否内联。
export default ({
: {
// 全部内联,产出的 HTML 完全自包含
: 100 * 1024 * 1024
}
})ktr build)的运行包无法序列化函数形式,函数会回退为默认的 4096(构建期有警告提示)。standalone 独立构建
standalone 用于不希望维护 Vite 或 tsdown 生产入口的项目。ktr build 会扫描所有 index.tsx 模板,严格检查数据类型,并生成可被 Node ESM 直接导入的运行包。
import { defineConfig } from '@karinjs/template-react'
export default defineConfig({
standalone: {
outDir: 'dist/ktr',
target: 'node18',
format: 'esm',
minify: false,
sourcemap: false,
assets: 'copy',
external: [],
singleChunk: true
}
})字段说明:outDir 是产物目录;target 是 Node 语法目标;第一阶段 format 固定为 esm;assets: 'copy' 将 ktr/public/ 复制到产物的 assets/;external 是允许保留为运行时依赖的包名;singleChunk 默认要求只有一个 JavaScript chunk。
不可配置的固定位置:框架缓存强制为项目根的 .ktr/;mock 数据固定在各模板自己的 data/ 子目录。独立构建的产物目录由 standalone.outDir 控制;使用 ktrBuildPlugin 的 npm 模式则继续跟随打包器的 outDir。
vite 扩展配置
export default ({
: {
: { : { '@': '/src' } }
}
})普通的 Vite 配置对象,直接合并。
这个字段扩展的是 ktr 自己的 Vite 管线(开发面板服务器、模板 CSS 的独立构建)。模板 CSS 的静态资源内联阈值
(build.assetsInlineLimit)、PostCSS 插件等影响 CSS 内容的选项都在这里配置;下游自身打包用的 vite.config.ts
不影响模板 CSS 的内容,只决定产物落盘位置(CSS 作为 bundle asset 跟随打包器 outDir)。
CLI 命令
安装 @karinjs/template-react 后通过 pnpm ktr <命令> 调用;init 和 create 也可以在装包前用 npx @karinjs/template-react <命令> 直接跑。
ktr create
npx @karinjs/template-react create <项目名>从零新建模板项目:建目录、写 package.json 和 tsconfig.json,然后走与 init 相同的问答。目标目录已存在且非空时报错退出。
ktr init
npx @karinjs/template-react init在已有的 Karin 插件项目里初始化。交互问答四项:样式方案(默认继承 HeroUI 主题,或额外生成带注释的主题变量块)、是否生成示例模板(官方 7 个)、是否生成 src/utils/render.ts 胶水层、开发面板端口。
产出:karin.template.ts、ktr/template/style.css、可选的示例模板与胶水层;给 tsconfig.json 补 jsx: "react-jsx";给 package.json 补开发依赖和 template 脚本。已存在的依赖版本和同名脚本一律保留;文件名冲突时先列出清单再问是否覆盖。
create 和 init 需要真实终端——单选框靠逐键读取 stdin,用管道或重定向喂输入会直接报错。ktr sync
pnpm ktr sync扫描 ktr/template/,生成或刷新 .ktr/ 三个产物(模板注册表、mock 注册表、类型增强声明)。新增、删除、移动模板或 mock 之后跑;挂了 ktrBuildPlugin() 的打包会自动同步,不用单独跑。
ktr dev
pnpm ktr dev --port 5180 --host localhost --no-open启动开发面板(先自动执行一次 sync)。选项 --port / --host / --open / --no-open 只覆盖 dev 子配置,其余仍读配置文件。端口被占用时自动换端口,并在启动详情里打印占用进程(名称 + PID)和释放命令。
使用场景
场景 1:快速预览模板
pnpm ktr dev自动打开浏览器,访问 http://localhost:5180,左侧选择模板,右侧实时预览。
场景 2:多设备调试
pnpm ktr dev --host 0.0.0.0局域网内其他设备通过 IP 访问(如 http://192.168.1.100:5180),适合手机预览、多屏对比。
场景 3:端口冲突处理
pnpm ktr dev --port 3000指定端口,被占用时自动尝试下一个可用端口(3001、3002...),并在终端打印:
⚠ 端口 3000 已被占用,已自动切换到 3001
占用进程:node(12345)
要释放原端口,可执行:
kill -9 12345场景 4:CI 环境或无头服务器
pnpm ktr dev --no-open启动面板但不打开浏览器,适合远程开发或 CI 流水线中的预览环境。
场景 5:热更新开发流程
- 修改
ktr/template/hello/card/index.tsx组件代码 - 保存后浏览器自动刷新,立即看到效果
- 修改
ktr/template/hello/card/mock.ts的 mock 数据 - 保存后自动重新渲染,无需手动刷新
ktr build
pnpm ktr build独立构建会执行模板扫描、.ktr 注册、严格 TypeScript 检查、Tailwind CSS 编译和 Node ESM 打包。默认产物为:
dist/ktr/
├── index.mjs # 运行时入口,包含 React、SSR runtime、模板和内嵌 CSS
├── index.d.mts # 路由与 data 的精确声明
└── assets/ # ktr/public/ 的静态资源(assets: 'copy')构建完成后,宿主应用不需要配置 Vite 或 tsdown:
import { renderTemplate } from './dist/ktr/index.mjs'
const result = await renderTemplate('hello/card', {
title: 'Hello',
items: []
})
if (!result.success) {
throw new Error(result.error)
}
console.log(result.htmlPath)CSS 在构建时内嵌到 index.mjs,不是单独的 style.css。HTML 文件只在实际调用渲染函数时按 outputDir 写出,构建过程本身不会生成 HTML。
生产构建
如果宿主本身就是 npm 包并且已经有 Vite 或 tsdown 入口,继续使用 ktrBuildPlugin()(来自 @karinjs/template-react/plugin);它会自动同步 .ktr 注册表并把 CSS 编译到打包器自己的 outDir。完整配置见 构建发布。
使用场景
场景 1:标准 Vite 项目打包
import { } from 'vite'
import { } from '@karinjs/template-react/plugin'
export default ({
: [()]
})运行 vite build 时自动:
buildStart 钩子执行ktr sync刷新注册表generateBundle 钩子编译 Tailwind CSS,并以 asset 形式注入打包器 bundle 输出<打包器 outDir>/style.css(上例为 vite 默认的dist/style.css),会出现在打包器自身的输出文件列表里- 复制静态资源到
<打包器 outDir>/assets/
生产渲染所需的 template-registry.js 由打包器入口产出。mock-registry.js 仅在生产代码主动调用 loadMockRegistry() 时按需构建,见 构建发布。
场景 2:tsdown 极速打包
import { } from 'tsdown'
import { } from '@karinjs/template-react/plugin'
export default ({
: ['src/index.ts'],
: ['esm'],
: true,
: [()]
})适合纯 TypeScript 插件项目,打包速度比 Vite 不相上下。
场景 3:自定义产物目录
import { } from 'vite'
import { } from '@karinjs/template-react/plugin'
export default ({
: {
: 'output' // 自定义产物目录
},
: [()] // CSS 自动输出到 output/style.css
})场景 4:跳过资源复制
import { } from '@karinjs/template-react'
export default ({
: {
: false // ktr/public 已在 package.json files 中,不重复复制
}
})适合资源目录本身已随包发布的场景。
场景 5:生产环境验证
# 打包
pnpm build
# 验证产物结构(dist 为 vite/tsdown 默认 outDir)
ls -R dist
# 应包含:
# - style.css(编译后的 CSS)
# - assets/(静态资源)
# 注意:.ktr/ 固定留在项目根目录,不会复制进产物;
# 生产注册表由打包器入口 chunk 产出,跟随产物代码一起发布
# 验证渲染功能
node -e "
import('./dist/index.js').then(async (mod) => {
const render = mod.createTemplateRenderer(import.meta.url);
const result = await render('hello/card', { title: 'Test' });
console.log('渲染结果:', result);
});
"CLI 选项优先级
命令行选项 > karin.template.ts > 内置默认值
# 配置文件设置 port: 5180
# 命令行覆盖为 3000
pnpm ktr dev --port 3000
# 最终使用 3000# 配置文件设置 open: true
# 命令行覆盖为 false
pnpm ktr dev --no-open
# 最终不打开浏览器常见问题
端口被占用
症状:启动时提示「端口 5180 已被占用」。
解决:
- 自动换端口(推荐):启动详情会打印新端口,直接访问即可。
- 手动释放端口:复制终端打印的
kill命令执行。 - 指定其他端口:
pnpm ktr dev --port 3000。
类型推导失效
症状:renderTemplate('hello/card', data) 中 data 没有类型提示。
解决:
- 运行
pnpm ktr sync刷新.ktr/registry-types.d.ts。 - 检查
tsconfig.json的include包含.ktr/**/*.d.ts。 - 重启 TypeScript Server(VSCode:
Ctrl+Shift+P→TypeScript: Restart TS Server)。
模板未找到
症状:渲染时返回 Template not found: hello/card。
解决:
- 确认模板文件存在:
ktr/template/hello/card/index.tsx。 - 确认导出方式:必须是
export default defineTemplate({...})。 - 运行
pnpm ktr sync刷新注册表。 - 检查路由拼写:板块和模板名用
/分隔,如'hello/card'。
CSS 未生效
症状:SSR HTML 没有样式,或样式不完整。
解决:
- 检查
ktr/template/style.css存在且包含@import 'tailwindcss'。 - 开发态确认
node_modules/.cache/ktr/style.css已生成(ktr dev自动生成)。 - 集成打包器模式确认产物目录包含
style.css(如lib/style.css);standalone 模式不生成独立 CSS 文件,CSS 已内嵌在dist/ktr/index.mjs。 - 额外样式检查
extraStylePaths路径正确且文件存在。
资源 404
症状:模板中引用的图片、字体等资源加载失败。
解决:
- 资源放到
ktr/public/目录。 - 模板中用绝对路径引用:
/assets/avatar.png(不是./assets/)。 - 确认
dir.copyAssets为true(默认值)。 - 生产态确认产物目录下
assets/存在(如lib/assets/)。