Skip to content

@nativescript/vite: native dev bridge drops ?raw from SVG imports #11550

Open

Description

@aleclarson

Native dev HTTP-ESM serving loses the ?raw semantics of SVG imports. The module received on the device exports an asset URL instead of the SVG XML string, breaking code that relies on Vite's raw-import contract.

Environment

  • @nativescript/vite: 8.0.17
  • Vite: 8.3.0
  • NativeScript CLI / Android runtime: 9.1.1
  • @nativescript/core: 9.1.3
  • Android development run from macOS, using pnpm
  • Consumer uses Octane Xplat 0.15.0 (e3545c95) and its canonical NativeScript Vite dependency patch. The HTTP behavior below was verified in that setup; a standalone unpatched NativeScript app has not been retested.

Minimal import shape

In a NativeScript Vite app, add an SVG and import it as text from an entry-reachable module:

<!-- src/icon.svg -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1 1"><path d="M0 0h1v1H0z"/></svg>
// src/svg-repro.ts — import this module from the app entry
import rawSvg from './icon.svg?raw'
export { rawSvg }

Run the native dev server (pnpm exec ns run android) and inspect the served importer and asset module:

curl 'http://127.0.0.1:5173/ns/m/src/svg-repro.ts'
curl 'http://127.0.0.1:5173/ns/m/src/icon.svg?raw'

These snippets illustrate the minimal import shape; the actual HTTP checks used equivalent SVG imports in the existing consumer rather than a fresh standalone project.

Expected

The SVG module's default export is the SVG XML string. The importer and /ns/m handler preserve the semantic raw query when requesting Vite's transform, independently of any HMR version query.

Observed

Two behaviors were verified through actual native dev HTTP responses:

  1. An importer containing import icon from './icon.svg?raw' is served with an import equivalent to import icon from '/ns/m/src/icon.svg', without ?raw.
  2. Even directly requesting /ns/m/src/icon.svg?raw returns a module exporting an asset value instead of XML: data:image/svg+xml,... for an inlined SVG, or a root-relative path such as /src/assets/icon.svg for a non-inlined SVG.

This causes a concrete Android failure when consumer code converts the presumed XML into a data URI. A value that is already a URI becomes double-encoded. Octane's SVG source normalizer decodes once, leaving the literal data:image/svg+xml,... string for AndroidSVG's XML parser:

Unhandled promise rejection:
org.xmlpull.v1.XmlPullParserException: Unexpected token (position:TEXT data:image/svg+x...)
getSVG(.../ui-svg/src/index.android:72:38)
at handleSrc(.../ui-svg/src/index.android:200:37)

Relevant source

createNsMRequestContext currently obtains spec from the pathname or path query, reads v separately, and strips query/hash content from spec. The raw flag does not reach the transform candidates. Import rewriting also needs to retain semantic queries; fixing only the inbound handler would leave the importer's query loss.

This source observation is separate from the verified behavior in the patched consumer; I have not run a clean current-main native app.

Consumer workaround and validation

The app now preserves existing SVG data URIs, resolves root-relative dev asset URLs against the HTTP module URL so the framework can fetch XML, and only data-encodes actual XML input. Source probes for imports from four asset groups then produced valid XML, and regression tests cover raw XML, existing percent/base64 data URIs, and non-inlined dev URLs. Android rendering has not been retested after the workaround.

A bridge regression test should cover both small/inlined and larger/non-inlined SVG imports, including ?raw combined with an HMR version parameter. Both should export XML, without requiring consumers to accommodate a different type of value in native dev.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions