weifuwu 0.9.2 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +150 -28
- package/dist/index.js +6167 -178
- package/package.json +4 -7
package/README.md
CHANGED
|
@@ -34,11 +34,42 @@ Everything follows the same `(req, ctx) => Response` contract. The Router handle
|
|
|
34
34
|
|
|
35
35
|
## Quick start
|
|
36
36
|
|
|
37
|
+
### Hello World
|
|
38
|
+
|
|
37
39
|
```ts
|
|
38
40
|
import { serve } from 'weifuwu'
|
|
39
41
|
serve((req, ctx) => new Response('Hello, World!'), { port: 3000 })
|
|
40
42
|
```
|
|
41
43
|
|
|
44
|
+
### React + Tailwind
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm install weifuwu
|
|
48
|
+
mkdir -p ui/pages
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
// app.ts
|
|
53
|
+
import { serve, Router } from 'weifuwu'
|
|
54
|
+
|
|
55
|
+
const app = new Router()
|
|
56
|
+
app.use('/', await tsx({ dir: './ui/' }))
|
|
57
|
+
serve(app.handler(), { port: 3000, websocket: app.websocketHandler() })
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
// ui/pages/page.tsx
|
|
62
|
+
export default function Home() {
|
|
63
|
+
return <h1 className="text-3xl font-bold text-blue-600">Hello</h1>
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
node app.ts
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Open http://localhost:3000 — Tailwind CSS is compiled automatically, pages hot-reload on save.
|
|
72
|
+
|
|
42
73
|
## Router
|
|
43
74
|
|
|
44
75
|
```ts
|
|
@@ -851,44 +882,134 @@ import { serve, Router } from 'weifuwu'
|
|
|
851
882
|
import { tsx } from 'weifuwu/tsx'
|
|
852
883
|
|
|
853
884
|
const app = new Router()
|
|
854
|
-
app.use('/', await tsx({ dir: './
|
|
885
|
+
app.use('/', await tsx({ dir: './ui/' }))
|
|
855
886
|
|
|
856
887
|
serve(app.handler(), { port: 3000, websocket: app.websocketHandler() })
|
|
857
888
|
```
|
|
858
889
|
|
|
859
|
-
###
|
|
890
|
+
### Directory structure
|
|
860
891
|
|
|
861
|
-
|
|
892
|
+
```
|
|
893
|
+
ui/
|
|
894
|
+
├── pages/ ← 页面文件
|
|
895
|
+
│ ├── page.tsx → GET / (React component, default export)
|
|
896
|
+
│ ├── layout.tsx → root layout (HTML shell, receives req/ctx, NOT hydrated)
|
|
897
|
+
│ ├── not-found.tsx → 404 error page (rendered for unmatched routes, wrapped in layout)
|
|
898
|
+
│ ├── about/page.tsx → GET /about
|
|
899
|
+
│ ├── blog/[slug]/
|
|
900
|
+
│ │ ├── page.tsx → GET /blog/:slug
|
|
901
|
+
│ │ ├── load.ts → data fetching (server-only, default export)
|
|
902
|
+
│ │ └── route.ts → POST /blog/:slug (API, named exports POST/PUT/DELETE/...)
|
|
903
|
+
│ ├── blog/layout.tsx → /blog/* layout (UI structure, receives children, hydrated)
|
|
904
|
+
│ └── api/search/
|
|
905
|
+
│ └── route.ts → GET /api/search (standalone API, no page.tsx needed)
|
|
906
|
+
└── components/ ← 组件文件(会被热更自动感知)
|
|
907
|
+
└── button.tsx
|
|
908
|
+
```
|
|
909
|
+
|
|
910
|
+
### Development mode
|
|
862
911
|
|
|
863
|
-
|
|
864
|
-
- **Tailwind CSS** — if an `app.css` or `globals.css` file is found, Tailwind CSS is processed automatically. Write `className` directly.
|
|
865
|
-
- **`@` aliases** — if `tsconfig.json` or `jsconfig.json` has `compilerOptions.paths`, the `@` alias is passed to esbuild automatically (works with shadcn/ui)
|
|
866
|
-
- **Process state preserved** — DB connections, WebSockets, in-memory caches are not lost
|
|
912
|
+
tsx() runs in development mode automatically when `NODE_ENV !== 'production'`:
|
|
867
913
|
|
|
868
|
-
|
|
914
|
+
- **File watching** — chokidar watches the `dir` directory for `.tsx`/`.ts` changes
|
|
915
|
+
- Page files in `pages/` → single-file recompilation + registry update
|
|
916
|
+
- Component files in `components/` → full rebuild of all pages
|
|
917
|
+
- New files are detected automatically
|
|
918
|
+
- **Live reload** — Compiled via esbuild `write: false` + `vm.Script.runInContext` (no disk writes, no `node --watch` conflict)
|
|
919
|
+
- **WebSocket auto-refresh** — `/__weifuwu/livereload` endpoint pushes reload signals; browser refreshes automatically
|
|
920
|
+
- **`node --watch` compatible** — External files (`app.ts`, `middleware/`) handled by `--watch` restart; `ui/` changes handled by tsx() without conflict
|
|
869
921
|
|
|
870
922
|
```bash
|
|
871
|
-
node app.ts # development
|
|
923
|
+
node app.ts # development (auto-reload + live refresh)
|
|
872
924
|
NODE_ENV=production node app.ts # production
|
|
873
925
|
```
|
|
874
926
|
|
|
875
|
-
###
|
|
927
|
+
### Tailwind CSS
|
|
876
928
|
|
|
929
|
+
tsx() includes built-in Tailwind CSS v4 support. If an `app.css` file exists in the `dir` directory, it is compiled automatically through PostCSS + `@tailwindcss/postcss`. If no `app.css` is found, one is created automatically:
|
|
930
|
+
|
|
931
|
+
```css
|
|
932
|
+
@import "tailwindcss";
|
|
877
933
|
```
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
load.ts → data fetching (server-only, default export)
|
|
886
|
-
route.ts → POST /blog/:slug (API, named exports POST/PUT/DELETE/...)
|
|
887
|
-
blog/layout.tsx → /blog/* layout (UI structure, receives children, hydrated)
|
|
888
|
-
api/search/
|
|
889
|
-
route.ts → GET /api/search (standalone API, no page.tsx needed)
|
|
934
|
+
|
|
935
|
+
Write `className` directly in your components — no CLI, no configuration:
|
|
936
|
+
|
|
937
|
+
```tsx
|
|
938
|
+
export default function Home() {
|
|
939
|
+
return <h1 className="text-3xl font-bold text-blue-600">Hello</h1>
|
|
940
|
+
}
|
|
890
941
|
```
|
|
891
942
|
|
|
943
|
+
In development mode, Tailwind is reprocessed whenever a `.tsx` file changes (new class names are picked up automatically).
|
|
944
|
+
|
|
945
|
+
### `@` alias
|
|
946
|
+
|
|
947
|
+
If your project has a `tsconfig.json` or `jsconfig.json` with `compilerOptions.paths`, tsx() reads it automatically and passes aliases to all esbuild builds (SSR compilation, hydration bundles, and hot reload):
|
|
948
|
+
|
|
949
|
+
```json
|
|
950
|
+
{
|
|
951
|
+
"compilerOptions": {
|
|
952
|
+
"paths": {
|
|
953
|
+
"@/*": ["./ui/*"]
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
```
|
|
958
|
+
|
|
959
|
+
This enables imports like `@/components/button` or `@/lib/utils` in both server-rendered and client-hydrated code.
|
|
960
|
+
|
|
961
|
+
### shadcn/ui
|
|
962
|
+
|
|
963
|
+
tsx() works with [shadcn/ui](https://ui.shadcn.com) out of the box. The `@` alias and Tailwind CSS are handled automatically.
|
|
964
|
+
|
|
965
|
+
```bash
|
|
966
|
+
# 1. Install shadcn CLI and init (select "other" framework)
|
|
967
|
+
npx shadcn@latest init
|
|
968
|
+
|
|
969
|
+
# 2. When prompted, configure:
|
|
970
|
+
# - Style: your preference
|
|
971
|
+
# - Base color: your preference
|
|
972
|
+
# - CSS file path: ui/app.css
|
|
973
|
+
# - Import alias: @/ → ./ui/
|
|
974
|
+
# - React hooks: yes
|
|
975
|
+
```
|
|
976
|
+
|
|
977
|
+
```json
|
|
978
|
+
// tsconfig.json (generated by shadcn init)
|
|
979
|
+
{
|
|
980
|
+
"compilerOptions": {
|
|
981
|
+
"paths": {
|
|
982
|
+
"@/*": ["./ui/*"]
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
```
|
|
987
|
+
|
|
988
|
+
Add components:
|
|
989
|
+
|
|
990
|
+
```bash
|
|
991
|
+
npx shadcn@latest add button card dialog
|
|
992
|
+
```
|
|
993
|
+
|
|
994
|
+
Use them in your pages:
|
|
995
|
+
|
|
996
|
+
```tsx
|
|
997
|
+
// ui/pages/page.tsx
|
|
998
|
+
import { Button } from '@/components/ui/button'
|
|
999
|
+
|
|
1000
|
+
export default function Home() {
|
|
1001
|
+
return <Button variant="outline">Click me</Button>
|
|
1002
|
+
}
|
|
1003
|
+
```
|
|
1004
|
+
|
|
1005
|
+
```bash
|
|
1006
|
+
node app.ts
|
|
1007
|
+
```
|
|
1008
|
+
|
|
1009
|
+
### Backward compatibility
|
|
1010
|
+
|
|
1011
|
+
`tsx({ dir: './pages/' })` still works. When there is no `pages/` subdirectory under `dir`, the `dir` itself is used as the pages directory.
|
|
1012
|
+
|
|
892
1013
|
### page.tsx — page component
|
|
893
1014
|
|
|
894
1015
|
```tsx
|
|
@@ -967,7 +1088,7 @@ serve(app.handler(), { websocket: app.websocketHandler() })
|
|
|
967
1088
|
```
|
|
968
1089
|
|
|
969
1090
|
```bash
|
|
970
|
-
node app.ts # development (auto-reload
|
|
1091
|
+
node app.ts # development (auto-reload + live refresh)
|
|
971
1092
|
NODE_ENV=production node app.ts # production
|
|
972
1093
|
```
|
|
973
1094
|
|
|
@@ -1110,18 +1231,19 @@ Returns `MessagerModule` — `{ migrate, router, wsHandler, send, close }`.
|
|
|
1110
1231
|
|
|
1111
1232
|
| Option | Default | Description |
|
|
1112
1233
|
|--------|---------|-------------|
|
|
1113
|
-
| `dir`
|
|
1234
|
+
| `dir` | — | UI directory path (containing `pages/` and optionally `components/`) |
|
|
1114
1235
|
|
|
1115
1236
|
Returns `Promise<Router>`.
|
|
1116
1237
|
|
|
1117
|
-
|
|
1238
|
+
Auto-detected features (no configuration needed):
|
|
1118
1239
|
|
|
1119
1240
|
| Feature | Behavior |
|
|
1120
1241
|
|---------|----------|
|
|
1121
|
-
| **File watching** | Enabled
|
|
1122
|
-
| **Tailwind CSS** | Auto-detected when `app.css` / `globals.css` exists. Processed through PostCSS + Tailwind plugin. Served at `/__wfw/style.css` and auto-injected into HTML `<head>` |
|
|
1123
|
-
| **`@` alias** | Read from `tsconfig.json` / `jsconfig.json` `compilerOptions.paths` and passed to esbuild |
|
|
1242
|
+
| **File watching** | Enabled in dev mode. Watches `dir` for changes, recompiles on the fly, sends reload via WebSocket |
|
|
1124
1243
|
| **WebSocket live reload** | Endpoint at `/__weifuwu/livereload`. Browser auto-refreshes on file changes or server restart |
|
|
1244
|
+
| **Tailwind CSS** | Auto-detected when `app.css` exists. Compiled through PostCSS + `@tailwindcss/postcss`. Served at `/__wfw/style.css`, auto-injected into HTML `<head>` |
|
|
1245
|
+
| **`@` alias** | Read from `tsconfig.json` / `jsconfig.json` `compilerOptions.paths`. Passed to all esbuild builds |
|
|
1246
|
+
| **Process state** | Dev mode keeps the process alive on file changes. DB connections, WebSockets, in-memory caches persist |
|
|
1125
1247
|
|
|
1126
1248
|
To use WebSocket features, pass `router.websocketHandler()` to `serve()`:
|
|
1127
1249
|
|