@pyreon/vite-plugin 0.24.4 → 0.24.5
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/lib/analysis/index.js.html +1 -1
- package/lib/index.js +1 -0
- package/package.json +2 -2
- package/src/index.ts +22 -0
- package/src/tests/ssr-no-external.test.ts +82 -0
|
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
|
|
|
5386
5386
|
</script>
|
|
5387
5387
|
<script>
|
|
5388
5388
|
/*<!--*/
|
|
5389
|
-
const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src/index.ts","uid":"
|
|
5389
|
+
const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src/index.ts","uid":"4f3120a0-1"}]},{"name":"rocketstyle-collapse-C4eMAnwR.js","children":[{"name":"src/rocketstyle-collapse.ts","uid":"4f3120a0-3"}]}],"isRoot":true},"nodeParts":{"4f3120a0-1":{"renderedLength":45599,"gzipLength":14790,"brotliLength":0,"metaUid":"4f3120a0-0"},"4f3120a0-3":{"renderedLength":3424,"gzipLength":1530,"brotliLength":0,"metaUid":"4f3120a0-2"}},"nodeMetas":{"4f3120a0-0":{"id":"/src/index.ts","moduleParts":{"index.js":"4f3120a0-1"},"imported":[{"uid":"4f3120a0-4"},{"uid":"4f3120a0-5"},{"uid":"4f3120a0-6"},{"uid":"4f3120a0-2","dynamic":true},{"uid":"4f3120a0-7","dynamic":true}],"importedBy":[],"isEntry":true},"4f3120a0-2":{"id":"/src/rocketstyle-collapse.ts","moduleParts":{"rocketstyle-collapse-C4eMAnwR.js":"4f3120a0-3"},"imported":[{"uid":"4f3120a0-8","dynamic":true}],"importedBy":[{"uid":"4f3120a0-0"}]},"4f3120a0-4":{"id":"node:fs","moduleParts":{},"imported":[],"importedBy":[{"uid":"4f3120a0-0"}]},"4f3120a0-5":{"id":"node:path","moduleParts":{},"imported":[],"importedBy":[{"uid":"4f3120a0-0"}]},"4f3120a0-6":{"id":"@pyreon/compiler","moduleParts":{},"imported":[],"importedBy":[{"uid":"4f3120a0-0"}]},"4f3120a0-7":{"id":"node:fs/promises","moduleParts":{},"imported":[],"importedBy":[{"uid":"4f3120a0-0"}]},"4f3120a0-8":{"id":"vite","moduleParts":{},"imported":[],"importedBy":[{"uid":"4f3120a0-2"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
|
|
5390
5390
|
|
|
5391
5391
|
const run = () => {
|
|
5392
5392
|
const width = window.innerWidth;
|
package/lib/index.js
CHANGED
|
@@ -236,6 +236,7 @@ function pyreonPlugin(options) {
|
|
|
236
236
|
const pyreonExclude = scanPyreonDeps(projectRoot);
|
|
237
237
|
return {
|
|
238
238
|
resolve: { conditions: ["bun"] },
|
|
239
|
+
ssr: { noExternal: [/@pyreon\//] },
|
|
239
240
|
optimizeDeps: { exclude: Array.from(new Set([...compatExclude, ...pyreonExclude])) },
|
|
240
241
|
oxc: { jsx: {
|
|
241
242
|
runtime: "automatic",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyreon/vite-plugin",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.5",
|
|
4
4
|
"description": "Vite plugin for Pyreon — .pyreon SFC support, HMR, compiler integration",
|
|
5
5
|
"homepage": "https://github.com/pyreon/pyreon/tree/main/packages/vite-plugin#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"prepublishOnly": "bun run build"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@pyreon/compiler": "^0.24.
|
|
46
|
+
"@pyreon/compiler": "^0.24.5"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"vite": "^8.0.0"
|
package/src/index.ts
CHANGED
|
@@ -504,6 +504,28 @@ export default function pyreonPlugin(options?: PyreonPluginOptions): Plugin {
|
|
|
504
504
|
// Use "bun" condition for workspace resolution — source .ts/.tsx files
|
|
505
505
|
// for HMR, fast refresh, and type-safe imports.
|
|
506
506
|
resolve: { conditions: ['bun'] },
|
|
507
|
+
// Force every `@pyreon/*` package through Vite's transform pipeline
|
|
508
|
+
// for SSR. Without this, Vite externalizes some `@pyreon/*` packages
|
|
509
|
+
// (loads via Node's `import()`) while transforming others — producing
|
|
510
|
+
// TWO module instances of `@pyreon/core` (one at `lib/index.js`, one
|
|
511
|
+
// at `src/index.ts` via the `bun` condition). The two instances have
|
|
512
|
+
// SEPARATE `_current` lifecycle state, so `runWithHooks` sets
|
|
513
|
+
// `_current` on instance A while `provide()` reads `_current` from
|
|
514
|
+
// instance B → null → `provide() outside setup` warning storm.
|
|
515
|
+
//
|
|
516
|
+
// Real-app symptom (bokisch.com dev-404 SSR, 0.24.4): 17 spurious
|
|
517
|
+
// `[Pyreon] onUnmount() called outside component setup` warnings
|
|
518
|
+
// per unmatched URL hit, even though every `provide()` IS structurally
|
|
519
|
+
// inside a `runWithHooks` setup window. Fix is purely a Vite
|
|
520
|
+
// module-graph reconciliation; no runtime behavior change.
|
|
521
|
+
//
|
|
522
|
+
// The regex `/@pyreon\//` matches every framework package + every
|
|
523
|
+
// user-side `@pyreon/*` import. Internal `@pyreon/*` resolution
|
|
524
|
+
// chains (zero → runtime-server → core; user `_layout.tsx` →
|
|
525
|
+
// ui-core → core) all converge on the same module instance.
|
|
526
|
+
ssr: {
|
|
527
|
+
noExternal: [/@pyreon\//],
|
|
528
|
+
},
|
|
507
529
|
optimizeDeps: {
|
|
508
530
|
exclude: optimizeDepsExclude,
|
|
509
531
|
},
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression lock: `@pyreon/vite-plugin` must set
|
|
3
|
+
* `ssr.noExternal: [/@pyreon\//]` so every framework package goes through
|
|
4
|
+
* Vite's transform pipeline. Without this, Vite externalizes some
|
|
5
|
+
* `@pyreon/*` packages (loads via Node's `import()`) while transforming
|
|
6
|
+
* others — producing TWO module instances of `@pyreon/core` (one at
|
|
7
|
+
* `lib/index.js` via `import` condition, one at `src/index.ts` via the
|
|
8
|
+
* `bun` condition). The two instances have SEPARATE `_current` lifecycle
|
|
9
|
+
* state → `provide()` outside setup warning storm.
|
|
10
|
+
*
|
|
11
|
+
* Real-app symptom (bokisch.com dev-404 SSR, 0.24.4): 17 spurious
|
|
12
|
+
* `[Pyreon] onUnmount() called outside component setup` warnings per
|
|
13
|
+
* unmatched URL hit, even though every `provide()` IS structurally
|
|
14
|
+
* inside a `runWithHooks` setup window.
|
|
15
|
+
*
|
|
16
|
+
* Reproduction trace (the differential):
|
|
17
|
+
* at onUnmount (.../core/lib/index.js:68) ← LIB
|
|
18
|
+
* at provide (.../core/lib/index.js:427) ← LIB
|
|
19
|
+
* at HeadProvider (.../head/lib/provider.js:44) ← LIB
|
|
20
|
+
* at runWithHooks (.../core/src/component.ts:34) ← SRC ❗
|
|
21
|
+
* at renderComponent (.../runtime-server/lib/index.js:308)
|
|
22
|
+
*
|
|
23
|
+
* `head/lib` and `runtime-server/lib` resolve `@pyreon/core` via
|
|
24
|
+
* different Vite paths — `head` lands at `lib/`, `runtime-server` lands
|
|
25
|
+
* at `src/`. Two `_current` variables, two `setCurrentHooks` slots, the
|
|
26
|
+
* one that gets set is NOT the one `provide()` reads from.
|
|
27
|
+
*
|
|
28
|
+
* Bisect-verified: removing `ssr.noExternal` from `vite-plugin`'s
|
|
29
|
+
* `config()` return → bokisch reproduces 17 warnings on `/xyzzy-404`.
|
|
30
|
+
* Restored → 1 (the residual is a separate `useWindowResize` bug class).
|
|
31
|
+
*/
|
|
32
|
+
import pyreon from '@pyreon/vite-plugin'
|
|
33
|
+
import { describe, expect, it } from 'vitest'
|
|
34
|
+
|
|
35
|
+
describe('@pyreon/vite-plugin — ssr.noExternal regression lock', () => {
|
|
36
|
+
it('config() return includes ssr.noExternal matching @pyreon/* via regex', () => {
|
|
37
|
+
const plugin = pyreon()
|
|
38
|
+
const cfg = (plugin as { config: (u: unknown, e: unknown) => unknown }).config(
|
|
39
|
+
{ root: process.cwd() },
|
|
40
|
+
{ command: 'serve' as const, mode: 'development', isPreview: false, isSsrBuild: false },
|
|
41
|
+
) as { ssr?: { noExternal?: unknown } }
|
|
42
|
+
|
|
43
|
+
expect(cfg.ssr).toBeDefined()
|
|
44
|
+
expect(cfg.ssr?.noExternal).toBeDefined()
|
|
45
|
+
expect(Array.isArray(cfg.ssr?.noExternal)).toBe(true)
|
|
46
|
+
|
|
47
|
+
const arr = cfg.ssr?.noExternal as readonly (string | RegExp)[]
|
|
48
|
+
expect(arr.length).toBeGreaterThan(0)
|
|
49
|
+
|
|
50
|
+
// The regex must match every @pyreon/* package name. Without this,
|
|
51
|
+
// Vite externalizes some packages and the module-instance duplication
|
|
52
|
+
// bug returns.
|
|
53
|
+
const matches = (name: string) =>
|
|
54
|
+
arr.some((entry) => (entry instanceof RegExp ? entry.test(name) : entry === name))
|
|
55
|
+
|
|
56
|
+
expect(matches('@pyreon/core'), '@pyreon/core must be noExternal').toBe(true)
|
|
57
|
+
expect(matches('@pyreon/runtime-server'), '@pyreon/runtime-server must be noExternal').toBe(true)
|
|
58
|
+
expect(matches('@pyreon/router'), '@pyreon/router must be noExternal').toBe(true)
|
|
59
|
+
expect(matches('@pyreon/head'), '@pyreon/head must be noExternal').toBe(true)
|
|
60
|
+
expect(matches('@pyreon/ui-core'), '@pyreon/ui-core must be noExternal').toBe(true)
|
|
61
|
+
expect(matches('@pyreon/styler'), '@pyreon/styler must be noExternal').toBe(true)
|
|
62
|
+
expect(matches('@pyreon/elements'), '@pyreon/elements must be noExternal').toBe(true)
|
|
63
|
+
expect(matches('@pyreon/rocketstyle'), '@pyreon/rocketstyle must be noExternal').toBe(true)
|
|
64
|
+
// Hypothetical third-party @pyreon package — the regex should match too.
|
|
65
|
+
expect(matches('@pyreon/anything-new'), 'regex must match future packages').toBe(true)
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('regex does NOT match non-@pyreon packages', () => {
|
|
69
|
+
const plugin = pyreon()
|
|
70
|
+
const cfg = (plugin as { config: (u: unknown, e: unknown) => unknown }).config(
|
|
71
|
+
{ root: process.cwd() },
|
|
72
|
+
{ command: 'serve' as const, mode: 'development', isPreview: false, isSsrBuild: false },
|
|
73
|
+
) as { ssr?: { noExternal?: readonly (string | RegExp)[] } }
|
|
74
|
+
const arr = cfg.ssr?.noExternal ?? []
|
|
75
|
+
const matches = (name: string) =>
|
|
76
|
+
arr.some((entry) => (entry instanceof RegExp ? entry.test(name) : entry === name))
|
|
77
|
+
|
|
78
|
+
expect(matches('react'), 'react must not be noExternal').toBe(false)
|
|
79
|
+
expect(matches('vite'), 'vite must not be noExternal').toBe(false)
|
|
80
|
+
expect(matches('pyreon'), 'unscoped pyreon must not be noExternal').toBe(false)
|
|
81
|
+
})
|
|
82
|
+
})
|