Skip to content

Commit bbe8f31

Browse files
authored
Merge pull request #317 from DataDog/sdkennedy2/inline-dynamic-imports-shared-config
[APPS] Use manualChunks for self-contained backend function builds
2 parents 2b3b6ab + 3877b11 commit bbe8f31

4 files changed

Lines changed: 34 additions & 45 deletions

File tree

packages/plugins/apps/src/vite/build-backend-functions.ts

Lines changed: 31 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -28,55 +28,46 @@ export async function buildBackendFunctions(
2828
): Promise<string> {
2929
const outDir = await mkdtemp(path.join(tmpdir(), 'dd-apps-backend-'));
3030

31-
const virtualEntries: Record<string, string> = {};
32-
const input: Record<string, string> = {};
31+
log.debug(`Building ${functions.length} backend function(s) via vite.build()`);
3332

33+
// Build each function individually so that each output is a single
34+
// self-contained JS file
3435
for (const func of functions) {
3536
const virtualId = `${VIRTUAL_PREFIX}${func.name}`;
36-
virtualEntries[virtualId] = generateVirtualEntryContent(
37-
func.name,
38-
func.entryPath,
39-
buildRoot,
40-
);
41-
input[func.name] = virtualId;
42-
}
43-
44-
log.debug(`Building ${functions.length} backend function(s) via vite.build()`);
37+
const virtualContent = generateVirtualEntryContent(func.name, func.entryPath, buildRoot);
4538

46-
const baseConfig = getBaseBackendBuildConfig(buildRoot, virtualEntries);
39+
const baseConfig = getBaseBackendBuildConfig(buildRoot, { [virtualId]: virtualContent });
4740

48-
// Production: build all functions in one vite.build() call, writing each to
49-
// disk as a named file so the archive/upload step can collect them.
50-
// Uses multi-entry input (one per function) with \0-prefixed virtual IDs —
51-
// the \0 convention prevents other plugins from processing these IDs.
52-
const result = await viteBuild({
53-
...baseConfig,
54-
build: {
55-
...baseConfig.build,
56-
write: true,
57-
outDir,
58-
emptyOutDir: false,
59-
rollupOptions: {
60-
...baseConfig.build.rollupOptions,
61-
input,
62-
output: { ...baseConfig.build.rollupOptions.output, entryFileNames: '[name].js' },
41+
// eslint-disable-next-line no-await-in-loop
42+
const result = await viteBuild({
43+
...baseConfig,
44+
build: {
45+
...baseConfig.build,
46+
write: true,
47+
outDir,
48+
emptyOutDir: false,
49+
rollupOptions: {
50+
...baseConfig.build.rollupOptions,
51+
input: { [func.name]: virtualId },
52+
output: {
53+
...baseConfig.build.rollupOptions.output,
54+
entryFileNames: '[name].js',
55+
},
56+
},
6357
},
64-
},
65-
});
58+
});
6659

67-
const output = Array.isArray(result) ? result[0] : result;
60+
const output = Array.isArray(result) ? result[0] : result;
6861

69-
// viteBuild always returns RolldownOutput here since we don't set build.watch.
70-
// RolldownWatcher would only be returned if watch mode were enabled.
71-
if ('output' in output) {
72-
for (const chunk of output.output) {
73-
if (chunk.type !== 'chunk' || !chunk.isEntry) {
74-
continue;
62+
if ('output' in output) {
63+
for (const chunk of output.output) {
64+
if (chunk.type !== 'chunk' || !chunk.isEntry) {
65+
continue;
66+
}
67+
const absolutePath = path.resolve(outDir, chunk.fileName);
68+
backendOutputs.set(func.name, absolutePath);
69+
log.debug(`Backend function "${func.name}" output: ${absolutePath}`);
7570
}
76-
const funcName = chunk.name;
77-
const absolutePath = path.resolve(outDir, chunk.fileName);
78-
backendOutputs.set(funcName, absolutePath);
79-
log.debug(`Backend function "${funcName}" output: ${absolutePath}`);
8071
}
8172
}
8273

packages/plugins/apps/src/vite/build-config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export function getBaseBackendBuildConfig(
4646
minify: false,
4747
target: 'esnext',
4848
rollupOptions: {
49-
output: { format: 'es', exports: 'named' },
49+
output: { format: 'es', exports: 'named', inlineDynamicImports: true },
5050
preserveEntrySignatures: 'exports-only',
5151
treeshake: false,
5252
onwarn(warning, defaultHandler) {

packages/plugins/apps/src/vite/dev-server.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,6 @@ async function bundleBackendFunction(
7979
// bundled script to the Datadog API without writing temp files.
8080
// Uses a plain "virtual:" prefix instead of \0 because Rollup generates
8181
// empty chunks when \0-prefixed IDs are used as input entries.
82-
// inlineDynamicImports collapses everything into one chunk since we only
83-
// have a single entry (incompatible with multi-entry builds).
8482
const result = await viteBuild({
8583
...baseConfig,
8684
build: {
@@ -89,7 +87,7 @@ async function bundleBackendFunction(
8987
rollupOptions: {
9088
...baseConfig.build.rollupOptions,
9189
input: virtualId,
92-
output: { ...baseConfig.build.rollupOptions.output, inlineDynamicImports: true },
90+
output: baseConfig.build.rollupOptions.output,
9391
},
9492
},
9593
});

packages/plugins/apps/src/vite/index.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ describe('Backend Functions - getVitePlugin', () => {
4646
// eslint-disable-next-line @typescript-eslint/no-explicit-any
4747
await (plugin as any).closeBundle();
4848

49-
expect(mockViteBuild).toHaveBeenCalledTimes(1);
49+
expect(mockViteBuild).toHaveBeenCalledTimes(2);
5050
expect(defaultOptions.backendOutputs.size).toBe(2);
5151
expect(defaultOptions.backendOutputs.has('myHandler')).toBe(true);
5252
expect(defaultOptions.backendOutputs.has('otherFunc')).toBe(true);

0 commit comments

Comments
 (0)