Skip to content

Support for Vite Virtual Files Convention in Embroider #2529

@josemarluedke

Description

@josemarluedke

Embroider should support the standard Vite virtual files convention (virtual: prefix) to allow v2 addons to import virtual files emitted by Vite plugins.

Current Issue

In docfy, we have a Vite plugin that emits a virtual file virtual:docfy/output and this file gets imported by a v2 addon. This currently causes the error below. (at end of the issue)

Background

The virtual: prefix is the standard convention for virtual modules in Vite, where plugins can create files that don't physically exist on disk but can be imported and used by other modules. Internally, plugins that use virtual modules should prefix the module ID with \0 while resolving the id, a convention from the rollup ecosystem, but the user-facing convention is the virtual: prefix.

Use Case

Our docfy plugin needs to:

  1. Generate dynamic content based on documentation files
  2. Emit this content as a virtual file virtual:docfy/output
  3. Allow v2 addons to import this virtual file to consume the generated content

This pattern is common in the Vite ecosystem and enables powerful build-time code generation and transformation workflows.

Proposed Solution

Embroider should not prevent other plugins from resolving imports that use the virtual: prefix convention, allowing them to be handled by the appropriate Vite plugins in the build pipeline.

Reproduction

A minimal reproduction of this issue can be found at: https://github.com/josemarluedke/--docfy-vite-test

Appendix

Vite docs: https://vite.dev/guide/api-plugin.html#importing-a-virtual-file

Error:

✘ [ERROR] @docfy/ember is trying to import from virtual:docfy but that is not one of its explicit dependencies [plugin embroider-esbuild-resolver]

    node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@embroider/core/dist/src/module-resolver.js:857:18:
      857 │             throw new Error(`${pkg.name} is trying to import from ${packageName} but that is not one of its explicit dependencies`);
          ╵                   ^

    at Resolver.preHandleExternal (/Users/jluedke/code/oss/site/node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@embroider/core/dist/src/module-resolver.js:857:19)
    at Resolver.beforeResolve (/Users/jluedke/code/oss/site/node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@embroider/core/dist/src/module-resolver.js:82:24)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async Resolver.resolve (/Users/jluedke/code/oss/site/node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@embroider/core/dist/src/module-resolver.js:94:19)
    at async file:///Users/jluedke/code/oss/site/node_modules/.pnpm/@[email protected]_@[email protected]_@[email protected]__@[email protected]._bef50ffead4dbad31fc3ae1c844682dd/node_modules/@embroider/vite/dist/src/esbuild-resolver.js:72:34
    at async requestCallbacks.on-resolve (/Users/jluedke/code/oss/site/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1217:22)
    at async handleRequest (/Users/jluedke/code/oss/site/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:628:11)

  This error came from the "onResolve" callback registered here:

    node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1141:20:
      1141 │       let promise = setup({
           ╵                     ^

    at setup (file:///Users/jluedke/code/oss/site/node_modules/.pnpm/@[email protected]_@[email protected]_@[email protected]__@[email protected]._bef50ffead4dbad31fc3ae1c844682dd/node_modules/@embroider/vite/dist/src/esbuild-resolver.js:58:19)
    at handlePlugins (/Users/jluedke/code/oss/site/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1141:21)
    at buildOrContextImpl (/Users/jluedke/code/oss/site/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:854:5)
    at Object.buildOrContext (/Users/jluedke/code/oss/site/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:680:5)
    at /Users/jluedke/code/oss/site/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:2035:68
    at new Promise (<anonymous>)
    at Object.context (/Users/jluedke/code/oss/site/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:2035:27)
    at Object.context (/Users/jluedke/code/oss/site/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1877:58)
    at prepareEsbuildOptimizerRun (file:///Users/jluedke/code/oss/site/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected][email protected][email protected]/node_modules/vite/dist/node/chunks/dep-Bg4HVnP5.js:11386:32)

  The plugin "embroider-esbuild-resolver" was triggered by this import

    node_modules/.pnpm/@[email protected]_@[email protected]_@[email protected][email protected]_@[email protected][email protected]_/node_modules/@docfy/ember/dist/services/docfy.js:3:19:
      3 │ import output from 'virtual:docfy/output';

/Users/jluedke/code/oss/site/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1467
  let error = new Error(text);
              ^

Error: Build failed with 1 error:
node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@embroider/core/dist/src/module-resolver.js:857:18: ERROR: [plugin: embroider-esbuild-resolver] @docfy/ember is trying to import from virtual:docfy but that is not one of its explicit dependencies
    at failureErrorWithLog (/Users/jluedke/code/oss/site/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1467:15)
    at /Users/jluedke/code/oss/site/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:926:25
    at /Users/jluedke/code/oss/site/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1345:9
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5) {
  errors: [Getter/Setter],
  warnings: [Getter/Setter]
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions