Skip to content

feat: support full bundle mode in ssr#21626

Draft
sheremet-va wants to merge 22 commits intovitejs:mainfrom
sheremet-va:fix/support-full-bundle-mode-in-ssr
Draft

feat: support full bundle mode in ssr#21626
sheremet-va wants to merge 22 commits intovitejs:mainfrom
sheremet-va:fix/support-full-bundle-mode-in-ssr

Conversation

@sheremet-va
Copy link
Member

@sheremet-va sheremet-va commented Feb 12, 2026

I am exploring how full bundle mode can be supported in SSR. At the moment the goal is to support environments.ssr.runner.import and environment.fetchModule. Module graph, transformRequest, pluginContainer are out of scope of this PR, but they will be revisited later.

Known quirks (to discuss)

  • url in runner.import(url) is not resolved with resolveId like it is done usually. Instead it accepts:
    • Absolute URL to the bundled entry point specified in rolldownOptions.input
    • Relative URL (relative to root) to the bundled entry point
    • The chunk name
    • Relative URL to the bundled entry point starting with / (/entry-point.js vs ./entry-point.js)
    • The url must be an actual filename or a URL with the extension at the end
  • import.meta.url, import.meta.filename and import.meta.dirname reference "would be" (or "virtual") files, these are the URLs that would exist if vite kept the bundle on the file system. Doing something like readFileSync(import.meta.filename) will throw an error because the file does not exist on disk
    • For example for the build configuration like { ourDir: './dist' }, the filename would be something like <root>/dist/asset/chunk-1.js

@sheremet-va sheremet-va changed the title feat: support ful bundle mode in ssr feat: support full bundle mode in ssr Feb 12, 2026
@jamesopstad
Copy link
Contributor

Very excited to see the beginnings of this!

const href = posixPathToFileHref(modulePath)
const filename = modulePath
const dirname = posixDirname(modulePath)
const isVirtual = modulePath.startsWith('data:application/javascript,')
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what Node returns in import.meta.url if it runs in REPL or inside --import=data/application. I think we can reuse this idea

import.meta.dirname and filename are also not available there since files are virtual

But it will be quite inconvenient at runtime

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another idea is to use the file where it would be bundled. However then something like readFileSync(import.meta.filename) will throw an error

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to go with the second approach for now to avoid any breaking changes

dep = String(dep)
if (dep[0] === '.') {
dep = posixResolve(posixDirname(url), dep)
dep = posixJoin(posixDirname(url), dep)
Copy link
Member Author

@sheremet-va sheremet-va Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolve always adds process.cwd() at the start, but we are resolving ./file1.js relative to asset/parent.js

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants