Skip to content

Commit

Permalink
feat(js): add --includeBabelRc flag for @nrwl/js:library generator (#…
Browse files Browse the repository at this point in the history
…8793, #8600) (#10055)

* fix(js): fix(js): adding missing babelrc for tsc compiled libraries

ISSUES CLOSED: #8600, #8793

ISSUES CLOSED: #8600, #8793

* feat(js): adds the --skipBabelConfig flag to prevent .babelrc file generation

ISSUES CLOSED: #8600, #8793
ISSUES CLOSED: #8600, #8793

* feat(js): adds the --includeBabelRc flag to the library generator

adds the --includeBabelRc flag to the library generator, and a mechanism to automatically detect the
nrwl/web plugin, which requires auto-generation of the babelrc even when not explicitly set by the
user

ISSUES CLOSED: #8600, #8793
  • Loading branch information
floroz committed May 4, 2022
1 parent e4cccfc commit 664df0e
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 1 deletion.
4 changes: 4 additions & 0 deletions docs/generated/packages/js.json
Expand Up @@ -59,6 +59,10 @@
"description": "Do not update tsconfig.json for development experience.",
"default": false
},
"includeBabelRc": {
"type": "boolean",
"description": "Include a .babelrc configuration to compile TypeScript files"
},
"testEnvironment": {
"type": "string",
"enum": ["jsdom", "node"],
Expand Down
22 changes: 22 additions & 0 deletions e2e/js/src/js.test.ts
@@ -1,5 +1,6 @@
import {
checkFilesExist,
checkFilesDoNotExist,
newProject,
readFile,
readJson,
Expand Down Expand Up @@ -46,6 +47,16 @@ describe('js e2e', () => {
'match the cache'
);

const packageJson = readJson('package.json');
const devPackageNames = Object.keys(packageJson.devDependencies);
expect(devPackageNames).toContain('@nrwl/web');

const babelRc = readJson(`libs/${lib}/.babelrc`);
expect(babelRc.plugins).toBeUndefined();
expect(babelRc.presets).toStrictEqual([
['@nrwl/web/babel', { useBuiltIns: 'usage' }],
]);

expect(runCLI(`build ${lib}`)).toContain('Done compiling TypeScript files');
checkFilesExist(
`dist/libs/${lib}/README.md`,
Expand Down Expand Up @@ -181,6 +192,8 @@ describe('js e2e', () => {
`dist/libs/${lib}/src/lib/${lib}.d.ts`
);

checkFilesDoNotExist(`libs/${lib}/.babelrc`);

const parentLib = uniq('parentlib');
runCLI(`generate @nrwl/js:lib ${parentLib} --buildable --compiler=swc`);
const parentLibPackageJson = readJson(`libs/${parentLib}/package.json`);
Expand Down Expand Up @@ -220,4 +233,13 @@ describe('js e2e', () => {
expect(output).toContain('1 task(s) it depends on');
expect(output).toContain('Successfully compiled: 2 files with swc');
}, 120000);

it('should not create a `.babelrc` file when creating libs with js executors (--compiler=tsc)', () => {
const lib = uniq('lib');
runCLI(
`generate @nrwl/js:lib ${lib} --compiler=tsc --includeBabelRc=false`
);

checkFilesDoNotExist(`libs/${lib}/.babelrc`);
});
});
113 changes: 113 additions & 0 deletions packages/js/src/generators/library/library.spec.ts
Expand Up @@ -13,6 +13,7 @@ describe('lib', () => {
let tree: Tree;
const defaultOptions: Omit<LibraryGeneratorSchema, 'name'> = {
skipTsConfig: false,
includeBabelRc: false,
unitTestRunner: 'jest',
skipFormat: false,
linter: 'eslint',
Expand Down Expand Up @@ -850,5 +851,117 @@ describe('lib', () => {
expect(tree.exists('tools/scripts/publish.mjs')).toBeTruthy();
});
});

describe('--includeBabelRc', () => {
it('should generate a .babelrc when flag is set to true', async () => {
await libraryGenerator(tree, {
...defaultOptions,
name: 'myLib',
includeBabelRc: true,
});

expect(tree.exists('libs/my-lib/.babelrc')).toBeTruthy();
});

it('should not generate a .babelrc when flag is set to false', async () => {
await libraryGenerator(tree, {
...defaultOptions,
name: 'myLib',
includeBabelRc: false,
});

expect(tree.exists('libs/my-lib/.babelrc')).toBeFalsy();
});

it('should not generate a .babelrc when compiler is swc (even if flag is set to true)', async () => {
await libraryGenerator(tree, {
...defaultOptions,
name: 'myLib',
compiler: 'swc',
includeBabelRc: true,
});

expect(tree.exists('libs/my-lib/.babelrc')).toBeFalsy();
});

it('should generate a .babelrc when flag is set to true (even if there is no `@nrwl/web` plugin installed)', async () => {
updateJson(tree, 'package.json', (json) => {
json.devDependencies = {};
return json;
});

await libraryGenerator(tree, {
...defaultOptions,
name: 'myLib',
includeBabelRc: true,
});

expect(tree.exists('libs/my-lib/.babelrc')).toBeTruthy();

const babelRc = readJson(tree, 'libs/my-lib/.babelrc');
expect(babelRc).toMatchInlineSnapshot(`
Object {
"presets": Array [
Array [
"@nrwl/web/babel",
Object {
"useBuiltIns": "usage",
},
],
],
}
`);
});

it('should generate a .babelrc when flag is not set and there is a `@nrwl/web` package installed', async () => {
updateJson(tree, 'package.json', (json) => {
json.devDependencies = {
'@nrwl/web': '1.1.1',
'@nrwl/react': '1.1.1',
'@nrwl/next': '1.1.1',
};
return json;
});

await libraryGenerator(tree, {
...defaultOptions,
name: 'myLib',
includeBabelRc: undefined,
});

expect(tree.exists('libs/my-lib/.babelrc')).toBeTruthy();

const babelRc = readJson(tree, 'libs/my-lib/.babelrc');
expect(babelRc).toMatchInlineSnapshot(`
Object {
"presets": Array [
Array [
"@nrwl/web/babel",
Object {
"useBuiltIns": "usage",
},
],
],
}
`);
});
it('should not generate a .babelrc when flag is not set and there is NOT a `@nrwl/web` package installed', async () => {
updateJson(tree, 'package.json', (json) => {
json.devDependencies = {
'@nrwl/angular': '1.1.1',
'@nrwl/next': '1.1.1',
};
return json;
});

await libraryGenerator(tree, {
...defaultOptions,
name: 'myLib',
includeBabelRc: undefined,
});

expect(tree.exists('libs/my-lib/.babelrc')).toBeFalsy();
});
});
});
});
40 changes: 39 additions & 1 deletion packages/js/src/generators/library/library.ts
Expand Up @@ -12,6 +12,8 @@ import {
toJS,
Tree,
updateJson,
readJson,
writeJson,
} from '@nrwl/devkit';
import { jestProjectGenerator } from '@nrwl/jest';
import { findRootJestPreset } from '@nrwl/jest/src/utils/config/find-root-jest-files';
Expand Down Expand Up @@ -177,6 +179,40 @@ function updateTsConfig(tree: Tree, options: NormalizedSchema) {
});
}

/**
* Currently `@nrwl/js:library` TypeScript files can be compiled by most NX applications scaffolded via the Plugin system. However, `@nrwl/react:app` is an exception that due to its babel configuration, won't transpile external TypeScript files from packages/libs that do not contain a .babelrc.
*
* If a user doesn't explicitly set the flag, to prevent breaking the experience (they see the application failing, and they need to manually add the babelrc themselves), we want to detect whether they have the `@nrwl/web` plugin installed, and generate it automatically for them (even when they do not explicity request it).
*
* You can find more details on why this is necessary here:
* https://github.com/nrwl/nx/pull/10055
*/
function shouldAddBabelRc(tree: Tree, options: NormalizedSchema) {
if (typeof options.includeBabelRc === 'undefined') {
const webPluginName = '@nrwl/web';

const packageJson = readJson(tree, 'package.json');

const hasNxWebPlugin = Object.keys(
packageJson.devDependencies as Record<string, string>
).includes(webPluginName);

return hasNxWebPlugin;
}

return options.includeBabelRc;
}

function addBabelRc(tree: Tree, options: NormalizedSchema) {
const filename = '.babelrc';

const babelrc = {
presets: [['@nrwl/web/babel', { useBuiltIns: 'usage' }]],
};

writeJson(tree, join(options.projectRoot, filename), babelrc);
}

function createFiles(tree: Tree, options: NormalizedSchema, filesDir: string) {
const { className, name, propertyName } = names(options.name);

Expand All @@ -196,9 +232,11 @@ function createFiles(tree: Tree, options: NormalizedSchema, filesDir: string) {
hasUnitTestRunner: options.unitTestRunner !== 'none',
});

if (options.buildable && options.compiler === 'swc') {
if (options.compiler === 'swc') {
addSwcDependencies(tree);
addSwcConfig(tree, options.projectRoot);
} else if (shouldAddBabelRc(tree, options)) {
addBabelRc(tree, options);
}

if (options.unitTestRunner === 'none') {
Expand Down
4 changes: 4 additions & 0 deletions packages/js/src/generators/library/schema.json
Expand Up @@ -52,6 +52,10 @@
"description": "Do not update tsconfig.json for development experience.",
"default": false
},
"includeBabelRc": {
"type": "boolean",
"description": "Include a .babelrc configuration to compile TypeScript files"
},
"testEnvironment": {
"type": "string",
"enum": ["jsdom", "node"],
Expand Down
1 change: 1 addition & 0 deletions packages/js/src/utils/schema.d.ts
Expand Up @@ -15,6 +15,7 @@ export interface LibraryGeneratorSchema {
tags?: string;
simpleModuleName?: boolean;
skipTsConfig?: boolean;
includeBabelRc?: boolean;
unitTestRunner?: 'jest' | 'none';
linter?: Linter;
testEnvironment?: 'jsdom' | 'node';
Expand Down

1 comment on commit 664df0e

@vercel
Copy link

@vercel vercel bot commented on 664df0e May 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nx-dev – ./

nx-five.vercel.app
nx-dev-git-master-nrwl.vercel.app
nx-dev-nrwl.vercel.app
nx.dev

Please sign in to comment.