Skip to content

Commit

Permalink
feat(js): adds the --includeBabelRc flag to the library generator
Browse files Browse the repository at this point in the history
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
Daniele committed May 4, 2022
1 parent 74032d5 commit 29a6bf5
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 47 deletions.
5 changes: 2 additions & 3 deletions docs/generated/packages/js.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,9 @@
"description": "Do not update tsconfig.json for development experience.",
"default": false
},
"skipBabelConfig": {
"includeBabelRc": {
"type": "boolean",
"description": "Skip creating a .babelrc configuration",
"default": false
"description": "Include a .babelrc configuration to compile TypeScript files"
},
"testEnvironment": {
"type": "string",
Expand Down
16 changes: 16 additions & 0 deletions e2e/js/src/js.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
checkFilesExist,
checkFilesDoNotExist,
newProject,
readFile,
readJson,
Expand Down Expand Up @@ -46,6 +47,10 @@ 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([
Expand Down Expand Up @@ -187,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 @@ -226,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('qqqq 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`);
});
});
126 changes: 96 additions & 30 deletions packages/js/src/generators/library/library.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe('lib', () => {
let tree: Tree;
const defaultOptions: Omit<LibraryGeneratorSchema, 'name'> = {
skipTsConfig: false,
skipBabelConfig: false,
includeBabelRc: false,
unitTestRunner: 'jest',
skipFormat: false,
linter: 'eslint',
Expand Down Expand Up @@ -163,27 +163,6 @@ describe('lib', () => {
`);
});

it('should create a local .babelrc configuration', async () => {
await libraryGenerator(tree, {
...defaultOptions,
name: 'myLib',
});

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

it('should extend from root tsconfig.json when no tsconfig.base.json', async () => {
tree.rename('tsconfig.base.json', 'tsconfig.json');

Expand Down Expand Up @@ -244,7 +223,6 @@ describe('lib', () => {
expect(tree.exists('libs/my-dir/my-lib/src/index.ts')).toBeTruthy();
expect(tree.exists(`libs/my-dir/my-lib/.eslintrc.json`)).toBeTruthy();
expect(tree.exists(`libs/my-dir/my-lib/package.json`)).toBeFalsy();
expect(tree.exists(`libs/my-dir/my-lib/.babelrc`)).toBeTruthy();
});

it('should update workspace.json', async () => {
Expand Down Expand Up @@ -874,24 +852,112 @@ describe('lib', () => {
});
});

describe('--skipBabelConfig', () => {
it('should not generate a .babelrc for swc even when set to false', async () => {
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',
buildable: true,
compiler: 'swc',
skipBabelConfig: false,
includeBabelRc: true,
});

expect(tree.exists('libs/my-lib/.babelrc')).toBeFalsy();
});
it('should not create a .babelrc when set to true', async () => {

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',
compiler: 'tsc',
skipBabelConfig: true,
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();
Expand Down
42 changes: 32 additions & 10 deletions packages/js/src/generators/library/library.ts
Original file line number Diff line number Diff line change
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,16 +179,38 @@ function updateTsConfig(tree: Tree, options: NormalizedSchema) {
});
}

function addBabelConfig(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' }]],
};

tree.write(
join(options.projectRoot, filename),
JSON.stringify(babelrc, null, 2)
);
writeJson(tree, join(options.projectRoot, filename), babelrc);
}

function createFiles(tree: Tree, options: NormalizedSchema, filesDir: string) {
Expand All @@ -208,13 +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);
}

if (options.compiler !== 'swc' && !options.skipBabelConfig) {
addBabelConfig(tree, options);
} else if (shouldAddBabelRc(tree, options)) {
addBabelRc(tree, options);
}

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

0 comments on commit 29a6bf5

Please sign in to comment.