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: nrwl#8600, nrwl#8793
  • Loading branch information
Daniele committed May 4, 2022
1 parent 74032d5 commit f73d88e
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 47 deletions.
4 changes: 2 additions & 2 deletions docs/generated/packages/js.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@
"description": "Do not update tsconfig.json for development experience.",
"default": false
},
"skipBabelConfig": {
"includeBabelRc": {
"type": "boolean",
"description": "Skip creating a .babelrc configuration",
"description": "Include a .babelrc configuration to compile TypeScript files",
"default": false
},
"testEnvironment": {
Expand Down
9 changes: 8 additions & 1 deletion 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 @@ -34,7 +35,7 @@ describe('js e2e', () => {
});
}, 120000);

it('should create libs with js executors (--compiler=tsc)', async () => {
it('qqqq should create libs with js executors (--compiler=tsc)', async () => {
const lib = uniq('lib');
runCLI(`generate @nrwl/js:lib ${lib} --buildable --compiler=tsc`);
const libPackageJson = readJson(`libs/${lib}/package.json`);
Expand All @@ -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
128 changes: 97 additions & 31 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',
buildable: true,
compiler: 'swc',
skipBabelConfig: false,
includeBabelRc: true,
});

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

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 to false 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: false,
});

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 set to false and there is no `@nrwl/web` package installed', async () => {
updateJson(tree, 'package.json', (json) => {
json.devDependencies = {
'@nrwl/react': '1.1.1',
'@nrwl/next': '1.1.1',
};
return json;
});

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

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', async () => {
await libraryGenerator(tree, {
...defaultOptions,
name: 'myLib',
compiler: 'tsc',
skipBabelConfig: true,
includeBabelRc: false,
});

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

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

expect(tree.exists('libs/my-lib/.babelrc')).toBeFalsy();
Expand Down
41 changes: 31 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,37 @@ 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.
* To prevent breaking the experience for the user (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 (options.includeBabelRc) {
return true;
}

const webPluginName = '@nrwl/web';

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

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

return hasNxWebPlugin;
}

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 +231,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
4 changes: 2 additions & 2 deletions packages/js/src/generators/library/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@
"description": "Do not update tsconfig.json for development experience.",
"default": false
},
"skipBabelConfig": {
"includeBabelRc": {
"type": "boolean",
"description": "Skip creating a .babelrc configuration",
"description": "Include a .babelrc configuration to compile TypeScript files",
"default": false
},
"testEnvironment": {
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 f73d88e

Please sign in to comment.