Repository navigation
Description
Native dev drops import 'virtual:bamboo.css', leaving generated component styles unloaded and the app layout broken.
There are two parts to the failure: the import disappears, and requesting the stylesheet directly returns raw CSS instead of a native CSS registration module.
Reproduction and observed behavior
With the app importing virtual:bamboo.css, compare these dev-server responses:
| Request | Response |
|---|---|
/src/main.ts |
Includes import "/@id/__x00__virtual:bamboo.css"; |
/ns/m/src/main.ts |
Bamboo import is missing; ordinary file CSS imports remain |
/ns/m/@id/__x00__virtual:bamboo.css |
HTTP 200 with raw CSS, including generated rules and @layer xplat.reset, xplat.base, xplat.tokens, xplat.utilities; |
These were checked against the running server at http://127.0.0.1:5173.
The installed astNormalizeModuleImportsAndHelpers also reproduces the removal independently:
// Input
import "/@id/__x00__virtual:bamboo.css";
export const mounted = true;
// Output
/* [ast-normalized] */
export const mounted = true;In ast-normalizer.ts, isViteVirtual matches null/__x00__ IDs except the OXC helper exemption, and the import visitor removes them. The same filtering is present on upstream main by source inspection.
Expected behavior
Preserve user virtual stylesheet imports and pass their CSS through native adaptation/registration. Preserving the import alone will not fix the raw-CSS response. Keep filtering specific to unsupported browser helpers.
A regression test should load a plugin-provided virtual stylesheet that sizes a native view, alongside ordinary file CSS and CSS HMR coverage.
Environment and limits
@nativescript/vite8.0.17, with Octane Xplat's canonical dependency patch- Vite 8.3.0;
@nativescript/core9.1.3; Android runtime/CLI 9.1.1 - Octane Xplat 0.15.0 (
e3545c95); Bamboo 1.56.2; macOS; pnpm
Verified in Android HTTP dev and with the installed normalizer. A clean unpatched NativeScript app and iOS HTTP dev have not been tested. No workaround has been applied.
Supporting layout measurements
Android's last laid-out hierarchy had a roughly 698 dp wide bottom bar (declared maximum 353 dp) at the top, with SVGs around 233×82 dp (declared 31×36 and 54×54 dp).
These came from 72 native views via adb shell dumpsys activity <app-id>, at 520 dpi (3.25 px/dp). The activity was backgrounded/stopped, and component mapping was inferred from tree structure/source order. The HTTP responses and normalizer reproduction above are the primary evidence.
A bundled Debug build on iPhone 18 Pro / iOS 27 has the expected 31×36 and 54×54 pt icon sizes. This is a different platform and serving mode; it does not establish that the HTTP-dev failure is Android-specific. Measurements used native bounds without screenshots or text/input values.
Related: #11472 concerns ordinary workspace CSS and __vite__updateStyle; #11461 concerns core cascade layers. Here, the stylesheet fails to reach native registration first.
Activity
aleclarson commentedon Oct 19, 2026
Confirmed with a minimal Vite plugin (no Bamboo compiler or application layout involved), using
@nativescript/vite8.0.17 and Vite 8.3.0. The 8.0.19 source and current main still have the broadisViteVirtualfilter.There are additional stages to account for beyond the two in the report:
processCodeForDevicehas a later/@id/import sanitizer. Exempting stylesheet modules only inastNormalizeModuleImportsAndHelpersstill drops them here. Both side-effect and default stylesheet imports need to survive, andrewriteImportsmust route them through/ns/m./@id/early return runs before the native CSS handler. Excluding stylesheets from that shortcut lets them reach native registration. Before callingtransformRequest, unwrap/@id/__x00__...to its actual null-prefixed plugin ID. Passing the encoded URL directly totransformRequest(...?inline)can produceERR_DENIED_ID/a transform miss: Vite's normal HTTP middleware ordinarily does that unwrapping.?inlineis insufficient for HMR. The canonical stylesheet must also have its transform/watch edges and self-accepting CSS boundary populated, since plugins reload that node. A plugin can invalidate just the canonical node, leaving an old inline sibling cached. NativeScript's extra transform-result TTL cache can also retain the previous sheet. Our temporary patch refreshes the inline sibling and uses Vite directly for virtual CSS compilation.reloadModuleemitted ajs-updatefor the virtual.cssmodule in this fixture./ns-hmrcurrently discards stockupdatemessages. We translate just virtual stylesheet updates intons:css-updates, fetching adapted text through/ns/m/...?...direct=1and using the original module URL as the tag. Raw null IDs and/@id/__x00__paths need the same canonical tag.The focused regression starts real Vite HTTP serving with
registerNsModuleServerRoute, preserves browser-helper filtering, executes the returned registration JavaScript (including the pending-registration fallback), checks ordinary file CSS, and tests virtual reloads while leaving the inline/result caches populated. It then feeds the resulting update into the actual clienthandleCssUpdatesagainst a host API double to verify tagged replacement and clearing without touchingapp.css.With the framework's existing native CSS adapter enabled, the HTTP registration payload contains
.fixed { width: 31dip; height: 36dip; }, with layers/platform blocks adapted. The dev adapter must run after Bamboo's load-time validation; build-time output validation/adaptation ordering remains separate.These are HTTP/host-execution findings, not device rendering evidence. No Android/iOS layout smoke is claimed. The temporary patch stays in Octane Xplat's existing dependency-patch distribution; no app-specific workaround is needed.
aleclarson commentedon Oct 19, 2026
Consumer verification after upgrading Opals to octane-xplat v0.16.0 with its canonical NativeScript dependency patches:
/ns/m/src/main.tsnow preserves the Bamboo import, and/ns/m/@id/__x00__virtual:bamboo.cssreturns JavaScript calling__NS_REGISTER_CSS__(or queuing pending CSS), with platform-filtered CSS and DIP units. This verifies the framework-carried mitigation against @nativescript/vite 8.0.17. The framework release is https://github.com/octane-xplat/octane-xplat/releases/tag/v0.16.0 .