Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/strip-entry-module-url.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@solidjs/vite-plugin': patch
---

SSR builds no longer export `$$moduleUrl` from entry chunks, so a Cloudflare Worker whose `main` is a project module starts again in workerd.
35 changes: 35 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1334,6 +1334,23 @@ export default function solidPlugin(options: Partial<Options> = {}): Plugin[] {
return code + `\nexport const $$moduleUrl = ${JSON.stringify(relativeId)};\n`;
}

// Pads removed specifiers with spaces so the chunk's source map stays valid.
function stripModuleUrlExport(code: string): string | null {
const clause = /export\s*\{([^}]*)\}\s*;?(?=(?:\s|\/\/[^\n]*|\/\*[\s\S]*?\*\/)*$)/.exec(code);
if (!clause) return null;
const specifiers = clause[1].split(',');
const kept = specifiers.filter(
(spec) => !/^\s*(?:[\w$]+\s+as\s+)?(?:\$\$moduleUrl|(["'])\$\$moduleUrl\1)\s*$/.test(spec),
);
if (kept.length === specifiers.length) return null;
const start = clause.index + clause[0].indexOf('{') + 1;
return (
code.slice(0, start) +
kept.join(',').padEnd(clause[1].length) +
code.slice(start + clause[1].length)
);
}

function nativeTsrxCss(result: unknown): string {
const css = (result as { css?: unknown }).css;
return typeof css === 'string' ? css : '';
Expand Down Expand Up @@ -2070,6 +2087,24 @@ export default manifest;`;
},
},

renderChunk(code, chunk, outputOptions) {
// Hosts re-export server entries whole, and workerd rejects non-handler exports.
if (!isBuild || isClientBuild(this) || outputOptions.format !== 'es') return null;
if (!chunk.isEntry || !chunk.exports.includes('$$moduleUrl')) return null;
const build = this.environment?.config?.build;
const input = build?.lib
? build.lib.entry
: typeof build?.ssr === 'string'
? build.ssr
: configuredBuildInput(build);
if (!resolveConfiguredEntries(input, projectRoot).isEntryModule(chunk.facadeModuleId))
return null;
const facade = this.getModuleInfo(chunk.facadeModuleId!);
if (facade?.importers.length || facade?.dynamicImporters.length) return null;
const stripped = stripModuleUrlExport(code);
return stripped === null ? null : { code: stripped, map: null };
},

generateBundle(outputOptions, bundle) {
if (!isBuild || !isClientBuild(this)) return;
clientOutDir = outputOptions.dir ?? null;
Expand Down
Loading