@chidchanun/bcp 0.1.20 → 0.1.22
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 +71 -4
- package/docs/README.md +48 -13
- package/docs/developer-tools.md +118 -0
- package/docs/hydration.md +92 -14
- package/docs/releases/0.1.21.md +92 -0
- package/docs/releases/0.1.22.md +77 -0
- package/package.json +1 -1
- package/packages/bundler/src/index.ts +22 -20
- package/packages/cli/src/args.ts +32 -0
- package/packages/cli/src/developer-tools.ts +1249 -0
- package/packages/cli/src/index.ts +74 -0
- package/packages/server/src/production-server.ts +0 -1746
- package/packages/server/src/standalone-production-runtime.ts +0 -1951
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# BCP Framework
|
|
2
2
|
|
|
3
|
-
BCP Framework is a React full-stack framework with file-based routing, SSR, client navigation, API routes, middleware, metadata, client islands, cache/revalidation, security defaults and standalone production builds.
|
|
3
|
+
BCP Framework is a React full-stack framework with file-based routing, SSR, client navigation, API routes, middleware, metadata, client islands, cache/revalidation, validation, structured errors, authentication, database primitives, security defaults and standalone production builds.
|
|
4
4
|
|
|
5
|
-
> Current release target: `0.1.
|
|
5
|
+
> Current release target: `0.1.22`. BCP is still pre-1.0 and validates each release candidate before the manual npm publish step.
|
|
6
6
|
|
|
7
7
|
## Quick start
|
|
8
8
|
|
|
@@ -86,6 +86,61 @@ See [Application Modules](docs/application-modules.md) for the complete boundary
|
|
|
86
86
|
|
|
87
87
|
Generated Tailwind projects compile to `public/bcp.css`. BCP 0.1.6 inlines that stylesheet into SSR HTML when it is 8 KiB or smaller, removing the stylesheet request from the initial render-critical path. Larger stylesheets remain external so the browser can cache them normally. If the application's Content Security Policy does not allow inline styles, BCP automatically keeps the external stylesheet link.
|
|
88
88
|
|
|
89
|
+
## Development hydration parity
|
|
90
|
+
|
|
91
|
+
BCP 0.1.21 fixes a development-only hydration mismatch where the SSR transform and the React Refresh client transform could assign different semantic values to the same multiline JSX attribute.
|
|
92
|
+
|
|
93
|
+
For example, this is supported application code:
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
<div
|
|
97
|
+
className="
|
|
98
|
+
min-h-screen
|
|
99
|
+
bg-white
|
|
100
|
+
text-slate-950
|
|
101
|
+
"
|
|
102
|
+
/>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
BCP 0.1.20 already normalized Windows `CRLF` and standalone `CR` source line endings to `LF`, but Babel's JSX transform could still collapse the multiline quoted attribute to a single-space-separated string while SSR preserved the original line breaks and indentation.
|
|
106
|
+
|
|
107
|
+
In 0.1.21, Babel remains responsible for TypeScript stripping and React Refresh registration, but JSX is preserved until esbuild compiles it with the development JSX runtime. This keeps static JSX attribute semantics aligned between SSR and the development client bundle.
|
|
108
|
+
|
|
109
|
+
Applications should not need to rewrite multiline classes to one line or use `suppressHydrationWarning` to work around framework transform differences. Genuine runtime mismatches caused by values such as `Date.now()`, `Math.random()`, browser-only initial state, locale differences or changing external data still need to be fixed in application code.
|
|
110
|
+
|
|
111
|
+
See [Hydration and deterministic rendering](docs/hydration.md) for the transform pipeline and troubleshooting guidance.
|
|
112
|
+
|
|
113
|
+
## Developer diagnostics
|
|
114
|
+
|
|
115
|
+
BCP 0.1.22 adds dedicated developer tooling for diagnosing application setup without starting the development server.
|
|
116
|
+
|
|
117
|
+
Run a project health check:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
bcp doctor
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The doctor checks the Node.js runtime, project structure, installed BCP/React packages, React and React DOM version parity, duplicate React package roots, environment/config loading, route conflicts and client/server boundaries. Blocking failures produce a non-zero process exit code.
|
|
124
|
+
|
|
125
|
+
Inspect the resolved project inputs BCP sees:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
bcp inspect
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
This prints development env filenames, public environment variable names, resolved BCP configuration, dependency versions and discovered page/API routes.
|
|
132
|
+
|
|
133
|
+
Both commands support JSON output:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
bcp doctor --json
|
|
137
|
+
bcp inspect --json
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
The duplicate React checks are especially useful when verifying local framework builds. Install packed `.tgz` artifacts for release testing instead of linking `.package/bcp` directly into another project, because a linked staging directory can make the application and SSR renderer resolve different React instances.
|
|
141
|
+
|
|
142
|
+
See [Developer Tools](docs/developer-tools.md) for the complete command reference.
|
|
143
|
+
|
|
89
144
|
## Commands
|
|
90
145
|
|
|
91
146
|
```bash
|
|
@@ -93,6 +148,10 @@ bcp dev
|
|
|
93
148
|
bcp routes
|
|
94
149
|
bcp build
|
|
95
150
|
bcp start
|
|
151
|
+
bcp doctor
|
|
152
|
+
bcp doctor --json
|
|
153
|
+
bcp inspect
|
|
154
|
+
bcp inspect --json
|
|
96
155
|
bcp update
|
|
97
156
|
bcp version
|
|
98
157
|
```
|
|
@@ -117,7 +176,7 @@ bcp update --dry-run
|
|
|
117
176
|
Or select a published version/dist-tag explicitly:
|
|
118
177
|
|
|
119
178
|
```bash
|
|
120
|
-
bcp update 0.1.
|
|
179
|
+
bcp update 0.1.22
|
|
121
180
|
bcp update next
|
|
122
181
|
```
|
|
123
182
|
|
|
@@ -777,12 +836,20 @@ No real npm publish command is run automatically by the repository.
|
|
|
777
836
|
- [Server Data Loaders](docs/server-data-loaders.md)
|
|
778
837
|
- [Protected Route Guards](docs/route-guards.md)
|
|
779
838
|
- [Form Actions and Server Mutations](docs/form-actions.md)
|
|
839
|
+
- [Validation](docs/validation.md)
|
|
840
|
+
- [Error Handling](docs/error-handling.md)
|
|
841
|
+
- [Authentication](docs/authentication.md)
|
|
842
|
+
- [Auth Route Guards](docs/auth-route-guards.md)
|
|
780
843
|
- [JWT Cookie Sessions](docs/session-auth.md)
|
|
844
|
+
- [Database](docs/database.md)
|
|
845
|
+
- [Database Migrations](docs/database-migrations.md)
|
|
846
|
+
- [Middleware](docs/middleware.md)
|
|
847
|
+
- [Hydration and deterministic rendering](docs/hydration.md)
|
|
848
|
+
- [Developer Tools](docs/developer-tools.md)
|
|
781
849
|
- [Updating BCP Framework](docs/updating.md)
|
|
782
850
|
- [Routing](docs/routing.md)
|
|
783
851
|
- [Configuration](docs/configuration.md)
|
|
784
852
|
- [Caching](docs/caching.md)
|
|
785
|
-
- [Middleware](docs/middleware.md)
|
|
786
853
|
- [Security](docs/security.md)
|
|
787
854
|
- [Deployment](docs/deployment.md)
|
|
788
855
|
- [Releasing](docs/releasing.md)
|
package/docs/README.md
CHANGED
|
@@ -4,7 +4,7 @@ This directory is the documentation source of truth for the BCP Framework docume
|
|
|
4
4
|
|
|
5
5
|
The recommended documentation website project name is `bcp-docs`.
|
|
6
6
|
|
|
7
|
-
> Documentation target: BCP Framework `0.1.
|
|
7
|
+
> Documentation target: BCP Framework `0.1.22`
|
|
8
8
|
|
|
9
9
|
## Purpose
|
|
10
10
|
|
|
@@ -63,7 +63,8 @@ The website should not invent API behavior that is not documented or tested in t
|
|
|
63
63
|
| Website route | Source file | Description |
|
|
64
64
|
| --- | --- | --- |
|
|
65
65
|
| `/docs/middleware` | `middleware.md` | Middleware System v2 and v1 compatibility |
|
|
66
|
-
| `/docs/hydration` | `hydration.md` | SSR/client
|
|
66
|
+
| `/docs/hydration` | `hydration.md` | SSR/client transform parity, deterministic rendering and Windows line endings |
|
|
67
|
+
| `/docs/developer-tools` | `developer-tools.md` | `bcp doctor`, `bcp inspect` and JSON diagnostics |
|
|
67
68
|
| `/docs/caching` | `caching.md` | Cache and revalidation |
|
|
68
69
|
| `/docs/security` | `security.md` | Framework security defaults |
|
|
69
70
|
| `/docs/development-logging` | `development-logging.md` | Development request logging |
|
|
@@ -75,9 +76,9 @@ Use the files under `docs/releases/` for release pages.
|
|
|
75
76
|
Recommended route format:
|
|
76
77
|
|
|
77
78
|
```text
|
|
78
|
-
/releases/0.1.18
|
|
79
|
-
/releases/0.1.19
|
|
80
79
|
/releases/0.1.20
|
|
80
|
+
/releases/0.1.21
|
|
81
|
+
/releases/0.1.22
|
|
81
82
|
```
|
|
82
83
|
|
|
83
84
|
The newest release should also be available from `/releases`.
|
|
@@ -97,7 +98,8 @@ Recommended feature groups:
|
|
|
97
98
|
- Loading and error UI
|
|
98
99
|
- API routes
|
|
99
100
|
- Client islands / partial hydration
|
|
100
|
-
- Deterministic development hydration across
|
|
101
|
+
- Deterministic development hydration across server/client transform pipelines
|
|
102
|
+
- LF/CRLF-safe development source handling
|
|
101
103
|
|
|
102
104
|
### Server data and mutations
|
|
103
105
|
|
|
@@ -150,6 +152,10 @@ Recommended feature groups:
|
|
|
150
152
|
- Tailwind preset
|
|
151
153
|
- Database/auth presets
|
|
152
154
|
- `bcp update`
|
|
155
|
+
- `bcp doctor` project/runtime diagnostics
|
|
156
|
+
- `bcp inspect` environment/config/route inspection
|
|
157
|
+
- JSON developer-tool output for CI/automation
|
|
158
|
+
- Duplicate React package-root diagnostics
|
|
153
159
|
- Standalone production builds
|
|
154
160
|
- Critical CSS
|
|
155
161
|
- Cache/revalidation
|
|
@@ -209,6 +215,7 @@ Database
|
|
|
209
215
|
Runtime
|
|
210
216
|
Middleware
|
|
211
217
|
Hydration
|
|
218
|
+
Developer Tools
|
|
212
219
|
Caching
|
|
213
220
|
Security
|
|
214
221
|
|
|
@@ -217,9 +224,9 @@ Production
|
|
|
217
224
|
Development Logging
|
|
218
225
|
|
|
219
226
|
Releases
|
|
227
|
+
0.1.22
|
|
228
|
+
0.1.21
|
|
220
229
|
0.1.20
|
|
221
|
-
0.1.19
|
|
222
|
-
0.1.18
|
|
223
230
|
```
|
|
224
231
|
|
|
225
232
|
## Suggested documentation page layout
|
|
@@ -304,6 +311,10 @@ bcp dev
|
|
|
304
311
|
bcp routes
|
|
305
312
|
bcp build
|
|
306
313
|
bcp start
|
|
314
|
+
bcp doctor
|
|
315
|
+
bcp doctor --json
|
|
316
|
+
bcp inspect
|
|
317
|
+
bcp inspect --json
|
|
307
318
|
bcp update
|
|
308
319
|
bcp version
|
|
309
320
|
|
|
@@ -351,7 +362,7 @@ See `validation.md` for the complete API and examples.
|
|
|
351
362
|
|
|
352
363
|
## Error Handling documentation priority
|
|
353
364
|
|
|
354
|
-
BCP 0.1.20
|
|
365
|
+
BCP 0.1.20 introduced the public `bcp/error` entrypoint and a standard HTTP error envelope.
|
|
355
366
|
|
|
356
367
|
The docs website should clearly distinguish:
|
|
357
368
|
|
|
@@ -375,17 +386,41 @@ See `error-handling.md` for the complete API and examples.
|
|
|
375
386
|
|
|
376
387
|
## Hydration documentation priority
|
|
377
388
|
|
|
378
|
-
BCP 0.1.20
|
|
389
|
+
BCP 0.1.20 added line-ending normalization for the development React Refresh path. That removed the Windows `CRLF` versus `LF` mismatch, but a second issue remained when Babel compiled multiline quoted JSX attributes and collapsed their whitespace differently from SSR.
|
|
390
|
+
|
|
391
|
+
BCP 0.1.21 completes this fix by keeping Babel responsible for TypeScript removal and React Refresh instrumentation while leaving JSX untransformed. esbuild then performs the development JSX transform with the development JSX runtime enabled.
|
|
379
392
|
|
|
380
393
|
The docs website should make these points clear:
|
|
381
394
|
|
|
382
|
-
- multiline JSX attributes
|
|
383
|
-
-
|
|
384
|
-
-
|
|
395
|
+
- multiline quoted JSX attributes are supported,
|
|
396
|
+
- multiline template-literal JSX expressions are supported,
|
|
397
|
+
- developers should not need to rewrite multiline `className` values as one-line strings to avoid framework hydration warnings,
|
|
398
|
+
- `CRLF` and standalone `CR` source line endings are normalized to `LF` before development instrumentation,
|
|
399
|
+
- React Refresh instrumentation must not change the semantic value of JSX attributes,
|
|
385
400
|
- the framework fix does not suppress genuine hydration mismatches caused by random values, locale differences, browser-only initial branches, changing external data or invalid HTML,
|
|
386
401
|
- `suppressHydrationWarning` is not a general-purpose solution.
|
|
387
402
|
|
|
388
|
-
See `hydration.md` for the full explanation and troubleshooting steps.
|
|
403
|
+
See `hydration.md` for the full explanation, transform pipeline and troubleshooting steps.
|
|
404
|
+
|
|
405
|
+
## Developer Tools documentation priority
|
|
406
|
+
|
|
407
|
+
BCP 0.1.22 adds `bcp doctor` and `bcp inspect` as the first dedicated developer-diagnostics commands.
|
|
408
|
+
|
|
409
|
+
The docs website should surface:
|
|
410
|
+
|
|
411
|
+
- PASS/WARN/FAIL health checks,
|
|
412
|
+
- non-zero exit codes for blocking doctor failures,
|
|
413
|
+
- React / React DOM version and package-root parity,
|
|
414
|
+
- config and development environment inspection,
|
|
415
|
+
- page/API route summaries,
|
|
416
|
+
- `--json` output for CI and automation,
|
|
417
|
+
- the recommendation to verify local releases from packed `.tgz` artifacts rather than linked staging directories.
|
|
418
|
+
|
|
419
|
+
See `developer-tools.md` for the full command reference.
|
|
420
|
+
|
|
421
|
+
## Release roadmap
|
|
422
|
+
|
|
423
|
+
`0.1.22` is the Developer Tools milestone. The next planned milestone is `0.1.23` — Logging & Observability, followed by File Upload and the remaining pre-0.2 foundation milestones unless they are regrouped.
|
|
389
424
|
|
|
390
425
|
## Release workflow for documentation
|
|
391
426
|
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Developer Tools
|
|
2
|
+
|
|
3
|
+
BCP Framework 0.1.22 adds project diagnostics and runtime inspection commands for debugging a BCP application without starting the development server.
|
|
4
|
+
|
|
5
|
+
## `bcp doctor`
|
|
6
|
+
|
|
7
|
+
Run a health check from the application root:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
bcp doctor
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The command checks:
|
|
14
|
+
|
|
15
|
+
- the current Node.js runtime against BCP's minimum supported version,
|
|
16
|
+
- `package.json` and the `app/` project structure,
|
|
17
|
+
- the declared and installed BCP package,
|
|
18
|
+
- installed `react` and `react-dom` versions,
|
|
19
|
+
- React / React DOM resolution parity between the application and the framework,
|
|
20
|
+
- development environment files,
|
|
21
|
+
- resolved `bcp.config.*` settings,
|
|
22
|
+
- page/API route discovery and conflicts,
|
|
23
|
+
- client/server module boundaries.
|
|
24
|
+
|
|
25
|
+
A successful check is printed as `PASS`, a non-blocking recommendation as `WARN`, and a blocking project/runtime problem as `FAIL`.
|
|
26
|
+
|
|
27
|
+
If one or more checks fail, `bcp doctor` sets a non-zero process exit code. This makes it suitable for local scripts and CI gates.
|
|
28
|
+
|
|
29
|
+
Example:
|
|
30
|
+
|
|
31
|
+
```text
|
|
32
|
+
BCP Doctor v0.1.22
|
|
33
|
+
Project: D:\apps\my-bcp-app
|
|
34
|
+
Runtime: Node.js 24.15.0 | win32 x64
|
|
35
|
+
|
|
36
|
+
[PASS] Node.js runtime: Node.js 24.15.0 satisfies >=24.11.0.
|
|
37
|
+
[PASS] Project package: package.json is readable.
|
|
38
|
+
[PASS] App directory: app/ is present.
|
|
39
|
+
[PASS] React renderer version parity: react and react-dom both resolve to 19.2.8.
|
|
40
|
+
[PASS] Single React instance: BCP and the application resolve the same React package.
|
|
41
|
+
|
|
42
|
+
Summary: 11 passed, 0 warning(s), 0 failed.
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Duplicate React detection
|
|
46
|
+
|
|
47
|
+
`bcp doctor` specifically checks the package locations used by the application and by BCP itself.
|
|
48
|
+
|
|
49
|
+
This catches local-development layouts where an application resolves React from one `node_modules` tree while the BCP SSR renderer resolves React DOM from another. That situation commonly produces:
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
Invalid hook call. Hooks can only be called inside of the body of a function component.
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
For local release testing, install the packed `.tgz` artifact instead of linking `.package/bcp` directly into another project. A packed package lets the BCP peer dependencies resolve from the application's normal `node_modules` tree.
|
|
56
|
+
|
|
57
|
+
## `bcp inspect`
|
|
58
|
+
|
|
59
|
+
Use `inspect` when you want a deterministic snapshot of the project inputs BCP sees:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
bcp inspect
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
It prints:
|
|
66
|
+
|
|
67
|
+
- framework version,
|
|
68
|
+
- Node.js/platform information,
|
|
69
|
+
- development `.env` files that were loaded,
|
|
70
|
+
- names of public `BCP_PUBLIC_*` variables (values are not exposed by the summary),
|
|
71
|
+
- the fully resolved BCP configuration,
|
|
72
|
+
- resolved BCP/React/React DOM package versions,
|
|
73
|
+
- discovered page and API routes.
|
|
74
|
+
|
|
75
|
+
`inspect` validates route conflicts and client boundaries before printing its report. It does not start an HTTP server.
|
|
76
|
+
|
|
77
|
+
## JSON output
|
|
78
|
+
|
|
79
|
+
Both commands support machine-readable output:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
bcp doctor --json
|
|
83
|
+
bcp inspect --json
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
You can also target another project directory:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
bcp doctor --root ../my-app --json
|
|
90
|
+
bcp inspect --root ../my-app --json
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
`--json` is intentionally limited to `doctor` and `inspect` so other CLI commands keep their existing human-oriented output contracts.
|
|
94
|
+
|
|
95
|
+
## Environment and config behavior
|
|
96
|
+
|
|
97
|
+
Developer tools inspect the development environment because they are intended to diagnose `bcp dev` projects.
|
|
98
|
+
|
|
99
|
+
Environment file precedence remains the same as the normal framework environment loader:
|
|
100
|
+
|
|
101
|
+
```text
|
|
102
|
+
.env
|
|
103
|
+
.env.local
|
|
104
|
+
.env.development
|
|
105
|
+
.env.development.local
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Resolved configuration still follows the framework configuration precedence rules. `bcp inspect` displays the final resolved config rather than only the source `bcp.config.*` object.
|
|
109
|
+
|
|
110
|
+
## CI example
|
|
111
|
+
|
|
112
|
+
A simple project-health gate can use:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
bcp doctor --json > bcp-doctor.json
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The command exits non-zero when blocking checks fail, while the JSON report remains available for CI logs or artifacts.
|
package/docs/hydration.md
CHANGED
|
@@ -2,21 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
BCP uses server-side rendering for the initial HTML and React hydration in the browser. The server-rendered tree and the first client-rendered tree must produce the same element attributes and text.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Development transform parity
|
|
6
6
|
|
|
7
|
-
BCP Framework 0.1.
|
|
7
|
+
BCP Framework 0.1.21 fixes a development hydration mismatch caused by the server and client using different JSX transform semantics.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
A common trigger is a multiline quoted JSX attribute:
|
|
10
10
|
|
|
11
11
|
```tsx
|
|
12
12
|
export default function Page() {
|
|
13
13
|
return (
|
|
14
14
|
<main
|
|
15
|
-
className=
|
|
15
|
+
className="
|
|
16
16
|
min-h-screen
|
|
17
17
|
bg-white
|
|
18
18
|
text-slate-950
|
|
19
|
-
|
|
19
|
+
"
|
|
20
20
|
>
|
|
21
21
|
Hello
|
|
22
22
|
</main>
|
|
@@ -24,13 +24,63 @@ export default function Page() {
|
|
|
24
24
|
}
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Before 0.1.21, development SSR loaded TSX through the server runtime while the client React Refresh path transformed the same module with `@babel/preset-react`. Babel's JSX transform normalizes whitespace in multiline quoted JSX attributes, so the client could receive a value such as:
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
" min-h-screen bg-white text-slate-950 "
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
while SSR produced the original multiline value:
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
"\n min-h-screen\n bg-white\n text-slate-950\n "
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Those class lists are visually equivalent to CSS but they are different JavaScript strings, so React reports a hydration mismatch.
|
|
40
|
+
|
|
41
|
+
BCP 0.1.21 keeps Babel in the development pipeline for TypeScript stripping and React Refresh registration, but Babel no longer compiles JSX. JSX is handed to esbuild with the development JSX runtime enabled. This keeps development JSX semantics aligned with the framework's esbuild-based client compilation and avoids Babel rewriting multiline attribute values before hydration.
|
|
42
|
+
|
|
43
|
+
## Windows CRLF support
|
|
44
|
+
|
|
45
|
+
BCP Framework 0.1.20 added source line-ending normalization for the development React Refresh path.
|
|
46
|
+
|
|
47
|
+
Application source is normalized from `CRLF` (`\r\n`) and standalone `CR` (`\r`) to `LF` (`\n`) before Babel processes development modules. This prevents Windows line endings from introducing carriage-return differences between SSR and the client bundle.
|
|
48
|
+
|
|
49
|
+
The 0.1.20 fix correctly removed carriage-return mismatches, but a separate Babel JSX whitespace normalization issue remained for multiline quoted JSX attributes. That remaining transform-parity issue is addressed by 0.1.21.
|
|
50
|
+
|
|
51
|
+
Developers do not need to rewrite multiline `className` values as one-line strings to work around either framework issue.
|
|
28
52
|
|
|
29
|
-
|
|
53
|
+
## Supported multiline patterns
|
|
54
|
+
|
|
55
|
+
Both of these patterns are valid application code:
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
<div
|
|
59
|
+
className="
|
|
60
|
+
min-h-screen
|
|
61
|
+
bg-white
|
|
62
|
+
text-slate-950
|
|
63
|
+
"
|
|
64
|
+
/>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
and:
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
<div
|
|
71
|
+
className={`
|
|
72
|
+
min-h-screen
|
|
73
|
+
bg-white
|
|
74
|
+
text-slate-950
|
|
75
|
+
`}
|
|
76
|
+
/>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
BCP should hydrate them deterministically without requiring application-specific whitespace workarounds.
|
|
30
80
|
|
|
31
81
|
## What BCP fixes automatically
|
|
32
82
|
|
|
33
|
-
The
|
|
83
|
+
The framework fixes deterministic source-transform differences. It does not hide genuine hydration differences caused by application behavior.
|
|
34
84
|
|
|
35
85
|
BCP applications should still avoid producing different initial values on the server and client from code such as:
|
|
36
86
|
|
|
@@ -55,6 +105,7 @@ Other common application-level causes include:
|
|
|
55
105
|
|
|
56
106
|
- locale-dependent formatting that differs between server and browser,
|
|
57
107
|
- data that changes between SSR and hydration without a serialized snapshot,
|
|
108
|
+
- browser-only state initialized from `localStorage`, `sessionStorage` or `matchMedia`,
|
|
58
109
|
- invalid HTML nesting,
|
|
59
110
|
- browser extensions that modify the DOM before React hydrates it.
|
|
60
111
|
|
|
@@ -91,22 +142,49 @@ export default function BrowserValue() {
|
|
|
91
142
|
}
|
|
92
143
|
```
|
|
93
144
|
|
|
94
|
-
## Development
|
|
145
|
+
## Development pipeline
|
|
146
|
+
|
|
147
|
+
The 0.1.21 development client transform is intentionally split by responsibility:
|
|
148
|
+
|
|
149
|
+
```text
|
|
150
|
+
application TS/TSX
|
|
151
|
+
↓
|
|
152
|
+
line-ending normalization
|
|
153
|
+
↓
|
|
154
|
+
Babel
|
|
155
|
+
- remove TypeScript syntax
|
|
156
|
+
- inject React Refresh registrations
|
|
157
|
+
- preserve JSX
|
|
158
|
+
↓
|
|
159
|
+
esbuild
|
|
160
|
+
- compile JSX
|
|
161
|
+
- use development JSX runtime
|
|
162
|
+
- bundle application modules
|
|
163
|
+
↓
|
|
164
|
+
React hydration
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
The key rule is that React Refresh instrumentation must not change the semantic value of JSX attributes compared with SSR.
|
|
95
168
|
|
|
96
|
-
|
|
169
|
+
Production client compilation already uses the esbuild production pipeline and does not use the development React Refresh Babel transform.
|
|
97
170
|
|
|
98
171
|
## Troubleshooting
|
|
99
172
|
|
|
100
|
-
If React still reports a hydration mismatch after upgrading to a BCP release containing
|
|
173
|
+
If React still reports a hydration mismatch after upgrading to a BCP release containing the 0.1.21 fix:
|
|
101
174
|
|
|
102
175
|
1. stop the BCP dev server,
|
|
103
176
|
2. remove `.bcp-framework/`,
|
|
104
177
|
3. start `bcp dev` again,
|
|
105
|
-
4.
|
|
106
|
-
5.
|
|
178
|
+
4. hard-refresh the browser,
|
|
179
|
+
5. inspect the first differing server/client value in the React hydration warning,
|
|
180
|
+
6. check for request-time, random, locale, browser-only or externally changing values.
|
|
181
|
+
|
|
182
|
+
For framework diagnostics, compare the initial SSR HTML with the generated development client bundle. If the same static JSX attribute produces different strings, treat it as a framework transform-parity regression.
|
|
107
183
|
|
|
108
184
|
Do not use `suppressHydrationWarning` as a general fix. It should only be used when a difference is intentional and understood.
|
|
109
185
|
|
|
110
186
|
## Regression coverage
|
|
111
187
|
|
|
112
|
-
The framework test suite contains a Windows-style CRLF fixture
|
|
188
|
+
The framework test suite contains a Windows-style CRLF fixture using the same multiline quoted JSX `className` pattern that exposed the issue in a real BCP application.
|
|
189
|
+
|
|
190
|
+
The regression test extracts the generated `className` value from the development bundle and verifies that its semantic string value still contains the expected line breaks and indentation instead of Babel's collapsed whitespace form.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# BCP Framework 0.1.21
|
|
2
|
+
|
|
3
|
+
BCP 0.1.21 is a hydration parity hotfix for development builds.
|
|
4
|
+
|
|
5
|
+
## Why this release exists
|
|
6
|
+
|
|
7
|
+
BCP 0.1.20 fixed a Windows-specific `CRLF` versus `LF` mismatch in the React Refresh client transform. After that fix, a second development-only mismatch was isolated: Babel's JSX transform could normalize whitespace inside multiline quoted JSX attributes differently from the SSR transform.
|
|
8
|
+
|
|
9
|
+
For example:
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
<div
|
|
13
|
+
className="
|
|
14
|
+
min-h-screen
|
|
15
|
+
bg-white
|
|
16
|
+
text-slate-950
|
|
17
|
+
"
|
|
18
|
+
/>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
SSR could preserve the multiline string while the development client bundle produced a collapsed value such as:
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
" min-h-screen bg-white text-slate-950 "
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
React correctly treats those as different attribute strings and reports a hydration mismatch.
|
|
28
|
+
|
|
29
|
+
## Fix
|
|
30
|
+
|
|
31
|
+
The development client pipeline now separates React Refresh instrumentation from JSX compilation:
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
TS/TSX source
|
|
35
|
+
-> normalize line endings
|
|
36
|
+
-> Babel: strip TypeScript + inject React Refresh registrations
|
|
37
|
+
-> preserve JSX
|
|
38
|
+
-> esbuild: compile JSX with the development JSX runtime
|
|
39
|
+
-> client bundle
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
This prevents `@babel/preset-react` from rewriting multiline JSX attribute whitespace before hydration while keeping Fast Refresh support.
|
|
43
|
+
|
|
44
|
+
## Highlights
|
|
45
|
+
|
|
46
|
+
- Preserves multiline quoted JSX attribute semantics in development client bundles.
|
|
47
|
+
- Keeps the 0.1.20 `CRLF` / `CR` to `LF` source normalization.
|
|
48
|
+
- Uses esbuild as the development JSX compiler after React Refresh instrumentation.
|
|
49
|
+
- Enables the esbuild development JSX runtime for dev bundles.
|
|
50
|
+
- Adds regression coverage using the same multiline quoted `className` pattern that reproduced the real hydration warning.
|
|
51
|
+
- Regression coverage extracts the generated `className` string and compares its semantic value, rather than only checking that carriage-return characters are absent.
|
|
52
|
+
- No application workaround such as rewriting multiline classes to one line is required.
|
|
53
|
+
|
|
54
|
+
## Compatibility
|
|
55
|
+
|
|
56
|
+
0.1.21 does not change the public application API.
|
|
57
|
+
|
|
58
|
+
Existing routes, loaders, guards, actions, middleware, validation, authentication, database APIs and the 0.1.20 Error Handling System continue to work unchanged.
|
|
59
|
+
|
|
60
|
+
The change is limited to development client transformation and hydration parity.
|
|
61
|
+
|
|
62
|
+
## Local package verification
|
|
63
|
+
|
|
64
|
+
Do not install `.package/bcp` directly into an application for release verification. A direct local-directory install can be linked back to the framework checkout. In that layout, application components may resolve `react` from the application while BCP's SSR renderer resolves `react-dom` from the framework checkout, creating two React instances and causing an `Invalid hook call` before hydration starts.
|
|
65
|
+
|
|
66
|
+
Use the packed release artifact under `.package/artifacts/*.tgz` or the existing package smoke tests instead. A packed tarball is installed as a normal package under the application `node_modules` tree, so the framework's React peer dependencies resolve from the same application installation as the rendered components.
|
|
67
|
+
|
|
68
|
+
A stack trace that mixes paths such as:
|
|
69
|
+
|
|
70
|
+
```text
|
|
71
|
+
<app>/node_modules/react/...
|
|
72
|
+
<framework-checkout>/node_modules/react-dom/...
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
indicates a linked local-package test with duplicate React instances, not a hydration failure.
|
|
76
|
+
|
|
77
|
+
## Upgrade verification
|
|
78
|
+
|
|
79
|
+
After upgrading an application:
|
|
80
|
+
|
|
81
|
+
```powershell
|
|
82
|
+
Remove-Item -Recurse -Force .bcp-framework -ErrorAction SilentlyContinue
|
|
83
|
+
npm run dev
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
A multiline static JSX attribute should hydrate without the server/client attribute mismatch that occurred in 0.1.20.
|
|
87
|
+
|
|
88
|
+
If a hydration warning remains after 0.1.21, compare the first differing SSR/client value and check for genuine runtime differences such as `Date.now()`, `Math.random()`, locale formatting, browser-only initial state, changing external data or invalid HTML nesting.
|
|
89
|
+
|
|
90
|
+
## Roadmap note
|
|
91
|
+
|
|
92
|
+
Because 0.1.21 is used for this hotfix, the previously planned Developer Tools milestone moves to 0.1.22.
|