@chidchanun/bcp 0.1.19 → 0.1.21
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 +35 -4
- package/docs/README.md +70 -7
- package/docs/error-handling.md +457 -0
- package/docs/hydration.md +190 -0
- package/docs/releases/0.1.20.md +124 -0
- package/docs/releases/0.1.21.md +92 -0
- package/package.json +5 -1
- package/packages/bundler/src/index.ts +46 -33
- package/packages/client/src/http-error.ts +516 -0
- package/packages/client/src/server.ts +22 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Hydration and deterministic rendering
|
|
2
|
+
|
|
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
|
+
|
|
5
|
+
## Development transform parity
|
|
6
|
+
|
|
7
|
+
BCP Framework 0.1.21 fixes a development hydration mismatch caused by the server and client using different JSX transform semantics.
|
|
8
|
+
|
|
9
|
+
A common trigger is a multiline quoted JSX attribute:
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
export default function Page() {
|
|
13
|
+
return (
|
|
14
|
+
<main
|
|
15
|
+
className="
|
|
16
|
+
min-h-screen
|
|
17
|
+
bg-white
|
|
18
|
+
text-slate-950
|
|
19
|
+
"
|
|
20
|
+
>
|
|
21
|
+
Hello
|
|
22
|
+
</main>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
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.
|
|
52
|
+
|
|
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.
|
|
80
|
+
|
|
81
|
+
## What BCP fixes automatically
|
|
82
|
+
|
|
83
|
+
The framework fixes deterministic source-transform differences. It does not hide genuine hydration differences caused by application behavior.
|
|
84
|
+
|
|
85
|
+
BCP applications should still avoid producing different initial values on the server and client from code such as:
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
const value = Date.now();
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
const value = Math.random();
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
or:
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
const browserOnly =
|
|
99
|
+
typeof window !== "undefined";
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
when those values directly change the initial rendered markup.
|
|
103
|
+
|
|
104
|
+
Other common application-level causes include:
|
|
105
|
+
|
|
106
|
+
- locale-dependent formatting that differs between server and browser,
|
|
107
|
+
- data that changes between SSR and hydration without a serialized snapshot,
|
|
108
|
+
- browser-only state initialized from `localStorage`, `sessionStorage` or `matchMedia`,
|
|
109
|
+
- invalid HTML nesting,
|
|
110
|
+
- browser extensions that modify the DOM before React hydrates it.
|
|
111
|
+
|
|
112
|
+
## Recommended pattern for browser-only state
|
|
113
|
+
|
|
114
|
+
If a value genuinely depends on the browser, initialize the server/client render deterministically and update it after mount.
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
"use client";
|
|
118
|
+
|
|
119
|
+
import {
|
|
120
|
+
useEffect,
|
|
121
|
+
useState,
|
|
122
|
+
} from "react";
|
|
123
|
+
|
|
124
|
+
export default function BrowserValue() {
|
|
125
|
+
const [ready, setReady] =
|
|
126
|
+
useState(false);
|
|
127
|
+
|
|
128
|
+
useEffect(
|
|
129
|
+
() => {
|
|
130
|
+
setReady(true);
|
|
131
|
+
},
|
|
132
|
+
[]
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
<span>
|
|
137
|
+
{ready
|
|
138
|
+
? "Browser ready"
|
|
139
|
+
: "Loading"}
|
|
140
|
+
</span>
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
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.
|
|
168
|
+
|
|
169
|
+
Production client compilation already uses the esbuild production pipeline and does not use the development React Refresh Babel transform.
|
|
170
|
+
|
|
171
|
+
## Troubleshooting
|
|
172
|
+
|
|
173
|
+
If React still reports a hydration mismatch after upgrading to a BCP release containing the 0.1.21 fix:
|
|
174
|
+
|
|
175
|
+
1. stop the BCP dev server,
|
|
176
|
+
2. remove `.bcp-framework/`,
|
|
177
|
+
3. start `bcp dev` again,
|
|
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.
|
|
183
|
+
|
|
184
|
+
Do not use `suppressHydrationWarning` as a general fix. It should only be used when a difference is intentional and understood.
|
|
185
|
+
|
|
186
|
+
## Regression coverage
|
|
187
|
+
|
|
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,124 @@
|
|
|
1
|
+
# BCP Framework 0.1.20
|
|
2
|
+
|
|
3
|
+
BCP 0.1.20 introduces the Error Handling System: structured HTTP errors and consistent JSON error responses for APIs, form actions, guards, loaders and shared service code. It also hardens development hydration on Windows by normalizing source line endings before the React Refresh/Babel transform.
|
|
4
|
+
|
|
5
|
+
## Highlights
|
|
6
|
+
|
|
7
|
+
- Added the public `bcp/error` entrypoint.
|
|
8
|
+
- Added `HttpError`, `createHttpError()`, `throwHttpError()` and `isHttpError()`.
|
|
9
|
+
- Added `errorResponse()` and `toErrorResponse()`.
|
|
10
|
+
- Added convenience response helpers for common statuses:
|
|
11
|
+
- `badRequest()` — 400
|
|
12
|
+
- `unauthorized()` — 401
|
|
13
|
+
- `forbidden()` — 403
|
|
14
|
+
- `notFoundResponse()` — 404
|
|
15
|
+
- `conflict()` — 409
|
|
16
|
+
- `unprocessableEntity()` — 422
|
|
17
|
+
- `tooManyRequests()` — 429
|
|
18
|
+
- `internalServerError()` — 500
|
|
19
|
+
- `serviceUnavailable()` — 503
|
|
20
|
+
- Standardized the HTTP error payload around `status`, `code`, `message` and optional `details`.
|
|
21
|
+
- Error responses default to `Cache-Control: no-store`.
|
|
22
|
+
- `tooManyRequests()` can emit `Retry-After`.
|
|
23
|
+
- Unknown exceptions passed to `toErrorResponse()` become a safe generic 500 response without exposing the original exception message.
|
|
24
|
+
- Re-exported the HTTP error helpers through the server-only `bcp/server` entrypoint.
|
|
25
|
+
- Kept `notFound()` and `notFoundResponse()` intentionally separate: page 404 UI versus JSON HTTP 404 response.
|
|
26
|
+
- Fixed development hydration mismatches on Windows when CRLF source files contain multiline JSX/template-literal attributes such as multiline `className` values.
|
|
27
|
+
- Development application source now normalizes `CRLF` and standalone `CR` to `LF` before the React Refresh Babel transform, matching SSR source semantics.
|
|
28
|
+
- Added a CRLF development bundle regression fixture so the line-ending mismatch cannot silently return.
|
|
29
|
+
- Added unit and publish-surface regression coverage.
|
|
30
|
+
- Added the Error Handling and Hydration guides and updated the `bcp-docs` source map.
|
|
31
|
+
|
|
32
|
+
## API example
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import {
|
|
36
|
+
unauthorized,
|
|
37
|
+
} from "bcp/error";
|
|
38
|
+
|
|
39
|
+
export async function GET() {
|
|
40
|
+
const user = null;
|
|
41
|
+
|
|
42
|
+
if (!user) {
|
|
43
|
+
return unauthorized();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return Response.json({
|
|
47
|
+
user,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Validation example
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
import {
|
|
56
|
+
unprocessableEntity,
|
|
57
|
+
} from "bcp/error";
|
|
58
|
+
import {
|
|
59
|
+
v,
|
|
60
|
+
} from "bcp/validation";
|
|
61
|
+
|
|
62
|
+
const schema =
|
|
63
|
+
v.object({
|
|
64
|
+
email:
|
|
65
|
+
v.string({
|
|
66
|
+
email: true,
|
|
67
|
+
}),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
export async function POST(
|
|
71
|
+
request: Request
|
|
72
|
+
) {
|
|
73
|
+
const result =
|
|
74
|
+
schema.safeParse(
|
|
75
|
+
await request.json()
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
if (!result.success) {
|
|
79
|
+
return unprocessableEntity(
|
|
80
|
+
"Validation failed",
|
|
81
|
+
{
|
|
82
|
+
fieldErrors:
|
|
83
|
+
result.fieldErrors,
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return Response.json(
|
|
89
|
+
result.data
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Windows hydration fix
|
|
95
|
+
|
|
96
|
+
The following pattern is valid BCP/React code and no longer requires a one-line workaround on CRLF checkouts:
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
export default function Page() {
|
|
100
|
+
return (
|
|
101
|
+
<main
|
|
102
|
+
className={`
|
|
103
|
+
min-h-screen
|
|
104
|
+
bg-white
|
|
105
|
+
text-slate-950
|
|
106
|
+
`}
|
|
107
|
+
>
|
|
108
|
+
Hello
|
|
109
|
+
</main>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Before the fix, the development Babel/React Refresh path could preserve carriage-return characters differently from the SSR transform. React then saw different attribute strings during hydration even though the Tailwind class list looked identical. BCP now normalizes the development source before Babel.
|
|
115
|
+
|
|
116
|
+
This does not suppress genuine hydration errors from `Date.now()`, `Math.random()`, browser-only initial branches, locale differences, changing external data or invalid HTML.
|
|
117
|
+
|
|
118
|
+
See `docs/hydration.md` for details and troubleshooting.
|
|
119
|
+
|
|
120
|
+
## Compatibility
|
|
121
|
+
|
|
122
|
+
0.1.20 is additive. Existing `Response`, `Response.json()`, `bcp/server` helpers, `notFound()`, route guards and form actions continue to work.
|
|
123
|
+
|
|
124
|
+
Applications do not need to migrate existing error handling immediately. New code can adopt `bcp/error` incrementally.
|
|
@@ -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.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chidchanun/bcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.21",
|
|
4
4
|
"description": "BCP Framework - a React full-stack framework with file-based routing, SSR, APIs, middleware, islands, caching and standalone production builds.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -47,6 +47,10 @@
|
|
|
47
47
|
"types": "./packages/client/src/validation.ts",
|
|
48
48
|
"default": "./packages/client/src/validation.ts"
|
|
49
49
|
},
|
|
50
|
+
"./error": {
|
|
51
|
+
"types": "./packages/client/src/http-error.ts",
|
|
52
|
+
"default": "./packages/client/src/http-error.ts"
|
|
53
|
+
},
|
|
50
54
|
"./database": {
|
|
51
55
|
"types": "./packages/client/src/database.ts",
|
|
52
56
|
"browser": "./packages/client/src/server-only.browser.mjs",
|
|
@@ -608,9 +608,9 @@ if (!globalThis.__BCP_HMR_SOURCE__) {
|
|
|
608
608
|
runtimeOutput,
|
|
609
609
|
|
|
610
610
|
content:
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
611
|
+
fs.readFileSync(
|
|
612
|
+
runtimeOutput
|
|
613
|
+
),
|
|
614
614
|
|
|
615
615
|
contentType:
|
|
616
616
|
"text/javascript; charset=utf-8",
|
|
@@ -881,6 +881,9 @@ export class DevClientBundler {
|
|
|
881
881
|
jsx:
|
|
882
882
|
"automatic",
|
|
883
883
|
|
|
884
|
+
jsxDev:
|
|
885
|
+
true,
|
|
886
|
+
|
|
884
887
|
define:
|
|
885
888
|
createClientEnvironmentDefines(
|
|
886
889
|
"development"
|
|
@@ -1010,7 +1013,7 @@ export class DevClientBundler {
|
|
|
1010
1013
|
* เปลี่ยนเป็น
|
|
1011
1014
|
*
|
|
1012
1015
|
* Page
|
|
1013
|
-
* import A
|
|
1016
|
+
* เดิม import A
|
|
1014
1017
|
* import B
|
|
1015
1018
|
*
|
|
1016
1019
|
* จึง rebuild graph ใหม่
|
|
@@ -1114,7 +1117,7 @@ export class DevClientBundler {
|
|
|
1114
1117
|
/*
|
|
1115
1118
|
* =================================
|
|
1116
1119
|
* Module Graph
|
|
1117
|
-
*
|
|
1120
|
+
* =====================================
|
|
1118
1121
|
*/
|
|
1119
1122
|
|
|
1120
1123
|
private rebuildModuleGraph() {
|
|
@@ -1155,7 +1158,7 @@ export class DevClientBundler {
|
|
|
1155
1158
|
/*
|
|
1156
1159
|
* =================================
|
|
1157
1160
|
* Find Affected Routes
|
|
1158
|
-
*
|
|
1161
|
+
* =====================================
|
|
1159
1162
|
*/
|
|
1160
1163
|
|
|
1161
1164
|
findAffectedRoutes(
|
|
@@ -1201,7 +1204,7 @@ export class DevClientBundler {
|
|
|
1201
1204
|
/*
|
|
1202
1205
|
* =================================
|
|
1203
1206
|
* Debug Graph
|
|
1204
|
-
*
|
|
1207
|
+
* =====================================
|
|
1205
1208
|
*/
|
|
1206
1209
|
|
|
1207
1210
|
printAffectedRoutes(
|
|
@@ -1243,7 +1246,7 @@ export class DevClientBundler {
|
|
|
1243
1246
|
/*
|
|
1244
1247
|
* =================================
|
|
1245
1248
|
* Bundles
|
|
1246
|
-
*
|
|
1249
|
+
* =====================================
|
|
1247
1250
|
*/
|
|
1248
1251
|
|
|
1249
1252
|
getBundles():
|
|
@@ -1259,7 +1262,7 @@ export class DevClientBundler {
|
|
|
1259
1262
|
/*
|
|
1260
1263
|
* =================================
|
|
1261
1264
|
* Dispose
|
|
1262
|
-
*
|
|
1265
|
+
* =====================================
|
|
1263
1266
|
*/
|
|
1264
1267
|
|
|
1265
1268
|
async dispose() {
|
|
@@ -1649,6 +1652,15 @@ function createReactVendorPlugin():
|
|
|
1649
1652
|
};
|
|
1650
1653
|
}
|
|
1651
1654
|
|
|
1655
|
+
export function normalizeSourceLineEndings(
|
|
1656
|
+
source: string
|
|
1657
|
+
): string {
|
|
1658
|
+
return source.replace(
|
|
1659
|
+
/\r\n?/g,
|
|
1660
|
+
"\n"
|
|
1661
|
+
);
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1652
1664
|
/*
|
|
1653
1665
|
* =====================================
|
|
1654
1666
|
* React Refresh Plugin
|
|
@@ -1711,11 +1723,13 @@ function createReactRefreshPlugin(
|
|
|
1711
1723
|
}
|
|
1712
1724
|
|
|
1713
1725
|
const source =
|
|
1714
|
-
|
|
1715
|
-
.
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1726
|
+
normalizeSourceLineEndings(
|
|
1727
|
+
await fs.promises
|
|
1728
|
+
.readFile(
|
|
1729
|
+
args.path,
|
|
1730
|
+
"utf8"
|
|
1731
|
+
)
|
|
1732
|
+
);
|
|
1719
1733
|
|
|
1720
1734
|
const extension =
|
|
1721
1735
|
path.extname(
|
|
@@ -1726,17 +1740,18 @@ function createReactRefreshPlugin(
|
|
|
1726
1740
|
extension === ".ts" ||
|
|
1727
1741
|
extension === ".tsx";
|
|
1728
1742
|
|
|
1743
|
+
const parsesJsx =
|
|
1744
|
+
extension !== ".ts";
|
|
1745
|
+
|
|
1729
1746
|
const presets:
|
|
1730
1747
|
any[] = [];
|
|
1731
1748
|
|
|
1732
1749
|
/*
|
|
1733
|
-
* Babel
|
|
1734
|
-
*
|
|
1735
|
-
*
|
|
1736
|
-
*
|
|
1737
|
-
*
|
|
1738
|
-
* allExtensions
|
|
1739
|
-
* isTSX
|
|
1750
|
+
* Babel removes TypeScript syntax and
|
|
1751
|
+
* injects React Refresh registrations.
|
|
1752
|
+
* JSX intentionally remains untransformed
|
|
1753
|
+
* so esbuild owns JSX semantics for both
|
|
1754
|
+
* the normal dev bundle and production.
|
|
1740
1755
|
*/
|
|
1741
1756
|
if (
|
|
1742
1757
|
isTypeScript
|
|
@@ -1746,17 +1761,6 @@ function createReactRefreshPlugin(
|
|
|
1746
1761
|
]);
|
|
1747
1762
|
}
|
|
1748
1763
|
|
|
1749
|
-
presets.push([
|
|
1750
|
-
presetReact,
|
|
1751
|
-
{
|
|
1752
|
-
runtime:
|
|
1753
|
-
"automatic",
|
|
1754
|
-
|
|
1755
|
-
development:
|
|
1756
|
-
true,
|
|
1757
|
-
},
|
|
1758
|
-
]);
|
|
1759
|
-
|
|
1760
1764
|
const result =
|
|
1761
1765
|
await transformAsync(
|
|
1762
1766
|
source,
|
|
@@ -1773,6 +1777,15 @@ function createReactRefreshPlugin(
|
|
|
1773
1777
|
sourceType:
|
|
1774
1778
|
"module",
|
|
1775
1779
|
|
|
1780
|
+
parserOpts:
|
|
1781
|
+
parsesJsx
|
|
1782
|
+
? {
|
|
1783
|
+
plugins: [
|
|
1784
|
+
"jsx",
|
|
1785
|
+
],
|
|
1786
|
+
}
|
|
1787
|
+
: undefined,
|
|
1788
|
+
|
|
1776
1789
|
presets,
|
|
1777
1790
|
|
|
1778
1791
|
plugins: [
|
|
@@ -1828,7 +1841,7 @@ ${result.code}
|
|
|
1828
1841
|
transformed,
|
|
1829
1842
|
|
|
1830
1843
|
loader:
|
|
1831
|
-
"
|
|
1844
|
+
"jsx",
|
|
1832
1845
|
|
|
1833
1846
|
resolveDir:
|
|
1834
1847
|
path.dirname(
|