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 2dc6656 commit 92d02b2
Show file tree
Hide file tree
Showing 13 changed files with 147 additions and 117 deletions.
2 changes: 1 addition & 1 deletion e2e/expo/src/expo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ describe('expo', () => {
it('should build publishable library', async () => {
expect(() => {
runCLI(`build ${libName}`);
checkFilesExist(`dist/libs/${libName}/index.js`);
checkFilesExist(`dist/libs/${libName}/index.esm.js`);
checkFilesExist(`dist/libs/${libName}/src/index.d.ts`);
}).not.toThrow();
});
Expand Down
24 changes: 12 additions & 12 deletions e2e/react-core/src/react-package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ describe('Build React libraries and apps', () => {
runCLI(`build ${childLib}`);
runCLI(`build ${childLib2}`);

checkFilesExist(`dist/libs/${childLib}/index.js`);
checkFilesExist(`dist/libs/${childLib}/index.esm.js`);

checkFilesExist(`dist/libs/${childLib2}/index.js`);
checkFilesExist(`dist/libs/${childLib2}/index.esm.js`);

checkFilesExist(`dist/libs/${childLib}/assets/hello.txt`);
checkFilesExist(`dist/libs/${childLib2}/README.md`);
Expand All @@ -131,7 +131,7 @@ describe('Build React libraries and apps', () => {
*/
runCLI(`build ${parentLib} --updateBuildableProjectDepsInPackageJson`);

checkFilesExist(`dist/libs/${parentLib}/index.js`);
checkFilesExist(`dist/libs/${parentLib}/index.esm.js`);

const jsonFile = readJson(`dist/libs/${parentLib}/package.json`);
expect(jsonFile.peerDependencies).toEqual(
Expand All @@ -148,14 +148,14 @@ describe('Build React libraries and apps', () => {

runCLI(`build ${parentLib} --skip-nx-cache`);

checkFilesExist(`dist/libs/${parentLib}/index.js`);
checkFilesExist(`dist/libs/${childLib}/index.js`);
checkFilesExist(`dist/libs/${childLib2}/index.js`);
checkFilesExist(`dist/libs/${parentLib}/index.esm.js`);
checkFilesExist(`dist/libs/${childLib}/index.esm.js`);
checkFilesExist(`dist/libs/${childLib2}/index.esm.js`);

expect(readFile(`dist/libs/${childLib}/index.js`)).not.toContain(
expect(readFile(`dist/libs/${childLib}/index.esm.js`)).not.toContain(
'react/jsx-dev-runtime'
);
expect(readFile(`dist/libs/${childLib}/index.js`)).toContain(
expect(readFile(`dist/libs/${childLib}/index.esm.js`)).toContain(
'react/jsx-runtime'
);
});
Expand All @@ -172,14 +172,14 @@ export async function h() { return 'c'; }

runCLI(`build ${childLib} --format cjs,esm`);

checkFilesExist(`dist/libs/${childLib}/index.cjs`);
checkFilesExist(`dist/libs/${childLib}/index.js`);
checkFilesExist(`dist/libs/${childLib}/index.cjs.js`);
checkFilesExist(`dist/libs/${childLib}/index.esm.js`);

const cjsPackageSize = getSize(
tmpProjPath(`dist/libs/${childLib}/index.cjs`)
);
const esmPackageSize = getSize(
tmpProjPath(`dist/libs/${childLib}/index.js`)
tmpProjPath(`dist/libs/${childLib}/index.esm.js`)
);

// This is a loose requirement that ESM should be smaller than CJS output.
Expand Down Expand Up @@ -228,7 +228,7 @@ export async function h() { return 'c'; }
// What we're testing
runCLI(`build ${myLib}`);
// Assertion
const content = readFile(`dist/libs/${myLib}/index.js`);
const content = readFile(`dist/libs/${myLib}/index.esm.js`);

/**
* Then check if the result contains this "promise" polyfill?
Expand Down
2 changes: 1 addition & 1 deletion e2e/react-native/src/react-native.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ describe('react native', () => {
);
expect(() => {
runCLI(`build ${libName}`);
checkFilesExist(`dist/libs/${libName}/index.js`);
checkFilesExist(`dist/libs/${libName}/index.esm.js`);
checkFilesExist(`dist/libs/${libName}/src/index.d.ts`);
}).not.toThrow();
});
Expand Down
17 changes: 13 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,15 @@ 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).toEqual({
'.': {
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 +47,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 +61,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
2 changes: 1 addition & 1 deletion e2e/web/src/web.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ describe('Web Components Applications', () => {
checkFilesExist(`dist/apps/_should_not_remove.txt`);

// Asset that React runtime is imported
expect(readFile(`dist/libs/${libName}/index.js`)).toMatch(
expect(readFile(`dist/libs/${libName}/index.esm.js`)).toMatch(
/react\/jsx-runtime/
);

Expand Down
1 change: 1 addition & 0 deletions packages/js/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"typescript",
"eslint",
"verdaccio", // Optional, used for local registry
"rollup", // just for types (not in actual dist)
// require.resolve is used for these packages
"source-map-support",
"@babel/core",
Expand Down
60 changes: 60 additions & 0 deletions packages/js/src/plugins/rollup/type-definitions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import type { OutputBundle } from 'rollup';
import { relative } from 'path';
import { stripIndents } from '@nx/devkit';

//NOTE: This is here so we can share between `@nx/rollup` and `@nx/vite`.

/*
* This plugin takes all entry-points from the generated bundle and creates a
* bundled version of corresponding d.ts files.
*
* For example, `src/index.ts` generates two corresponding files:
* - `dist/xyz/index.js`
* - `dist/xyz/src/index.d.ts`
*
* We want a third file: `dist/index.d.ts` that re-exports from `src/index.d.ts`.
* That way, when TSC or IDEs look for types, it will find them in the right place.
*/
export function typeDefinitions(options: {
projectRoot: string;
main: string;
}) {
return {
name: 'dts-bundle',
async generateBundle(_opts: unknown, bundle: OutputBundle): Promise<void> {
for (const [name, file] of Object.entries(bundle)) {
if (
file.type === 'asset' ||
!file.isEntry ||
file.facadeModuleId == null
) {
continue;
}

const hasDefaultExport = file.exports.includes('default');
const entrySourceFileName = relative(
options.projectRoot,
file.facadeModuleId
);
const entrySourceDtsName = entrySourceFileName.replace(
/\.[cm]?[jt]sx?$/,
''
);
const dtsFileName = file.fileName.replace(/\.[cm]?js$/, '.d.ts');
const relativeSourceDtsName = JSON.stringify('./' + entrySourceDtsName);
const dtsFileSource = hasDefaultExport
? stripIndents`
export * from ${relativeSourceDtsName};
export { default } from ${relativeSourceDtsName};
`
: `export * from ${relativeSourceDtsName};\n`;

this.emitFile({
type: 'asset',
fileName: dtsFileName,
source: dtsFileSource,
});
}
},
};
}
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
Loading

0 comments on commit 92d02b2

Please sign in to comment.