diff --git a/src/builders/rollup/config.ts b/src/builders/rollup/config.ts index 2ee9a60b..bd331537 100644 --- a/src/builders/rollup/config.ts +++ b/src/builders/rollup/config.ts @@ -155,7 +155,16 @@ export function getRollupOptions(ctx: BuildContext): RollupOptions { ctx.options.rollup.preserveDynamicImports && { name: "unbuild=preserve-dynamic-imports", - renderDynamicImport(): { left: string; right: string } { + renderDynamicImport({ + targetModuleId, + targetChunk, + }: { + targetModuleId?: string | null; + targetChunk?: unknown; + }): { left: string; right: string } | null { + if (targetModuleId || targetChunk) { + return null; + } return { left: "import(", right: ")" }; }, }, diff --git a/test/rollup.test.ts b/test/rollup.test.ts new file mode 100644 index 00000000..cc6da8af --- /dev/null +++ b/test/rollup.test.ts @@ -0,0 +1,63 @@ +import { describe, it, expect } from "vitest"; +import { getRollupOptions } from "../src/builders/rollup/config"; +import type { BuildContext } from "../src/types"; + +describe("preserveDynamicImports", () => { + it("preserves external dynamic imports but delegates internal chunks to Rollup", () => { + const ctx = { + options: { + rootDir: "/root", + entries: [], + alias: {}, + replace: {}, + rollup: { + replace: false, + alias: false, + resolve: false, + json: false, + esbuild: false, + commonjs: false, + preserveDynamicImports: true, + cjsBridge: false, + dts: {}, + }, + }, + pkg: {}, + buildEntries: [], + usedImports: new Set(), + warnings: new Set(), + hooks: {} as any, + } as unknown as BuildContext; + + const rollupOptions = getRollupOptions(ctx); + const plugin = rollupOptions.plugins?.find( + (p: any) => p && p.name === "unbuild=preserve-dynamic-imports", + ) as any; + + expect(plugin).toBeDefined(); + + // External import (targetModuleId is null) should be preserved as import(...) + expect( + plugin.renderDynamicImport({ + targetModuleId: null, + targetChunk: null, + }), + ).toEqual({ left: "import(", right: ")" }); + + // Internal chunk by targetModuleId should return null so Rollup emits appropriate loader (e.g. require in CJS) + expect( + plugin.renderDynamicImport({ + targetModuleId: "/root/src/plugin.ts", + targetChunk: null, + }), + ).toBeNull(); + + // Internal chunk by targetChunk should also return null + expect( + plugin.renderDynamicImport({ + targetModuleId: null, + targetChunk: { fileName: "chunks/plugin.cjs" }, + }), + ).toBeNull(); + }); +});