赤刃明霄陈 — 轻量级 React 元框架:文件路由 · 数据钩子 · SSR · PWA · 多平台脚手架。
Star过200就在README里放赤刃明霄陈立绘
npx chen-the-dawnstreak my-app
# or
npx chen my-app交互式选择项目类型:
| 类型 | 说明 |
|---|---|
| Web | Vite + React |
| Web + PWA | 额外生成 manifest.json、Service Worker |
| Desktop (Electron) | 额外生成 Electron 主进程/预加载脚本 |
| Desktop (Tauri) | 额外生成 src-tauri/ Rust 项目 |
CLI 不会自动安装依赖,创建完成后按提示手动执行 npm install。
npm install chen-the-dawnstreakPeer requirement: React 19+.
import { ChenRouter, Routes, Route, Link, useFetch } from 'chen-the-dawnstreak';
function App() {
return (
<ChenRouter>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</ChenRouter>
);
}Thin wrapper around react-router v7.
import { ChenRouter, Route, Routes, Link, useNavigate } from 'chen-the-dawnstreak';Re-exports: ChenRouter, Route, Routes, Link, NavLink, Navigate, Outlet, useNavigate, useParams, useSearchParams, useLocation, useMatch.
import { useFetch } from 'chen-the-dawnstreak';
function UserList() {
const { data, loading, error, refetch } = useFetch<User[]>('/api/users');
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<ul>
{data?.map((u) => <li key={u.id}>{u.name}</li>)}
</ul>
);
}import { useMutation } from 'chen-the-dawnstreak';
function CreateUser() {
const { mutate, loading } = useMutation<User, { name: string }>('/api/users');
return (
<button disabled={loading} onClick={() => mutate({ name: 'Chen' })}>
Create
</button>
);
}Lightweight form management hook with validation, similar to React Hook Form.
import { useForm } from 'chen-the-dawnstreak';
function LoginForm() {
const { register, handleSubmit, errors, isSubmitting } = useForm({
defaultValues: { email: '', password: '' },
validationRules: {
email: { required: 'Email is required', pattern: { value: /^\S+@\S+$/, message: 'Invalid email' } },
password: { required: true, minLength: { value: 8, message: 'Min 8 characters' } },
},
onSubmit: async (values) => {
await fetch('/api/login', { method: 'POST', body: JSON.stringify(values) });
},
});
return (
<form onSubmit={handleSubmit}>
<input {...register('email')} placeholder="Email" />
{errors.email && <p>{errors.email}</p>}
<input {...register('password')} type="password" placeholder="Password" />
{errors.password && <p>{errors.password}</p>}
<button type="submit" disabled={isSubmitting}>Login</button>
</form>
);
}Returns: { values, errors, touched, isValid, isSubmitting, register, handleSubmit, setValue, setValues, reset, validate, validateField }.
Validation rules: required, min, max, minLength, maxLength, pattern, validate (async), custom.
For controlled components that don't use standard onChange:
import { useForm, useController } from 'chen-the-dawnstreak';
function MyForm() {
const form = useForm({ defaultValues: { role: 'user' } });
const { field, fieldState } = useController(form, { name: 'role' });
return <select value={field.value} onChange={field.onChange}>...</select>;
}Creates a scoped store with React Context. Each StoreProvider holds its own state.
import { createStore } from 'chen-the-dawnstreak';
const { StoreProvider, useStore, useStoreDispatch, useStoreSelector } = createStore({
name: 'counter',
initialState: { count: 0, label: 'Counter' },
});
function Counter() {
const count = useStoreSelector((s) => s.count);
const dispatch = useStoreDispatch();
return <button onClick={() => dispatch((s) => ({ count: s.count + 1 }))}>Count: {count}</button>;
}
function App() {
return (
<StoreProvider>
<Counter />
</StoreProvider>
);
}Module-level store, no Provider needed. Good for app-wide state like themes or auth.
import { createSimpleStore } from 'chen-the-dawnstreak';
const themeStore = createSimpleStore({ dark: false });
function ThemeToggle() {
const { dark } = themeStore.useStore();
const dispatch = themeStore.useDispatch();
return <button onClick={() => dispatch({ dark: !dark })}>{dark ? 'Light' : 'Dark'}</button>;
}Wraps React 19's useActionState for server actions:
import { useServerAction } from 'chen-the-dawnstreak';
// Server action (in a "use server" file)
async function createUser(prev: { error?: string }, formData: FormData) {
"use server";
const name = formData.get('name') as string;
// ... create user
return { error: undefined };
}
// Client component
function CreateUserForm() {
const { state, execute, isPending } = useServerAction(createUser, { error: undefined });
return (
<form action={execute}>
<input name="name" placeholder="Name" />
<button type="submit" disabled={isPending}>Create</button>
{state.error && <p>{state.error}</p>}
</form>
);
}Re-exports: useFormStatus (from react-dom), useOptimistic (from react).
Chen supports server-side rendering with streaming and string-based APIs.
// vite.config.ts
import { chen } from 'chen-the-dawnstreak/vite-plugin';
export default defineConfig({
plugins: [react(), chen({ ssr: true })],
});The ssr: true option stubs CSS imports during SSR builds and configures ssr.noExternal.
import { renderToStream, renderToHTML, createHTMLShell, ChenSSRRouter } from 'chen-the-dawnstreak/ssr';
import express from 'express';
const app = express();
app.use(express.static('dist/client'));
app.get('*', (req, res) => {
const element = (
<ChenSSRRouter location={req.url}>
<App />
</ChenSSRRouter>
);
// Option 1: Streaming (recommended)
renderToStream(element, res, {
clientEntry: '/assets/main.js',
title: 'My App',
cssHref: '/assets/style.css',
});
// Option 2: String rendering
// const html = renderToHTML(element, { clientEntry: '/assets/main.js', title: 'My App' });
// res.send(html);
});renderToStream(element, writable, options)— streams HTML with React'srenderToPipeableStreamrenderToHTML(element, options)— returns complete HTML stringcreateHTMLShell(options)— returns{ beforeContent, afterContent }for custom streamingChenSSRRouter— re-export ofStaticRouterfrom react-routerisBrowser/isServer— environment detection constants
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { chen } from 'chen-the-dawnstreak/vite-plugin';
export default defineConfig({
plugins: [react(), chen()],
});Place page files under src/pages/ according to convention. The plugin automatically generates routes, eliminating the need to manually write <Routes>/<Route>.
chen({ routes: true })
// Or custom directory
chen({ routes: { dir: 'src/pages' } })Add type references in vite-env.d.ts:
/// <reference types="chen-the-dawnstreak/vite-plugin/client" />Use in the application entry point:
import { ChenRouter } from 'chen-the-dawnstreak';
import { ChenRoutes } from 'virtual:chen-routes';
ReactDOM.createRoot(document.getElementById('root')!).render(
<ChenRouter>
<ChenRoutes />
</ChenRouter>
);File Conventions:
| File | Route | Description |
|---|---|---|
pages/index.tsx |
/ |
Homepage |
pages/about.tsx |
/about |
Static Routing |
pages/blog/index.tsx |
/blog |
Index |
pages/blog/[id].tsx |
/blog/:id |
Dynamic Parameters |
pages/[...slug].tsx |
* |
Wildcard catch-all |
pages/_layout.tsx |
— | Root Layout, must contain <Outlet /> |
pages/blog/_layout.tsx |
— | /blog Nested Layout |
pages/_404.tsx |
* |
Custom 404 Page |
_layout.tsx Example:
import { Outlet } from 'chen-the-dawnstreak';
export default function Layout() {
return (
<>
<nav>...</nav>
<Outlet />
</>
);
}Page files are automatically split using React.lazy. Adding/deleting files during development triggers an automatic refresh.
chen({ pwa: true })
// Or custom configuration
chen({
pwa: {
name: 'My App',
shortName: 'App',
themeColor: '#6750a4',
backgroundColor: '#ffffff',
display: 'standalone',
icons: [
{ src: '/icons/icon-192x192.png', sizes: '192x192', type: 'image/png' },
{ src: '/icons/icon-512x512.png', sizes: '512x512', type: 'image/png' },
],
},
})After enabling PWA, manifest.json and sw.js are automatically generated during the build process, and the manifest link, theme-color meta, and Service Worker registration scripts are injected into the HTML.
- Router (react-router v7 wrapper)
- File-based routing
- Data fetching hooks (useFetch, useMutation)
- Form management (useForm, useController)
- State management (createStore, createSimpleStore)
- Server actions (RSC)
- SSR support (streaming + string)
- Build tooling (Vite plugin)
- CLI scaffolding tool (Web / PWA / Electron / Tauri)
MIT