Skip to content

Commit

Permalink
feat(bundling): generate matching d.ts files for rollup
Browse files Browse the repository at this point in the history
  • Loading branch information
jaysoo committed Jul 27, 2023
1 parent 1dadb3d commit edcbadf
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 102 deletions.
19 changes: 15 additions & 4 deletions e2e/rollup/src/rollup.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import {
checkFilesExist,
cleanupProject,
newProject,
readJson,
rmDist,
runCLI,
runCommand,
Expand All @@ -23,8 +25,17 @@ describe('Rollup Plugin', () => {
`generate @nx/rollup:configuration ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts`
);
rmDist();
runCLI(`build ${myPkg}`);
let output = runCommand(`node dist/libs/${myPkg}/index.cjs`);
runCLI(`build ${myPkg} --format=cjs,esm --generateExportsField`);
checkFilesExist(`dist/libs/${myPkg}/index.cjs.d.ts`);
expect(readJson(`dist/libs/${myPkg}/package.json`).exports).toMatchObject({
exports: {
'.': {
import: './index.esm.js',
default: './index.cjs.js',
},
},
});
let output = runCommand(`node dist/libs/${myPkg}/index.cjs.js`);
expect(output).toMatch(/Hello/);

updateProjectConfig(myPkg, (config) => {
Expand All @@ -38,7 +49,7 @@ describe('Rollup Plugin', () => {
);
rmDist();
runCLI(`build ${myPkg}`);
output = runCommand(`node dist/libs/${myPkg}/index.cjs`);
output = runCommand(`node dist/libs/${myPkg}/index.cjs.js`);
expect(output).toMatch(/Hello/);

updateProjectConfig(myPkg, (config) => {
Expand All @@ -52,7 +63,7 @@ describe('Rollup Plugin', () => {
);
rmDist();
runCLI(`build ${myPkg}`);
output = runCommand(`node dist/libs/${myPkg}/index.cjs`);
output = runCommand(`node dist/libs/${myPkg}/index.cjs.js`);
expect(output).toMatch(/Hello/);
}, 500000);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,12 @@ describe('updatePackageJson', () => {
expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), {
exports: {
'.': {
types: './index.d.ts',
import: './index.js',
import: './index.esm.js',
},
},
main: './index.js',
module: './index.js',
main: './index.esm.js',
module: './index.esm.js',
type: 'module',
types: './index.d.ts',
});

spy.mockRestore();
Expand All @@ -73,13 +71,11 @@ describe('updatePackageJson', () => {
expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), {
exports: {
'.': {
types: './index.d.ts',
require: './index.cjs',
default: './index.cjs.js',
},
},
main: './index.cjs',
main: './index.cjs.js',
type: 'commonjs',
types: './index.d.ts',
});

spy.mockRestore();
Expand All @@ -103,15 +99,12 @@ describe('updatePackageJson', () => {
expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), {
exports: {
'.': {
types: './index.d.ts',
import: './index.js',
require: './index.cjs',
import: './index.esm.js',
default: './index.cjs.js',
},
},
main: './index.cjs',
module: './index.js',
type: 'module',
types: './index.d.ts',
main: './index.cjs.js',
module: './index.esm.js',
});

spy.mockRestore();
Expand All @@ -132,7 +125,7 @@ describe('updatePackageJson', () => {
{
exports: {
'./foo': {
import: './foo.js',
import: './foo.esm.js',
},
},
} as unknown as PackageJson
Expand All @@ -141,17 +134,15 @@ describe('updatePackageJson', () => {
expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), {
exports: {
'.': {
types: './index.d.ts',
import: './index.js',
import: './index.esm.js',
},
'./foo': {
import: './foo.js',
import: './foo.esm.js',
},
},
main: './index.js',
module: './index.js',
main: './index.esm.js',
module: './index.esm.js',
type: 'module',
types: './index.d.ts',
});

spy.mockRestore();
Expand All @@ -174,10 +165,9 @@ describe('updatePackageJson', () => {
);

expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), {
main: './index.js',
module: './index.js',
main: './index.esm.js',
module: './index.esm.js',
type: 'module',
types: './index.d.ts',
});

spy.mockRestore();
Expand All @@ -198,9 +188,8 @@ describe('updatePackageJson', () => {
);

expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), {
main: './index.cjs',
main: './index.cjs.js',
type: 'commonjs',
types: './index.d.ts',
});

spy.mockRestore();
Expand All @@ -221,10 +210,8 @@ describe('updatePackageJson', () => {
);

expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), {
main: './index.cjs',
module: './index.js',
type: 'module',
types: './index.d.ts',
main: './index.cjs.js',
module: './index.esm.js',
});

spy.mockRestore();
Expand All @@ -244,20 +231,19 @@ describe('updatePackageJson', () => {
{
exports: {
'./foo': {
import: './foo.js',
import: './foo.esm.js',
},
},
} as unknown as PackageJson
);

expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), {
main: './index.js',
module: './index.js',
main: './index.esm.js',
module: './index.esm.js',
type: 'module',
types: './index.d.ts',
exports: {
'./foo': {
import: './foo.js',
import: './foo.esm.js',
},
},
});
Expand Down
28 changes: 10 additions & 18 deletions packages/rollup/src/executors/rollup/lib/update-package-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { writeJsonFile } from 'nx/src/utils/fileutils';
import { PackageJson } from 'nx/src/utils/package-json';
import { NormalizedRollupExecutorOptions } from './normalize';

// TODO(jack): Use updatePackageJson from @nx/js instead.
export function updatePackageJson(
options: NormalizedRollupExecutorOptions,
context: ExecutorContext,
Expand All @@ -19,40 +20,31 @@ export function updatePackageJson(
const hasEsmFormat = options.format.includes('esm');
const hasCjsFormat = options.format.includes('cjs');

const types = `./${relative(options.projectRoot, options.main).replace(
/\.[jt]sx?$/,
'.d.ts'
)}`;
const exports = {
// TS 4.5+
'.': {
types,
},
'.': {},
};

if (hasEsmFormat) {
// `module` field is used by bundlers like rollup and webpack to detect ESM.
// May not be required in the future if type is already "module".
packageJson.module = './index.js';
exports['.']['import'] = './index.js';
packageJson.module = './index.esm.js';
exports['.']['import'] = './index.esm.js';

if (!hasCjsFormat) {
packageJson.main = './index.js';
packageJson.main = './index.esm.js';
}
}

if (hasCjsFormat) {
packageJson.main = './index.cjs';
exports['.']['require'] = './index.cjs';
packageJson.main = './index.cjs.js';
exports['.']['default'] = './index.cjs.js';
}
if (!options.skipTypeField) {

// Dual format should not specify `type` field, the `exports` field resolves ESM vs CJS.
if (!options.skipTypeField && options.format.length === 1) {
packageJson.type = options.format.includes('esm') ? 'module' : 'commonjs';
}

// Support for older TS versions < 4.5
packageJson.types = types;

// TODO(jack): remove this for Nx 16
if (options.generateExportsField && typeof packageJson.exports !== 'string') {
packageJson.exports = {
...packageJson.exports,
Expand Down
20 changes: 0 additions & 20 deletions packages/rollup/src/executors/rollup/lib/validate-types.ts

This file was deleted.

8 changes: 4 additions & 4 deletions packages/rollup/src/executors/rollup/rollup.impl.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ describe('rollupExecutor', () => {
dir: '/root/dist/ui',
format: 'esm',
name: 'Example',
chunkFileNames: '[name].js',
entryFileNames: '[name].js',
chunkFileNames: '[name].esm.js',
entryFileNames: '[name].esm.js',
},
{
dir: '/root/dist/ui',
format: 'cjs',
name: 'Example',
chunkFileNames: '[name].cjs',
entryFileNames: '[name].cjs',
chunkFileNames: '[name].cjs.js',
entryFileNames: '[name].cjs.js',
},
]);
});
Expand Down
39 changes: 21 additions & 18 deletions packages/rollup/src/executors/rollup/rollup.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ import {
import { analyze } from './lib/analyze-plugin';
import { deleteOutputDir } from '../../utils/fs';
import { swc } from './lib/swc-plugin';
import { validateTypes } from './lib/validate-types';
import { updatePackageJson } from './lib/update-package-json';
import { typeDefinitions } from '../../plugins/type-definitions';

export type RollupExecutorEvent = {
success: boolean;
Expand Down Expand Up @@ -85,18 +85,6 @@ export async function* rollupExecutor(

const outfile = resolveOutfile(context, options);

if (options.compiler === 'swc') {
try {
await validateTypes({
workspaceRoot: context.root,
projectRoot: options.projectRoot,
tsconfig: options.tsConfig,
});
} catch {
return { success: false };
}
}

if (options.watch) {
const watcher = rollup.watch(rollupOptions);
return yield* eachValueFrom(
Expand Down Expand Up @@ -204,6 +192,10 @@ export function createRollupOptions(
}

return options.format.map((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';

const plugins = [
copy({
targets: convertCopyAssetsToRollupOptions(
Expand All @@ -213,7 +205,7 @@ export function createRollupOptions(
}),
image(),
json(),
(useTsc || useBabel) &&
(useTsc || shouldBundleTypes) &&
require('rollup-plugin-typescript2')({
check: !options.skipTypeCheck,
tsconfig: options.tsConfig,
Expand All @@ -225,6 +217,12 @@ export function createRollupOptions(
),
},
}),
shouldBundleTypes &&
typeDefinitions({
main: options.main,
compiler: options.compiler,
projectRoot: options.projectRoot,
}),
peerDepsExternal({
packageJsonPath: options.project,
}),
Expand Down Expand Up @@ -295,8 +293,8 @@ export function createRollupOptions(
format,
dir: `${options.outputPath}`,
name: names(context.projectName).className,
entryFileNames: `[name].${format === 'esm' ? 'js' : 'cjs'}`,
chunkFileNames: `[name].${format === 'esm' ? 'js' : 'cjs'}`,
entryFileNames: `[name].${format}.js`,
chunkFileNames: `[name].${format}.js`,
},
external: (id: string) => {
return externalPackages.some(
Expand Down Expand Up @@ -327,6 +325,9 @@ function createTsCompilerOptions(
if (config.options.module === ts.ModuleKind.CommonJS) {
compilerOptions['module'] = 'ESNext';
}
if (options.compiler === 'swc') {
compilerOptions['emitDeclarationOnly'] = true;
}
return compilerOptions;
}

Expand All @@ -347,7 +348,9 @@ function convertCopyAssetsToRollupOptions(
: undefined;
}

function readCompatibleFormats(config: ts.ParsedCommandLine) {
function readCompatibleFormats(
config: ts.ParsedCommandLine
): ('cjs' | 'esm')[] {
switch (config.options.module) {
case ts.ModuleKind.CommonJS:
case ts.ModuleKind.UMD:
Expand All @@ -364,7 +367,7 @@ function resolveOutfile(
) {
if (!options.format?.includes('cjs')) return undefined;
const { name } = parse(options.outputFileName ?? options.main);
return resolve(context.root, options.outputPath, `${name}.cjs`);
return resolve(context.root, options.outputPath, `${name}.cjs.js`);
}

export default rollupExecutor;
Loading

0 comments on commit edcbadf

Please sign in to comment.