Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(bundling): rollup should support ESM config files #21999

Merged
merged 1 commit into from
Feb 28, 2024
Merged
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
44 changes: 43 additions & 1 deletion e2e/rollup/src/rollup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
import { join } from 'path';

describe('Rollup Plugin', () => {
beforeAll(() => newProject());
beforeAll(() => newProject({ packages: ['@nx/rollup', '@nx/js'] }));
afterAll(() => cleanupProject());

it('should be able to setup project to build node programs with rollup and different compilers', async () => {
Expand Down Expand Up @@ -119,4 +119,46 @@ describe('Rollup Plugin', () => {
runCLI(`generate @nx/js:lib ${jsLib} --bundler rollup`);
expect(() => runCLI(`build ${jsLib}`)).not.toThrow();
});

it('should be able to build libs generated with @nx/js:lib --bundler rollup with a custom rollup.config.{cjs|mjs}', () => {
const jsLib = uniq('jslib');
runCLI(`generate @nx/js:lib ${jsLib} --bundler rollup`);
updateFile(
`libs/${jsLib}/rollup.config.cjs`,
`module.exports = {
output: {
format: "cjs",
dir: "dist/test",
name: "Mylib",
entryFileNames: "[name].cjs.js",
chunkFileNames: "[name].cjs.js"
}
}`
);
updateJson(join('libs', jsLib, 'project.json'), (config) => {
config.targets.build.options.rollupConfig = `libs/${jsLib}/rollup.config.cjs`;
return config;
});
expect(() => runCLI(`build ${jsLib}`)).not.toThrow();
checkFilesExist(`dist/test/index.cjs.js`);

updateFile(
`libs/${jsLib}/rollup.config.mjs`,
`export default {
output: {
format: "es",
dir: "dist/test",
name: "Mylib",
entryFileNames: "[name].mjs.js",
chunkFileNames: "[name].mjs.js"
}
}`
);
updateJson(join('libs', jsLib, 'project.json'), (config) => {
config.targets.build.options.rollupConfig = `libs/${jsLib}/rollup.config.mjs`;
return config;
});
expect(() => runCLI(`build ${jsLib}`)).not.toThrow();
checkFilesExist(`dist/test/index.mjs.js`);
});
});
32 changes: 19 additions & 13 deletions packages/rollup/src/executors/rollup/rollup.impl.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { ExecutorContext } from '@nx/devkit';
import * as fs from 'fs';
import * as rollup from 'rollup';
import { RollupExecutorOptions } from './schema';
import { createRollupOptions } from './rollup.impl';
import { normalizeRollupExecutorOptions } from './lib/normalize';

jest.mock('rollup-plugin-copy', () => jest.fn());

jest.mock('fs', () => ({
...jest.requireActual('fs'),
readdirSync: () => [],
}));
describe('rollupExecutor', () => {
let context: ExecutorContext;
let testOptions: RollupExecutorOptions;
Expand Down Expand Up @@ -35,8 +39,8 @@ describe('rollupExecutor', () => {
});

describe('createRollupOptions', () => {
it('should create rollup options for valid config', () => {
const result: any = createRollupOptions(
it('should create rollup options for valid config', async () => {
const result: any = await createRollupOptions(
normalizeRollupExecutorOptions(
testOptions,
{ root: '/root' } as any,
Expand Down Expand Up @@ -73,7 +77,7 @@ describe('rollupExecutor', () => {
() => (o) => ({ ...o, prop: 'my-val' }),
{ virtual: true }
);
const result: any = createRollupOptions(
const result: any = await createRollupOptions(
normalizeRollupExecutorOptions(
{ ...testOptions, rollupConfig: 'custom-rollup.config.ts' },
{ root: '/root' } as any,
Expand All @@ -85,6 +89,7 @@ describe('rollupExecutor', () => {
'/root/src',
[]
);

expect(result.map((x) => x.prop)).toEqual(['my-val', 'my-val']);
});

Expand All @@ -103,7 +108,7 @@ describe('rollupExecutor', () => {
}),
{ virtual: true }
);
const result: any = createRollupOptions(
const result: any = await createRollupOptions(
normalizeRollupExecutorOptions(
{
...testOptions,
Expand All @@ -121,15 +126,16 @@ describe('rollupExecutor', () => {
'/root/src',
[]
);

expect(result.map((x) => x.prop1)).toEqual([
'my-val-my-val-2',
'my-val-my-val-2',
]);
expect(result.map((x) => x.prop2)).toEqual(['my-val-2', 'my-val-2']);
});

it(`should always use forward slashes for asset paths`, () => {
createRollupOptions(
it(`should always use forward slashes for asset paths`, async () => {
await createRollupOptions(
{
...normalizeRollupExecutorOptions(
testOptions,
Expand All @@ -156,8 +162,8 @@ describe('rollupExecutor', () => {
});
});

it(`should treat npm dependencies as external if external is all`, () => {
const options = createRollupOptions(
it(`should treat npm dependencies as external if external is all`, async () => {
const options = await createRollupOptions(
normalizeRollupExecutorOptions(
{ ...testOptions, external: 'all' },
{ root: '/root' } as any,
Expand All @@ -177,8 +183,8 @@ describe('rollupExecutor', () => {
expect(external('rxjs', '', false)).toBe(false);
});

it(`should not treat npm dependencies as external if external is none`, () => {
const options = createRollupOptions(
it(`should not treat npm dependencies as external if external is none`, async () => {
const options = await createRollupOptions(
normalizeRollupExecutorOptions(
{ ...testOptions, external: 'none' },
{ root: '/root' } as any,
Expand All @@ -198,8 +204,8 @@ describe('rollupExecutor', () => {
expect(external('rxjs', '', false)).toBe(false);
});

it(`should set external based on options`, () => {
const options = createRollupOptions(
it(`should set external based on options`, async () => {
const options = await createRollupOptions(
normalizeRollupExecutorOptions(
{ ...testOptions, external: ['rxjs'] },
{ root: '/root' } as any,
Expand Down
40 changes: 33 additions & 7 deletions packages/rollup/src/executors/rollup/rollup.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { analyze } from './lib/analyze-plugin';
import { deleteOutputDir } from '../../utils/fs';
import { swc } from './lib/swc-plugin';
import { updatePackageJson } from './lib/update-package-json';
import { loadConfigFile } from '@nx/devkit/src/utils/config-utils';

export type RollupExecutorEvent = {
success: boolean;
Expand Down Expand Up @@ -74,7 +75,7 @@ export async function* rollupExecutor(
.filter((d) => d.target.startsWith('npm:'))
.map((d) => d.target.slice(4));

const rollupOptions = createRollupOptions(
const rollupOptions = await createRollupOptions(
options,
dependencies,
context,
Expand Down Expand Up @@ -155,14 +156,14 @@ export async function* rollupExecutor(

// -----------------------------------------------------------------------------

export function createRollupOptions(
export async function createRollupOptions(
options: NormalizedRollupExecutorOptions,
dependencies: DependentBuildableProjectNode[],
context: ExecutorContext,
packageJson: PackageJson,
sourceRoot: string,
npmDeps: string[]
): rollup.InputOptions[] {
): Promise<rollup.InputOptions[]> {
const useBabel = options.compiler === 'babel';
const useTsc = options.compiler === 'tsc';
const useSwc = options.compiler === 'swc';
Expand Down Expand Up @@ -195,7 +196,7 @@ export function createRollupOptions(
options.format = ['cjs'];
}

return options.format.map((format, idx) => {
const _rollupOptions = options.format.map(async (format, idx) => {
// Either we're generating only one format, so we should bundle types
// OR we are generating dual formats, so only bundle types for CJS.
const shouldBundleTypes = options.format.length === 1 || format === 'cjs';
Expand Down Expand Up @@ -310,10 +311,35 @@ export function createRollupOptions(
plugins,
};

return options.rollupConfig.reduce((currentConfig, plugin) => {
return require(plugin)(currentConfig, options);
}, rollupConfig);
const userDefinedRollupConfigs = options.rollupConfig.map((plugin) =>
loadConfigFile(plugin)
);
let finalConfig: rollup.InputOptions = rollupConfig;
for (const _config of userDefinedRollupConfigs) {
const config = await _config;
if (typeof config === 'function') {
finalConfig = config(finalConfig, options);
} else {
finalConfig = {
...finalConfig,
...config,
plugins: [
...(finalConfig.plugins?.length > 0 ? finalConfig.plugins : []),
...(config.plugins?.length > 0 ? config.plugins : []),
],
};
}
}

return finalConfig;
});

const rollupOptions = [];
for (const rollupOption of _rollupOptions) {
rollupOptions.push(await rollupOption);
}

return rollupOptions;
}

function createTsCompilerOptions(
Expand Down