Skip to content

Commit

Permalink
feat(react): add generateExportsField option to @nrwl/web:rollup ex…
Browse files Browse the repository at this point in the history
…ecutor so it is an opt-in feature

- Also adds skipTypeField option in case that is causing issues for users
- Fixes #10741
  • Loading branch information
jaysoo authored and Jack Hsu committed Jun 14, 2022
1 parent 4aa7371 commit 24abc65
Show file tree
Hide file tree
Showing 5 changed files with 251 additions and 114 deletions.
10 changes: 10 additions & 0 deletions docs/generated/packages/web.json
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,16 @@
"type": "boolean",
"description": "Sets `javascriptEnabled` option for less loader",
"default": false
},
"generateExportsField": {
"type": "boolean",
"description": "Generate package.json with 'exports' field. This field defines entry points in the package and is used by Node and the TypeScript compiler.",
"default": false
},
"skipTypeField": {
"type": "boolean",
"description": "Prevents 'type' field from being added to compiled package.json file. Only use this if you are having an issue with this field.",
"default": false
}
},
"required": ["tsConfig", "project", "entryFile", "outputPath"],
Expand Down
330 changes: 221 additions & 109 deletions packages/web/src/executors/rollup/lib/update-package-json.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import { updatePackageJson } from './update-package-json';
import * as utils from 'nx/src/utils/fileutils';
import { PackageJson } from 'nx/src/utils/package-json';

jest.mock('fs', () => require('memfs').fs);

describe('updatePackageJson', () => {
const commonOptions = {
outputPath: 'dist/index.js',
Expand All @@ -23,132 +21,246 @@ describe('updatePackageJson', () => {
cwd: '',
};

it('should support ESM', () => {
const spy = jest.spyOn(utils, 'writeJsonFile');

updatePackageJson(
{
...commonOptions,
format: ['esm'],
},
sharedContext,
{ type: 'app', name: 'test', data: {} },
[],
{} as unknown as PackageJson
);

expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), {
exports: {
'.': {
types: './index.d.ts',
import: './index.js',
describe('generateExportsField: true', () => {
it('should support ESM', () => {
const spy = jest.spyOn(utils, 'writeJsonFile');

updatePackageJson(
{
...commonOptions,
generateExportsField: true,
format: ['esm'],
},
},
main: './index.js',
module: './index.js',
type: 'module',
types: './index.d.ts',
sharedContext,
{ type: 'app', name: 'test', data: {} },
[],
{} as unknown as PackageJson
);

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

spy.mockRestore();
});

spy.mockRestore();
});
it('should support CJS', () => {
const spy = jest.spyOn(utils, 'writeJsonFile');

updatePackageJson(
{
...commonOptions,
generateExportsField: true,
format: ['cjs'],
},
sharedContext,
{ type: 'app', name: 'test', data: {} },
[],
{} as unknown as PackageJson
);

it('should support CJS', () => {
const spy = jest.spyOn(utils, 'writeJsonFile');

updatePackageJson(
{
...commonOptions,
format: ['cjs'],
},
sharedContext,
{ type: 'app', name: 'test', data: {} },
[],
{} as unknown as PackageJson
);

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

spy.mockRestore();
});

spy.mockRestore();
});
it('should support ESM + CJS', () => {
const spy = jest.spyOn(utils, 'writeJsonFile');

it('should support ESM + CJS', () => {
const spy = jest.spyOn(utils, 'writeJsonFile');

updatePackageJson(
{
...commonOptions,
format: ['esm', 'cjs'],
},
sharedContext,
{ type: 'app', name: 'test', data: {} },
[],
{} as unknown as PackageJson
);

expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), {
exports: {
'.': {
types: './index.d.ts',
import: './index.js',
require: './index.cjs',
updatePackageJson(
{
...commonOptions,
generateExportsField: true,
format: ['esm', 'cjs'],
},
},
main: './index.cjs',
module: './index.js',
type: 'module',
types: './index.d.ts',
sharedContext,
{ type: 'app', name: 'test', data: {} },
[],
{} as unknown as PackageJson
);

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

spy.mockRestore();
});

spy.mockRestore();
});
it('should support custom exports field', () => {
const spy = jest.spyOn(utils, 'writeJsonFile');

it('should support custom exports field', () => {
const spy = jest.spyOn(utils, 'writeJsonFile');

updatePackageJson(
{
...commonOptions,
format: ['esm'],
},
sharedContext,
{ type: 'app', name: 'test', data: {} },
[],
{
updatePackageJson(
{
...commonOptions,
generateExportsField: true,
format: ['esm'],
},
sharedContext,
{ type: 'app', name: 'test', data: {} },
[],
{
exports: {
'./foo': {
import: './foo.js',
},
},
} as unknown as PackageJson
);

expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), {
exports: {
foo: {
'.': {
types: './index.d.ts',
import: './index.js',
},
'./foo': {
import: './foo.js',
},
},
} as unknown as PackageJson
);

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

spy.mockRestore();
});
});

describe('generateExportsField: false', () => {
it('should support ESM', () => {
const spy = jest.spyOn(utils, 'writeJsonFile');

updatePackageJson(
{
...commonOptions,
format: ['esm'],
},
sharedContext,
{ type: 'app', name: 'test', data: {} },
[],
{} as unknown as PackageJson
);

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

spy.mockRestore();
});

it('should support CJS', () => {
const spy = jest.spyOn(utils, 'writeJsonFile');

updatePackageJson(
{
...commonOptions,
format: ['cjs'],
},
foo: {
import: './foo.js',
sharedContext,
{ type: 'app', name: 'test', data: {} },
[],
{} as unknown as PackageJson
);

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

spy.mockRestore();
});

it('should support ESM + CJS', () => {
const spy = jest.spyOn(utils, 'writeJsonFile');

updatePackageJson(
{
...commonOptions,
format: ['esm', 'cjs'],
},
},
main: './index.js',
module: './index.js',
type: 'module',
types: './index.d.ts',
sharedContext,
{ type: 'app', name: 'test', data: {} },
[],
{} as unknown as PackageJson
);

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

spy.mockRestore();
});

spy.mockRestore();
it('should support custom exports field', () => {
const spy = jest.spyOn(utils, 'writeJsonFile');

updatePackageJson(
{
...commonOptions,
format: ['esm'],
},
sharedContext,
{ type: 'app', name: 'test', data: {} },
[],
{
exports: {
'./foo': {
import: './foo.js',
},
},
} as unknown as PackageJson
);

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

spy.mockRestore();
});
});
});
11 changes: 7 additions & 4 deletions packages/web/src/executors/rollup/lib/update-package-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,13 @@ export function updatePackageJson(
// Support for older TS versions < 4.5
packageJson.types = types;

packageJson.exports = {
...packageJson.exports,
...exports,
};
// TODO(jack): remove this for Nx 15
if (options.generateExportsField) {
packageJson.exports = {
...packageJson.exports,
...exports,
};
}

writeJsonFile(`${options.outputPath}/package.json`, packageJson);

Expand Down

0 comments on commit 24abc65

Please sign in to comment.