Skip to content

Import scanner counts imports shown as code inside template literals #159

@vivek7405

Description

@vivek7405

Problem

The module-graph import scanner (packages/server/src/module-graph.js, parseFile) runs IMPORT_RE / EXPORT_FROM_RE directly on raw source with no string/template redaction. So an import '...' statement that appears as TEXT inside a template literal (e.g. example code shown in a <pre> inside an html\`` template) is mistaken for a real import, creating a phantom graph edge.

Observed live on docs.webjs.dev/docs/getting-started: the page shows import '../components/counter.ts'; as example code inside its html\`template. There is no realapp/docs/components/counter.tsfile, yet the SSR emits`, which 404s.

This hits any tutorial/docs/marketing app that displays import statements as content.

Design / approach

Reuse the existing position-preserving lexer redactStringsAndTemplates from js-scan.js as a MASK. It blanks string/template CONTENT to spaces while keeping code (including the import / export / from keywords) intact at the same offsets.

Cannot run IMPORT_RE on the redacted text directly, because the import SPECIFIER is itself a string and would be blanked (real relative imports would be missed). Instead:

  1. Compute const masked = redactStringsAndTemplates(src) once.
  2. Run IMPORT_RE / EXPORT_FROM_RE on the RAW src (so the specifier capture is intact).
  3. For each match, skip it unless masked.slice(m.index, m.index + KEYWORD_LEN) still equals the keyword (import / export). A real top-level import keeps its keyword in masked; a keyword inside a template/string body is blanked, so the phantom is dropped.

This is verdict-safe for the gate and elision too: a path that only ever appears inside a string was never a real import, so dropping it is correct everywhere the graph is consumed.

Acceptance criteria

  • An import/export ... from appearing inside a template literal or string is NOT added as a graph edge
  • Real top-level relative imports (and export ... from re-exports, including multi-line) are still detected
  • The docs /app/docs/components/counter.ts phantom preload 404 is gone
  • Unit test with a fixture page that renders import './x.ts' as template text; counterfactual fails without the mask
  • Docs / AGENTS.md updated if the scanner contract wording changed

Found alongside #158 while auditing all four in-repo dogfood apps for broken modulepreload hints (blog hit #158; docs hit this; website + ui-website were clean).

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type
No fields configured for issues without a type.

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions