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.
Files changed (3) hide show
  1. package/README.md +150 -28
  2. package/dist/index.js +6167 -178
  3. 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: './pages/' }))
885
+ app.use('/', await tsx({ dir: './ui/' }))
855
886
 
856
887
  serve(app.handler(), { port: 3000, websocket: app.websocketHandler() })
857
888
  ```
858
889
 
859
- ### Development mode
890
+ ### Directory structure
860
891
 
861
- `tsx()` automatically runs in development mode (`NODE_ENV !== 'production'`):
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
- - **File watching** — editing a `.tsx`/`.ts` file triggers recompilation and the browser auto-refreshes via WebSocket
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
- Production mode (`NODE_ENV=production`) disables file watching and live reload. All other features work the same.
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
- ### File conventions
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
- pages/
879
- page.tsx → GET / (React component, default export)
880
- layout.tsx → root layout (HTML shell, receives req/ctx, NOT hydrated)
881
- not-found.tsx → 404 error page (rendered for unmatched routes, wrapped in layout)
882
- about/page.tsx → GET /about
883
- blog/[slug]/
884
- page.tsx → GET /blog/:slug
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 on changes)
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` | — | Pages directory path |
1234
+ | `dir` | — | UI directory path (containing `pages/` and optionally `components/`) |
1114
1235
 
1115
1236
  Returns `Promise<Router>`.
1116
1237
 
1117
- Development features (auto-detected, no configuration needed):
1238
+ Auto-detected features (no configuration needed):
1118
1239
 
1119
1240
  | Feature | Behavior |
1120
1241
  |---------|----------|
1121
- | **File watching** | Enabled when `NODE_ENV !== 'production'`. Watches pages directory, recompiles on change, sends live-reload signal via WebSocket |
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