@bamboocss/vite 1.39.1 → 1.40.1
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/dist/index.cjs +85 -15
- package/dist/index.mjs +85 -15
- package/package.json +9 -9
package/dist/index.cjs
CHANGED
|
@@ -383,7 +383,6 @@ const bamboocssCss = (options) => {
|
|
|
383
383
|
builder.extract();
|
|
384
384
|
if (builder.context?.config.polyfill) throw new Error("bamboocss: the cascade-layer polyfill is incompatible with compiled atomic styles. The polyfill removes the utility-layer boundary required for safe atom reachability and renaming.");
|
|
385
385
|
if (builder.context) {
|
|
386
|
-
session.cssLoaded = true;
|
|
387
386
|
session.utilityLayer = builder.context.config.layers?.utilities ?? "utilities";
|
|
388
387
|
session.extractedFiles.clear();
|
|
389
388
|
for (const file of builder.context.getFiles()) session.extractedFiles.add(builder.context.runtime.path.abs(builder.context.config.cwd, file));
|
|
@@ -413,6 +412,31 @@ const bamboocssCss = (options) => {
|
|
|
413
412
|
pending = Promise.resolve(pending).catch(() => void 0).then(build);
|
|
414
413
|
return pending;
|
|
415
414
|
};
|
|
415
|
+
/**
|
|
416
|
+
* The pass that runs before Rollup resolves anything, and the sheet it produced.
|
|
417
|
+
*
|
|
418
|
+
* `emit` writes `styled-system/`, and reaching it through `load` is too late to be what a
|
|
419
|
+
* fresh clone needs: `load` runs when the *virtual module* is requested, and a module's
|
|
420
|
+
* imports are all resolved before any of them is loaded. So `app/root.tsx` importing both
|
|
421
|
+
* `styled-system/css` and `virtual:bamboo.css` has the first resolved while the directory is
|
|
422
|
+
* still absent — the client build carried on and externalised it, the ssr build failed with
|
|
423
|
+
* "Rolldown failed to resolve import", and `vite dev` served an error overlay. `buildStart` is
|
|
424
|
+
* the first hook Rollup calls, and it precedes all of that.
|
|
425
|
+
*
|
|
426
|
+
* Memoised, and consumed by the first `load` rather than regenerated for it. `buildStart` runs
|
|
427
|
+
* once per environment against this one shared instance, and nothing can have invalidated the
|
|
428
|
+
* result in between — the modules that would invalidate it have not been transformed yet.
|
|
429
|
+
* Regenerating would mean a second full extraction on every cold start, to produce the same
|
|
430
|
+
* bytes.
|
|
431
|
+
*/
|
|
432
|
+
let prebuilt;
|
|
433
|
+
let prebuildStarted = false;
|
|
434
|
+
const prebuild = async () => {
|
|
435
|
+
if (prebuildStarted) return;
|
|
436
|
+
prebuildStarted = true;
|
|
437
|
+
prebuilt = generate();
|
|
438
|
+
await prebuilt;
|
|
439
|
+
};
|
|
416
440
|
return {
|
|
417
441
|
name: "bamboocss:css",
|
|
418
442
|
/**
|
|
@@ -479,6 +503,20 @@ const bamboocssCss = (options) => {
|
|
|
479
503
|
session.expectedEnvironments = new Set(Object.keys(builder.environments));
|
|
480
504
|
}
|
|
481
505
|
},
|
|
506
|
+
/**
|
|
507
|
+
* Put `styled-system/` on disk before anything resolves an import of it.
|
|
508
|
+
*
|
|
509
|
+
* Normalized rather than rethrown as caught, for the reason the compiler's `buildStart`
|
|
510
|
+
* gives: this evaluates the user's config and its hooks, and in dev anything that is not an
|
|
511
|
+
* object crashes Vite's error middleware instead of being reported.
|
|
512
|
+
*/
|
|
513
|
+
async buildStart() {
|
|
514
|
+
try {
|
|
515
|
+
await prebuild();
|
|
516
|
+
} catch (error) {
|
|
517
|
+
throw asError(error, `failed to generate ${VIRTUAL_CSS_ID}`);
|
|
518
|
+
}
|
|
519
|
+
},
|
|
482
520
|
resolveId(id) {
|
|
483
521
|
const query = queryOf(id);
|
|
484
522
|
const base = id.slice(0, id.length - query.length);
|
|
@@ -489,9 +527,12 @@ const bamboocssCss = (options) => {
|
|
|
489
527
|
const query = queryOf(id);
|
|
490
528
|
if (id.slice(0, id.length - query.length) !== RESOLVED_ID) return null;
|
|
491
529
|
servedEnvironments.add(this.environment?.name ?? "default");
|
|
530
|
+
session.cssLoaded = true;
|
|
492
531
|
let css;
|
|
493
532
|
try {
|
|
494
|
-
|
|
533
|
+
const first = prebuilt;
|
|
534
|
+
prebuilt = void 0;
|
|
535
|
+
css = await (first ?? generate());
|
|
495
536
|
} catch (error) {
|
|
496
537
|
throw asError(error, `failed to generate ${VIRTUAL_CSS_ID}`);
|
|
497
538
|
}
|
|
@@ -500,12 +541,28 @@ const bamboocssCss = (options) => {
|
|
|
500
541
|
},
|
|
501
542
|
configureServer(devServer) {
|
|
502
543
|
server = devServer;
|
|
544
|
+
/**
|
|
545
|
+
* The graph the stylesheet's own module lives in, which is the one that has to reach it.
|
|
546
|
+
*
|
|
547
|
+
* `load` registers every extracted file with `addWatchFile`, and `vite:css-analysis`
|
|
548
|
+
* turns those into real importer edges — the virtual module ends up a direct importer of
|
|
549
|
+
* each file the extractor read. So an edit to any of them propagates to the stylesheet on
|
|
550
|
+
* Vite's own pass, in whichever environment holds that edge.
|
|
551
|
+
*
|
|
552
|
+
* The client one, because CSS is a client concern: an ssr environment never applies a
|
|
553
|
+
* stylesheet update, and asking whether *any* environment matched would skip the forced
|
|
554
|
+
* reload below for a server-only module whose styles the client still has to be told
|
|
555
|
+
* about. Vite 5 has one graph and no `environments`, where the question is exact.
|
|
556
|
+
*/
|
|
557
|
+
const clientGraph = devServer.environments?.client?.moduleGraph ?? devServer.moduleGraph;
|
|
503
558
|
const invalidate = (file) => {
|
|
504
559
|
const ctx = builder.context;
|
|
505
560
|
if (!ctx) return;
|
|
506
561
|
if (!ctx.getFiles().some((f) => ctx.runtime.path.abs(ctx.config.cwd, f) === file)) return;
|
|
562
|
+
prebuilt = void 0;
|
|
507
563
|
const mod = server?.moduleGraph.getModuleById(RESOLVED_ID);
|
|
508
564
|
if (!mod) return;
|
|
565
|
+
if (clientGraph.getModulesByFile(file)?.size) return;
|
|
509
566
|
server?.moduleGraph.invalidateModule(mod);
|
|
510
567
|
server?.reloadModule(mod);
|
|
511
568
|
_bamboocss_logger.logger.debug("vite", `styles invalidated by ${file}`);
|
|
@@ -3236,21 +3293,33 @@ const bamboocss = (options = {}) => {
|
|
|
3236
3293
|
/**
|
|
3237
3294
|
* Modules to re-transform because `file` changed, hard-invalidated on the way out.
|
|
3238
3295
|
*
|
|
3239
|
-
*
|
|
3240
|
-
*
|
|
3241
|
-
*
|
|
3296
|
+
* Invalidating is the fix. It drops the stale compiled result, which is the defect itself,
|
|
3297
|
+
* and it has to happen here rather than being left to `updateModules`: Vite *soft*-
|
|
3298
|
+
* invalidates an importer that statically imports the changed module, and a soft invalidation
|
|
3299
|
+
* keeps the cached transform — the very place the compiled class string lives.
|
|
3300
|
+
*
|
|
3301
|
+
* Doing it here also survives another plugin filtering the list afterwards — a framework's
|
|
3302
|
+
* own `hotUpdate` decides what its route modules do, and the stale bytes have to go either
|
|
3303
|
+
* way.
|
|
3304
|
+
*
|
|
3305
|
+
* *Naming* those modules back to Vite is a different question, and the answer is almost
|
|
3306
|
+
* always no. `addWatchFile` makes every consumer a direct importer of the dependency in the
|
|
3307
|
+
* module graph, so `propagateUpdate` walks to all of them from the changed file by itself and
|
|
3308
|
+
* sends exactly the same update. Returning them as well does not merge into that pass: a
|
|
3309
|
+
* framework plugin downstream reads the list and re-drives HMR per entry — react-router's
|
|
3310
|
+
* `react-router-server-change-trigger-client-hmr` calls `reloadModule` once per module, in
|
|
3311
|
+
* both its client and its ssr pass — and each of those is a separate `updateModules`, a
|
|
3312
|
+
* separate `hmr update`, and a separate refetch of the whole module by the browser.
|
|
3242
3313
|
*
|
|
3243
|
-
*
|
|
3244
|
-
*
|
|
3245
|
-
*
|
|
3314
|
+
* Measured on a five-route react-router app, one `css()` edit in a shared `ui.ts`: eight
|
|
3315
|
+
* `hmr update` messages, `root.tsx` and `dashboard.tsx` fetched five times each, 554 kB over
|
|
3316
|
+
* the socket for a one-line edit. Dropping the redundant half takes it to four messages and
|
|
3317
|
+
* 367 kB with the same modules re-transformed and the same edit applied.
|
|
3246
3318
|
*
|
|
3247
|
-
*
|
|
3248
|
-
*
|
|
3249
|
-
*
|
|
3250
|
-
*
|
|
3251
|
-
* have done nothing at all. That one can end in a page reload, which is the honest outcome:
|
|
3252
|
-
* its compiled classes really did change, and a reload is what Vite does with any update
|
|
3253
|
-
* nothing accepts.
|
|
3319
|
+
* So the list is returned only when Vite has matched nothing for the file and would otherwise
|
|
3320
|
+
* do nothing at all — a dependency the fold read that never became a module of its own. That
|
|
3321
|
+
* one can end in a page reload, which is the honest outcome: its compiled classes really did
|
|
3322
|
+
* change, and a reload is what Vite does with any update nothing accepts.
|
|
3254
3323
|
*/
|
|
3255
3324
|
const foldDependentModules = (file, modules, graph) => {
|
|
3256
3325
|
const dependents = dependentsByDependency.get(normalizeFsPath(file));
|
|
@@ -3262,6 +3331,7 @@ const bamboocss = (options = {}) => {
|
|
|
3262
3331
|
added.push(module);
|
|
3263
3332
|
}
|
|
3264
3333
|
if (!added.length) return;
|
|
3334
|
+
if (modules.length) return;
|
|
3265
3335
|
return [...modules, ...added];
|
|
3266
3336
|
};
|
|
3267
3337
|
let ctx;
|
package/dist/index.mjs
CHANGED
|
@@ -353,7 +353,6 @@ const bamboocssCss = (options) => {
|
|
|
353
353
|
builder.extract();
|
|
354
354
|
if (builder.context?.config.polyfill) throw new Error("bamboocss: the cascade-layer polyfill is incompatible with compiled atomic styles. The polyfill removes the utility-layer boundary required for safe atom reachability and renaming.");
|
|
355
355
|
if (builder.context) {
|
|
356
|
-
session.cssLoaded = true;
|
|
357
356
|
session.utilityLayer = builder.context.config.layers?.utilities ?? "utilities";
|
|
358
357
|
session.extractedFiles.clear();
|
|
359
358
|
for (const file of builder.context.getFiles()) session.extractedFiles.add(builder.context.runtime.path.abs(builder.context.config.cwd, file));
|
|
@@ -383,6 +382,31 @@ const bamboocssCss = (options) => {
|
|
|
383
382
|
pending = Promise.resolve(pending).catch(() => void 0).then(build);
|
|
384
383
|
return pending;
|
|
385
384
|
};
|
|
385
|
+
/**
|
|
386
|
+
* The pass that runs before Rollup resolves anything, and the sheet it produced.
|
|
387
|
+
*
|
|
388
|
+
* `emit` writes `styled-system/`, and reaching it through `load` is too late to be what a
|
|
389
|
+
* fresh clone needs: `load` runs when the *virtual module* is requested, and a module's
|
|
390
|
+
* imports are all resolved before any of them is loaded. So `app/root.tsx` importing both
|
|
391
|
+
* `styled-system/css` and `virtual:bamboo.css` has the first resolved while the directory is
|
|
392
|
+
* still absent — the client build carried on and externalised it, the ssr build failed with
|
|
393
|
+
* "Rolldown failed to resolve import", and `vite dev` served an error overlay. `buildStart` is
|
|
394
|
+
* the first hook Rollup calls, and it precedes all of that.
|
|
395
|
+
*
|
|
396
|
+
* Memoised, and consumed by the first `load` rather than regenerated for it. `buildStart` runs
|
|
397
|
+
* once per environment against this one shared instance, and nothing can have invalidated the
|
|
398
|
+
* result in between — the modules that would invalidate it have not been transformed yet.
|
|
399
|
+
* Regenerating would mean a second full extraction on every cold start, to produce the same
|
|
400
|
+
* bytes.
|
|
401
|
+
*/
|
|
402
|
+
let prebuilt;
|
|
403
|
+
let prebuildStarted = false;
|
|
404
|
+
const prebuild = async () => {
|
|
405
|
+
if (prebuildStarted) return;
|
|
406
|
+
prebuildStarted = true;
|
|
407
|
+
prebuilt = generate();
|
|
408
|
+
await prebuilt;
|
|
409
|
+
};
|
|
386
410
|
return {
|
|
387
411
|
name: "bamboocss:css",
|
|
388
412
|
/**
|
|
@@ -449,6 +473,20 @@ const bamboocssCss = (options) => {
|
|
|
449
473
|
session.expectedEnvironments = new Set(Object.keys(builder.environments));
|
|
450
474
|
}
|
|
451
475
|
},
|
|
476
|
+
/**
|
|
477
|
+
* Put `styled-system/` on disk before anything resolves an import of it.
|
|
478
|
+
*
|
|
479
|
+
* Normalized rather than rethrown as caught, for the reason the compiler's `buildStart`
|
|
480
|
+
* gives: this evaluates the user's config and its hooks, and in dev anything that is not an
|
|
481
|
+
* object crashes Vite's error middleware instead of being reported.
|
|
482
|
+
*/
|
|
483
|
+
async buildStart() {
|
|
484
|
+
try {
|
|
485
|
+
await prebuild();
|
|
486
|
+
} catch (error) {
|
|
487
|
+
throw asError(error, `failed to generate ${VIRTUAL_CSS_ID}`);
|
|
488
|
+
}
|
|
489
|
+
},
|
|
452
490
|
resolveId(id) {
|
|
453
491
|
const query = queryOf(id);
|
|
454
492
|
const base = id.slice(0, id.length - query.length);
|
|
@@ -459,9 +497,12 @@ const bamboocssCss = (options) => {
|
|
|
459
497
|
const query = queryOf(id);
|
|
460
498
|
if (id.slice(0, id.length - query.length) !== RESOLVED_ID) return null;
|
|
461
499
|
servedEnvironments.add(this.environment?.name ?? "default");
|
|
500
|
+
session.cssLoaded = true;
|
|
462
501
|
let css;
|
|
463
502
|
try {
|
|
464
|
-
|
|
503
|
+
const first = prebuilt;
|
|
504
|
+
prebuilt = void 0;
|
|
505
|
+
css = await (first ?? generate());
|
|
465
506
|
} catch (error) {
|
|
466
507
|
throw asError(error, `failed to generate ${VIRTUAL_CSS_ID}`);
|
|
467
508
|
}
|
|
@@ -470,12 +511,28 @@ const bamboocssCss = (options) => {
|
|
|
470
511
|
},
|
|
471
512
|
configureServer(devServer) {
|
|
472
513
|
server = devServer;
|
|
514
|
+
/**
|
|
515
|
+
* The graph the stylesheet's own module lives in, which is the one that has to reach it.
|
|
516
|
+
*
|
|
517
|
+
* `load` registers every extracted file with `addWatchFile`, and `vite:css-analysis`
|
|
518
|
+
* turns those into real importer edges — the virtual module ends up a direct importer of
|
|
519
|
+
* each file the extractor read. So an edit to any of them propagates to the stylesheet on
|
|
520
|
+
* Vite's own pass, in whichever environment holds that edge.
|
|
521
|
+
*
|
|
522
|
+
* The client one, because CSS is a client concern: an ssr environment never applies a
|
|
523
|
+
* stylesheet update, and asking whether *any* environment matched would skip the forced
|
|
524
|
+
* reload below for a server-only module whose styles the client still has to be told
|
|
525
|
+
* about. Vite 5 has one graph and no `environments`, where the question is exact.
|
|
526
|
+
*/
|
|
527
|
+
const clientGraph = devServer.environments?.client?.moduleGraph ?? devServer.moduleGraph;
|
|
473
528
|
const invalidate = (file) => {
|
|
474
529
|
const ctx = builder.context;
|
|
475
530
|
if (!ctx) return;
|
|
476
531
|
if (!ctx.getFiles().some((f) => ctx.runtime.path.abs(ctx.config.cwd, f) === file)) return;
|
|
532
|
+
prebuilt = void 0;
|
|
477
533
|
const mod = server?.moduleGraph.getModuleById(RESOLVED_ID);
|
|
478
534
|
if (!mod) return;
|
|
535
|
+
if (clientGraph.getModulesByFile(file)?.size) return;
|
|
479
536
|
server?.moduleGraph.invalidateModule(mod);
|
|
480
537
|
server?.reloadModule(mod);
|
|
481
538
|
logger.debug("vite", `styles invalidated by ${file}`);
|
|
@@ -3206,21 +3263,33 @@ const bamboocss = (options = {}) => {
|
|
|
3206
3263
|
/**
|
|
3207
3264
|
* Modules to re-transform because `file` changed, hard-invalidated on the way out.
|
|
3208
3265
|
*
|
|
3209
|
-
*
|
|
3210
|
-
*
|
|
3211
|
-
*
|
|
3266
|
+
* Invalidating is the fix. It drops the stale compiled result, which is the defect itself,
|
|
3267
|
+
* and it has to happen here rather than being left to `updateModules`: Vite *soft*-
|
|
3268
|
+
* invalidates an importer that statically imports the changed module, and a soft invalidation
|
|
3269
|
+
* keeps the cached transform — the very place the compiled class string lives.
|
|
3270
|
+
*
|
|
3271
|
+
* Doing it here also survives another plugin filtering the list afterwards — a framework's
|
|
3272
|
+
* own `hotUpdate` decides what its route modules do, and the stale bytes have to go either
|
|
3273
|
+
* way.
|
|
3274
|
+
*
|
|
3275
|
+
* *Naming* those modules back to Vite is a different question, and the answer is almost
|
|
3276
|
+
* always no. `addWatchFile` makes every consumer a direct importer of the dependency in the
|
|
3277
|
+
* module graph, so `propagateUpdate` walks to all of them from the changed file by itself and
|
|
3278
|
+
* sends exactly the same update. Returning them as well does not merge into that pass: a
|
|
3279
|
+
* framework plugin downstream reads the list and re-drives HMR per entry — react-router's
|
|
3280
|
+
* `react-router-server-change-trigger-client-hmr` calls `reloadModule` once per module, in
|
|
3281
|
+
* both its client and its ssr pass — and each of those is a separate `updateModules`, a
|
|
3282
|
+
* separate `hmr update`, and a separate refetch of the whole module by the browser.
|
|
3212
3283
|
*
|
|
3213
|
-
*
|
|
3214
|
-
*
|
|
3215
|
-
*
|
|
3284
|
+
* Measured on a five-route react-router app, one `css()` edit in a shared `ui.ts`: eight
|
|
3285
|
+
* `hmr update` messages, `root.tsx` and `dashboard.tsx` fetched five times each, 554 kB over
|
|
3286
|
+
* the socket for a one-line edit. Dropping the redundant half takes it to four messages and
|
|
3287
|
+
* 367 kB with the same modules re-transformed and the same edit applied.
|
|
3216
3288
|
*
|
|
3217
|
-
*
|
|
3218
|
-
*
|
|
3219
|
-
*
|
|
3220
|
-
*
|
|
3221
|
-
* have done nothing at all. That one can end in a page reload, which is the honest outcome:
|
|
3222
|
-
* its compiled classes really did change, and a reload is what Vite does with any update
|
|
3223
|
-
* nothing accepts.
|
|
3289
|
+
* So the list is returned only when Vite has matched nothing for the file and would otherwise
|
|
3290
|
+
* do nothing at all — a dependency the fold read that never became a module of its own. That
|
|
3291
|
+
* one can end in a page reload, which is the honest outcome: its compiled classes really did
|
|
3292
|
+
* change, and a reload is what Vite does with any update nothing accepts.
|
|
3224
3293
|
*/
|
|
3225
3294
|
const foldDependentModules = (file, modules, graph) => {
|
|
3226
3295
|
const dependents = dependentsByDependency.get(normalizeFsPath(file));
|
|
@@ -3232,6 +3301,7 @@ const bamboocss = (options = {}) => {
|
|
|
3232
3301
|
added.push(module);
|
|
3233
3302
|
}
|
|
3234
3303
|
if (!added.length) return;
|
|
3304
|
+
if (modules.length) return;
|
|
3235
3305
|
return [...modules, ...added];
|
|
3236
3306
|
};
|
|
3237
3307
|
let ctx;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bamboocss/vite",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.40.1",
|
|
4
4
|
"description": "Vite integration for Bamboo CSS",
|
|
5
5
|
"homepage": "https://bamboocss.com",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,18 +40,18 @@
|
|
|
40
40
|
"postcss": "8.5.26",
|
|
41
41
|
"postcss-selector-parser": "7.1.5",
|
|
42
42
|
"ts-morph": "28.0.0",
|
|
43
|
-
"@bamboocss/config": "1.
|
|
44
|
-
"@bamboocss/extractor": "1.
|
|
45
|
-
"@bamboocss/
|
|
46
|
-
"@bamboocss/
|
|
47
|
-
"@bamboocss/node": "1.
|
|
48
|
-
"@bamboocss/shared": "1.
|
|
49
|
-
"@bamboocss/types": "1.
|
|
43
|
+
"@bamboocss/config": "1.40.1",
|
|
44
|
+
"@bamboocss/extractor": "1.40.1",
|
|
45
|
+
"@bamboocss/logger": "1.40.1",
|
|
46
|
+
"@bamboocss/core": "1.40.1",
|
|
47
|
+
"@bamboocss/node": "1.40.1",
|
|
48
|
+
"@bamboocss/shared": "1.40.1",
|
|
49
|
+
"@bamboocss/types": "1.40.1"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@jridgewell/trace-mapping": "^0.3.31",
|
|
53
53
|
"vite": "7.2.6",
|
|
54
|
-
"@bamboocss/fixture": "1.
|
|
54
|
+
"@bamboocss/fixture": "1.40.1"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"vite": ">=5"
|