From ca7af0b7fe01bcddeb7b778c431fc2572c8a6ffb Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Mon, 29 May 2023 14:01:15 -0400 Subject: [PATCH] feat(js): do not generate root babel.config.json for babel projects - Project will only use its .babelrc and ignore .babelrc of other projects (e.g. other libs) - For prevous behavior user can set `babelUpwardRootMode: true` for @nx/webpack:webpack or @nx/rollup:rollup executors --- .../express/generators/application.json | 8 +- .../packages/node/generators/application.json | 10 +- .../react/generators/application.json | 4 +- .../packages/react/generators/host.json | 2 +- .../packages/react/generators/init.json | 5 - .../packages/react/generators/remote.json | 2 +- .../packages/web/generators/application.json | 4 +- .../packages/web/generators/init.json | 5 - e2e/web/src/web.test.ts | 63 +++- .../src/generators/application/schema.d.ts | 2 + .../src/generators/application/schema.json | 8 +- .../__snapshots__/jest-project.spec.ts.snap | 7 +- .../jest-project/jest-project.spec.ts | 9 - .../jest-project/lib/create-files.ts | 11 +- packages/js/src/generators/library/library.ts | 12 - packages/js/src/utils/add-babel-inputs.ts | 3 +- packages/next/src/generators/init/init.ts | 1 - .../src/generators/library/library.spec.ts | 61 ---- .../next/src/generators/library/library.ts | 30 -- .../application/application.spec.ts | 29 +- .../src/generators/application/application.ts | 2 +- .../src/generators/application/schema.d.ts | 2 + .../src/generators/application/schema.json | 10 +- .../src/generators/init/init.spec.ts | 43 --- .../react-native/src/generators/init/init.ts | 2 - .../application/application.spec.ts | 4 +- .../src/generators/application/application.ts | 10 +- .../lib/install-common-dependencies.ts | 25 +- .../application/lib/set-defaults.ts | 2 +- .../application/lib/show-possible-warnings.ts | 16 + .../src/generators/application/schema.d.ts | 2 +- .../src/generators/application/schema.json | 4 +- .../react/src/generators/host/schema.d.ts | 2 +- .../react/src/generators/host/schema.json | 2 +- .../react/src/generators/init/init.spec.ts | 5 - packages/react/src/generators/init/init.ts | 35 --- .../react/src/generators/init/schema.d.ts | 1 - .../react/src/generators/init/schema.json | 5 - .../library/files/common/.babelrc__tmpl__ | 16 - .../generators/library/lib/create-files.ts | 30 +- .../lib/install-common-dependencies.ts | 9 + .../src/generators/library/library.spec.ts | 283 +++++++++--------- .../react/src/generators/library/library.ts | 1 - .../react/src/generators/remote/schema.d.ts | 2 +- .../react/src/generators/remote/schema.json | 2 +- .../rollup/src/generators/init/init.spec.ts | 17 -- packages/rollup/src/generators/init/init.ts | 4 - .../src/generators/application/application.ts | 2 - .../src/generators/application/schema.json | 4 +- packages/web/src/generators/init/init.ts | 3 - packages/web/src/generators/init/schema.d.ts | 1 - packages/web/src/generators/init/schema.json | 5 - .../webpack/src/generators/init/init.spec.ts | 17 -- packages/webpack/src/generators/init/init.ts | 3 - 54 files changed, 359 insertions(+), 488 deletions(-) create mode 100644 packages/react/src/generators/application/lib/show-possible-warnings.ts delete mode 100644 packages/react/src/generators/library/files/common/.babelrc__tmpl__ diff --git a/docs/generated/packages/express/generators/application.json b/docs/generated/packages/express/generators/application.json index 10336208f37f7f..f35f168da503c2 100644 --- a/docs/generated/packages/express/generators/application.json +++ b/docs/generated/packages/express/generators/application.json @@ -50,10 +50,16 @@ "type": "string", "description": "Frontend project that needs to access this application. This sets up proxy configuration." }, + "swcJest": { + "type": "boolean", + "description": "Use `@swc/jest` instead `ts-jest` for faster test compilation.", + "default": false + }, "babelJest": { "type": "boolean", "description": "Use `babel` instead `ts-jest`.", - "default": false + "default": false, + "x-deprecated": "Use --swcJest instead for faster compilation" }, "pascalCaseFiles": { "type": "boolean", diff --git a/docs/generated/packages/node/generators/application.json b/docs/generated/packages/node/generators/application.json index a2bbe09416a603..a8e6fae87bfa6e 100644 --- a/docs/generated/packages/node/generators/application.json +++ b/docs/generated/packages/node/generators/application.json @@ -54,11 +54,17 @@ "description": "Frontend project that needs to access this application. This sets up proxy configuration.", "x-priority": "important" }, - "babelJest": { + "swcJest": { "type": "boolean", - "description": "Use `babel` instead of `ts-jest`.", + "description": "Use `@swc/jest` instead `ts-jest` for faster test compilation.", "default": false }, + "babelJest": { + "type": "boolean", + "description": "Use `babel` instead `ts-jest`.", + "default": false, + "x-deprecated": "Use --swcJest instead for faster compilation" + }, "pascalCaseFiles": { "type": "boolean", "description": "Use pascal case file names.", diff --git a/docs/generated/packages/react/generators/application.json b/docs/generated/packages/react/generators/application.json index 90006ff44d5d86..58aae1b3fe8a2b 100644 --- a/docs/generated/packages/react/generators/application.json +++ b/docs/generated/packages/react/generators/application.json @@ -92,8 +92,8 @@ "default": false, "x-priority": "internal" }, - "skipWorkspaceJson": { - "description": "Skip updating `workspace.json` with default options based on values provided to this app (e.g. babel, style).", + "skipNxJson": { + "description": "Skip updating `nx.json` with default options based on values provided to this app.", "type": "boolean", "default": false, "x-priority": "internal" diff --git a/docs/generated/packages/react/generators/host.json b/docs/generated/packages/react/generators/host.json index 3e6ef743992e19..e2ee2454686c81 100644 --- a/docs/generated/packages/react/generators/host.json +++ b/docs/generated/packages/react/generators/host.json @@ -73,7 +73,7 @@ "default": false, "x-priority": "internal" }, - "skipWorkspaceJson": { + "skipNxJson": { "description": "Skip updating workspace.json with default options based on values provided to this app (e.g. babel, style).", "type": "boolean", "default": false, diff --git a/docs/generated/packages/react/generators/init.json b/docs/generated/packages/react/generators/init.json index 5122a0829ac2be..9c4e5d9f3f6987 100644 --- a/docs/generated/packages/react/generators/init.json +++ b/docs/generated/packages/react/generators/init.json @@ -31,11 +31,6 @@ "type": "boolean", "default": false }, - "skipBabelConfig": { - "description": "Do not generate a root babel.config.json (if babel is not needed).", - "type": "boolean", - "default": false - }, "skipHelperLibs": { "description": "Do not install tslib.", "type": "boolean", diff --git a/docs/generated/packages/react/generators/remote.json b/docs/generated/packages/react/generators/remote.json index cd99a9e0f414a4..ae32c075dc0969 100644 --- a/docs/generated/packages/react/generators/remote.json +++ b/docs/generated/packages/react/generators/remote.json @@ -78,7 +78,7 @@ "default": false, "x-priority": "internal" }, - "skipWorkspaceJson": { + "skipNxJson": { "description": "Skip updating workspace.json with default options based on values provided to this app (e.g. babel, style).", "type": "boolean", "default": false, diff --git a/docs/generated/packages/web/generators/application.json b/docs/generated/packages/web/generators/application.json index d44bd521eaee4e..74f90cd73df607 100644 --- a/docs/generated/packages/web/generators/application.json +++ b/docs/generated/packages/web/generators/application.json @@ -43,8 +43,8 @@ "compiler": { "type": "string", "description": "The compiler to use", - "enum": ["babel", "swc"], - "default": "babel", + "enum": ["swc", "babel"], + "default": "swc", "x-priority": "important" }, "bundler": { diff --git a/docs/generated/packages/web/generators/init.json b/docs/generated/packages/web/generators/init.json index d4903a3218836f..438efd9633fa1f 100644 --- a/docs/generated/packages/web/generators/init.json +++ b/docs/generated/packages/web/generators/init.json @@ -37,11 +37,6 @@ "type": "boolean", "default": false, "x-priority": "internal" - }, - "skipBabelConfig": { - "description": "Do not generate a root babel.config.json (if babel is not needed).", - "type": "boolean", - "default": false } }, "required": [], diff --git a/e2e/web/src/web.test.ts b/e2e/web/src/web.test.ts index 90cd40195b0625..a82f3b247b1954 100644 --- a/e2e/web/src/web.test.ts +++ b/e2e/web/src/web.test.ts @@ -7,7 +7,6 @@ import { killPorts, newProject, readFile, - removeFile, rmDist, runCLI, runCLIAsync, @@ -100,10 +99,10 @@ describe('Web Components Applications', () => { checkFilesExist(`dist/libs/${libName}/_should_keep.txt`); }, 120000); - it('should emit decorator metadata when it is enabled in tsconfig', async () => { + it('should emit decorator metadata when --compiler=babel and it is enabled in tsconfig', async () => { const appName = uniq('app'); runCLI( - `generate @nx/web:app ${appName} --bundler=webpack --no-interactive` + `generate @nx/web:app ${appName} --bundler=webpack --compiler=babel --no-interactive` ); updateFile(`apps/${appName}/src/app/app.element.ts`, (content) => { @@ -155,6 +154,48 @@ describe('Web Components Applications', () => { ); }, 120000); + it('should emit decorator metadata when using --compiler=swc', async () => { + const appName = uniq('app'); + runCLI( + `generate @nx/web:app ${appName} --bundler=webpack --compiler=swc --no-interactive` + ); + + updateFile(`apps/${appName}/src/app/app.element.ts`, (content) => { + const newContent = `${content} + function enumerable(value: boolean) { + return function ( + target: any, + propertyKey: string, + descriptor: PropertyDescriptor + ) { + descriptor.enumerable = value; + }; + } + function sealed(target: any) { + return target; + } + + @sealed + class Foo { + @enumerable(false) bar() {} + } + `; + return newContent; + }); + + updateFile(`apps/${appName}/src/app/app.element.ts`, (content) => { + const newContent = `${content} + // bust babel and nx cache + `; + return newContent; + }); + runCLI(`build ${appName} --outputHashing none`); + + expect(readFile(`dist/apps/${appName}/main.js`)).toMatch( + /Foo=__decorate\(\[sealed\],Foo\)/ + ); + }, 120000); + it('should support custom webpackConfig option', async () => { const appName = uniq('app'); runCLI( @@ -257,7 +298,7 @@ describe('CLI - Environment Variables', () => { `; runCLI( - `generate @nx/web:app ${appName} --bundler=webpack --no-interactive` + `generate @nx/web:app ${appName} --bundler=webpack --no-interactive --compiler=babel` ); const content = readFile(main); @@ -282,7 +323,7 @@ describe('CLI - Environment Variables', () => { const newCode2 = `const envVars = [process.env.NODE_ENV, process.env.NX_BUILD, process.env.NX_API, process.env.NX_WS_BASE, process.env.NX_WS_ENV_LOCAL, process.env.NX_WS_LOCAL_ENV, process.env.NX_APP_BASE, process.env.NX_APP_ENV_LOCAL, process.env.NX_APP_LOCAL_ENV, process.env.NX_SHARED_ENV];`; runCLI( - `generate @nx/web:app ${appName2} --bundler=webpack --no-interactive` + `generate @nx/web:app ${appName2} --bundler=webpack --no-interactive --compiler=babel` ); const content2 = readFile(main2); @@ -401,16 +442,16 @@ describe('index.html interpolation', () => { const srcPath = `apps/${appName}/src`; const indexPath = `${srcPath}/index.html`; const indexContent = ` - + - + BestReactApp - - - + + + -
+
Nx Variable: %NX_VARIABLE%
Some other variable: %SOME_OTHER_VARIABLE%
Deploy Url: %DEPLOY_URL%
diff --git a/packages/express/src/generators/application/schema.d.ts b/packages/express/src/generators/application/schema.d.ts index 1ec7eff6ee7ab0..e7c0468afcc3b2 100644 --- a/packages/express/src/generators/application/schema.d.ts +++ b/packages/express/src/generators/application/schema.d.ts @@ -10,6 +10,8 @@ export interface Schema { tags?: string; linter: Linter; frontendProject?: string; + swcJest?: boolean; + /** @deprecated use `swcJest` instead */ babelJest?: boolean; js: boolean; pascalCaseFiles: boolean; diff --git a/packages/express/src/generators/application/schema.json b/packages/express/src/generators/application/schema.json index db3c743ce5f18b..349d2e3ff3a040 100644 --- a/packages/express/src/generators/application/schema.json +++ b/packages/express/src/generators/application/schema.json @@ -50,10 +50,16 @@ "type": "string", "description": "Frontend project that needs to access this application. This sets up proxy configuration." }, + "swcJest": { + "type": "boolean", + "description": "Use `@swc/jest` instead `ts-jest` for faster test compilation.", + "default": false + }, "babelJest": { "type": "boolean", "description": "Use `babel` instead `ts-jest`.", - "default": false + "default": false, + "x-deprecated": "Use --swcJest instead for faster compilation" }, "pascalCaseFiles": { "type": "boolean", diff --git a/packages/jest/src/generators/jest-project/__snapshots__/jest-project.spec.ts.snap b/packages/jest/src/generators/jest-project/__snapshots__/jest-project.spec.ts.snap index d82db950869ed8..baf985127967cd 100644 --- a/packages/jest/src/generators/jest-project/__snapshots__/jest-project.spec.ts.snap +++ b/packages/jest/src/generators/jest-project/__snapshots__/jest-project.spec.ts.snap @@ -8,7 +8,12 @@ export default { transform: { '^.+\\\\.[tj]sx?$': [ '@swc/jest', - { jsc: { transform: { react: { runtime: 'automatic' } } } }, + { + jsc: { + parser: { syntax: 'typescript', tsx: true }, + transform: { react: { runtime: 'automatic' } }, + }, + }, ], }, moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], diff --git a/packages/jest/src/generators/jest-project/jest-project.spec.ts b/packages/jest/src/generators/jest-project/jest-project.spec.ts index 190019142b7473..85a83f089a2ecf 100644 --- a/packages/jest/src/generators/jest-project/jest-project.spec.ts +++ b/packages/jest/src/generators/jest-project/jest-project.spec.ts @@ -60,15 +60,6 @@ describe('jestProject', () => { expect(tree.read('libs/lib1/jest.config.ts', 'utf-8')).toMatchSnapshot(); }); - it('should generate files w/babel-jest', async () => { - await jestProjectGenerator(tree, { - ...defaultOptions, - project: 'lib1', - babelJest: true, - } as JestProjectSchema); - expect(tree.exists('babel.config.json')).toBeTruthy(); - }); - it('should alter project configuration', async () => { await jestProjectGenerator(tree, { ...defaultOptions, diff --git a/packages/jest/src/generators/jest-project/lib/create-files.ts b/packages/jest/src/generators/jest-project/lib/create-files.ts index 6188e440b04048..e9d4a03b3dadb4 100644 --- a/packages/jest/src/generators/jest-project/lib/create-files.ts +++ b/packages/jest/src/generators/jest-project/lib/create-files.ts @@ -21,7 +21,7 @@ export function createFiles(tree: Tree, options: NormalizedJestProjectSchema) { transformer = '@swc/jest'; if (options.supportTsx) { transformerOptions = - "{ jsc: { transform: { react: { runtime: 'automatic' } } } }"; + "{ jsc: { parser: { syntax: 'typescript', tsx: true }, transform: { react: { runtime: 'automatic' } } } }"; } } else { transformer = 'ts-jest'; @@ -48,15 +48,6 @@ export function createFiles(tree: Tree, options: NormalizedJestProjectSchema) { tree.delete(join(projectConfig.root, './src/test-setup.ts')); } - if (options.babelJest && !tree.exists('babel.config.json')) { - tree.write( - 'babel.config.json', - JSON.stringify({ - babelrcRoots: ['*'], - }) - ); - } - if (options.js) { tree.rename( join(projectConfig.root, 'jest.config.ts'), diff --git a/packages/js/src/generators/library/library.ts b/packages/js/src/generators/library/library.ts index 943bc85b4f3b3e..6c70d348da6069 100644 --- a/packages/js/src/generators/library/library.ts +++ b/packages/js/src/generators/library/library.ts @@ -91,10 +91,6 @@ export async function projectGenerator( }); tasks.push(viteTask); } - if (options.bundler === 'rollup') { - ensureBabelRootConfigExists(tree); - } - if (options.linter !== 'none') { const lintCallback = await addLint(tree, options); tasks.push(lintCallback); @@ -583,14 +579,6 @@ function getBuildExecutor(bundler: Bundler) { } } -function ensureBabelRootConfigExists(tree: Tree) { - if (tree.exists('babel.config.json')) return; - - writeJson(tree, 'babel.config.json', { - babelrcRoots: ['*'], - }); -} - function getOutputPath(options: NormalizedSchema, destinationDir?: string) { const parts = ['dist']; if (destinationDir) { diff --git a/packages/js/src/utils/add-babel-inputs.ts b/packages/js/src/utils/add-babel-inputs.ts index b499042e8148e0..3e3e7ee3e0706c 100644 --- a/packages/js/src/utils/add-babel-inputs.ts +++ b/packages/js/src/utils/add-babel-inputs.ts @@ -1,5 +1,4 @@ import { - formatFiles, joinPathFragments, readNxJson, Tree, @@ -7,6 +6,8 @@ import { writeJson, } from '@nx/devkit'; +/** @deprecated Do not use this function as the root babel.config.json file is no longer needed */ +// TODO(jack): Remove This in Nx 17 once we don't need to support Nx 15 anymore. Currently this function is used in v15 migrations. export function addBabelInputs(tree: Tree) { const nxJson = readNxJson(tree); let globalBabelFile = ['babel.config.js', 'babel.config.json'].find((file) => diff --git a/packages/next/src/generators/init/init.ts b/packages/next/src/generators/init/init.ts index 42712b80dfcb0a..e0bc4061a29f3c 100644 --- a/packages/next/src/generators/init/init.ts +++ b/packages/next/src/generators/init/init.ts @@ -65,7 +65,6 @@ export async function nextInitGenerator(host: Tree, schema: InitSchema) { const reactTask = await reactInitGenerator(host, { ...schema, skipFormat: true, - skipBabelConfig: true, }); tasks.push(reactTask); diff --git a/packages/next/src/generators/library/library.spec.ts b/packages/next/src/generators/library/library.spec.ts index 5417ebf7642fcf..768892043f0290 100644 --- a/packages/next/src/generators/library/library.spec.ts +++ b/packages/next/src/generators/library/library.spec.ts @@ -13,67 +13,6 @@ describe('next library', () => { let mockedInstalledCypressVersion: jest.Mock< ReturnType > = installedCypressVersion as never; - it('should use "@nx/next/babel" preset in babelrc', async () => { - const baseOptions: Schema = { - name: '', - linter: Linter.EsLint, - skipFormat: false, - skipTsConfig: false, - unitTestRunner: 'jest', - style: 'css', - component: true, - }; - - const appTree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); - - await libraryGenerator(appTree, { - ...baseOptions, - name: 'myLib', - }); - await libraryGenerator(appTree, { - ...baseOptions, - name: 'myLib2', - style: '@emotion/styled', - }); - await libraryGenerator(appTree, { - ...baseOptions, - name: 'myLib-styled-jsx', - style: 'styled-jsx', - }); - await libraryGenerator(appTree, { - ...baseOptions, - name: 'myLib3', - directory: 'myDir', - }); - - expect(readJson(appTree, 'libs/my-lib/.babelrc')).toEqual({ - presets: ['@nx/next/babel'], - plugins: [], - }); - expect(readJson(appTree, 'libs/my-lib2/.babelrc')).toEqual({ - presets: [ - [ - '@nx/next/babel', - { - 'preset-react': { - runtime: 'automatic', - importSource: '@emotion/react', - }, - }, - ], - ], - plugins: ['@emotion/babel-plugin'], - }); - expect(readJson(appTree, 'libs/my-lib-styled-jsx/.babelrc')).toEqual({ - presets: ['@nx/next/babel'], - plugins: [], - }); - expect(readJson(appTree, 'libs/my-dir/my-lib3/.babelrc')).toEqual({ - presets: ['@nx/next/babel'], - plugins: [], - }); - }); - it('should use @nx/next images.d.ts file', async () => { const baseOptions: Schema = { name: '', diff --git a/packages/next/src/generators/library/library.ts b/packages/next/src/generators/library/library.ts index b1d6cf2c32b743..cfda6a23a2a926 100644 --- a/packages/next/src/generators/library/library.ts +++ b/packages/next/src/generators/library/library.ts @@ -71,36 +71,6 @@ export async function libraryGenerator(host: Tree, rawOptions: Schema) { ); addTsConfigPath(host, `${options.importPath}/server`, [serverEntryPath]); - updateJson( - host, - joinPathFragments(options.projectRoot, '.babelrc'), - (json) => { - if (options.style === '@emotion/styled') { - json.presets = [ - [ - '@nx/next/babel', - { - 'preset-react': { - runtime: 'automatic', - importSource: '@emotion/react', - }, - }, - ], - ]; - } else if (options.style === 'styled-jsx') { - // next.js doesn't require the `styled-jsx/babel' plugin as it is already - // built-into the `next/babel` preset - json.presets = ['@nx/next/babel']; - json.plugins = (json.plugins || []).filter( - (x) => x !== 'styled-jsx/babel' - ); - } else { - json.presets = ['@nx/next/babel']; - } - return json; - } - ); - updateJson( host, joinPathFragments(options.projectRoot, 'tsconfig.json'), diff --git a/packages/node/src/generators/application/application.spec.ts b/packages/node/src/generators/application/application.spec.ts index d3af66f1d6ed3e..6384729c0ff4fc 100644 --- a/packages/node/src/generators/application/application.spec.ts +++ b/packages/node/src/generators/application/application.spec.ts @@ -343,7 +343,33 @@ describe('app', () => { }); }); - describe('--babelJest', () => { + describe('--swcJest', () => { + it('should use @swc/jest for jest', async () => { + await applicationGenerator(tree, { + name: 'myNodeApp', + tags: 'one,two', + swcJest: true, + } as Schema); + + expect(tree.read(`my-node-app/jest.config.ts`, 'utf-8')) + .toMatchInlineSnapshot(` + "/* eslint-disable */ + export default { + displayName: 'my-node-app', + preset: '../jest.preset.js', + testEnvironment: 'node', + transform: { + '^.+\\\\.[tj]s$': '@swc/jest', + }, + moduleFileExtensions: ['ts', 'js', 'html'], + coverageDirectory: '../coverage/my-node-app', + }; + " + `); + }); + }); + + describe('--babelJest (deprecated)', () => { it('should use babel for jest', async () => { await applicationGenerator(tree, { name: 'myNodeApp', @@ -368,6 +394,7 @@ describe('app', () => { `); }); }); + describe('--js flag', () => { it('should generate js files instead of ts files', async () => { await applicationGenerator(tree, { diff --git a/packages/node/src/generators/application/application.ts b/packages/node/src/generators/application/application.ts index 1c6b350b32bfdb..2dd541d4821ff6 100644 --- a/packages/node/src/generators/application/application.ts +++ b/packages/node/src/generators/application/application.ts @@ -398,7 +398,7 @@ export async function applicationGenerator(tree: Tree, schema: Schema) { skipSerializers: true, supportTsx: options.js, testEnvironment: 'node', - compiler: 'tsc', + compiler: options.swcJest ? 'swc' : 'tsc', skipFormat: true, }); tasks.push(jestTask); diff --git a/packages/node/src/generators/application/schema.d.ts b/packages/node/src/generators/application/schema.d.ts index aec0248728ffc3..70f30e83a5be61 100644 --- a/packages/node/src/generators/application/schema.d.ts +++ b/packages/node/src/generators/application/schema.d.ts @@ -10,6 +10,8 @@ export interface Schema { linter?: Linter; tags?: string; frontendProject?: string; + swcJest?: boolean; + /** @deprecated use `swcJest` instead */ babelJest?: boolean; js?: boolean; pascalCaseFiles?: boolean; diff --git a/packages/node/src/generators/application/schema.json b/packages/node/src/generators/application/schema.json index 92b9f480109267..a1118404bfafc0 100644 --- a/packages/node/src/generators/application/schema.json +++ b/packages/node/src/generators/application/schema.json @@ -54,11 +54,17 @@ "description": "Frontend project that needs to access this application. This sets up proxy configuration.", "x-priority": "important" }, - "babelJest": { + "swcJest": { "type": "boolean", - "description": "Use `babel` instead of `ts-jest`.", + "description": "Use `@swc/jest` instead `ts-jest` for faster test compilation.", "default": false }, + "babelJest": { + "type": "boolean", + "description": "Use `babel` instead `ts-jest`.", + "default": false, + "x-deprecated": "Use --swcJest instead for faster compilation" + }, "pascalCaseFiles": { "type": "boolean", "description": "Use pascal case file names.", diff --git a/packages/react-native/src/generators/init/init.spec.ts b/packages/react-native/src/generators/init/init.spec.ts index 70d7648a27a6f6..c79e7dc189dcb9 100644 --- a/packages/react-native/src/generators/init/init.spec.ts +++ b/packages/react-native/src/generators/init/init.spec.ts @@ -35,47 +35,4 @@ describe('init', () => { expect(content).toMatch(/# React Native/); expect(content).toMatch(/# Nested node_modules/); }); - - describe('babel config', () => { - it('should create babel config if not present', async () => { - updateJson(tree, 'nx.json', (json) => { - json.namedInputs = { - sharedGlobals: ['{workspaceRoot}/exiting-file.json'], - }; - return json; - }); - - await reactNativeInitGenerator(tree, { - unitTestRunner: 'none', - e2eTestRunner: 'none', - }); - - expect(tree.exists('babel.config.json')).toBe(true); - const sharedGloabls = readJson(tree, 'nx.json') - .namedInputs.sharedGlobals; - expect(sharedGloabls).toContain('{workspaceRoot}/exiting-file.json'); - expect(sharedGloabls).toContain('{workspaceRoot}/babel.config.json'); - }); - - it('should not overwrite existing babel config', async () => { - tree.write('babel.config.json', '{ "preset": ["preset-awesome"] }'); - - await reactNativeInitGenerator(tree, { - unitTestRunner: 'none', - e2eTestRunner: 'none', - }); - - const existing = readJson(tree, 'babel.config.json'); - expect(existing).toEqual({ preset: ['preset-awesome'] }); - }); - - it('should not overwrite existing babel config (.js)', async () => { - tree.write('/babel.config.js', 'module.exports = () => {};'); - await reactNativeInitGenerator(tree, { - unitTestRunner: 'none', - e2eTestRunner: 'none', - }); - expect(tree.exists('babel.config.json')).toBe(false); - }); - }); }); diff --git a/packages/react-native/src/generators/init/init.ts b/packages/react-native/src/generators/init/init.ts index 8bfabf03701e74..c5a42c9ea49094 100644 --- a/packages/react-native/src/generators/init/init.ts +++ b/packages/react-native/src/generators/init/init.ts @@ -10,7 +10,6 @@ import { } from '@nx/devkit'; import { Schema } from './schema'; -import { addBabelInputs } from '@nx/js/src/utils/add-babel-inputs'; import { jestInitGenerator } from '@nx/jest'; import { detoxInitGenerator } from '@nx/detox'; import { babelPresetReactVersion } from '@nx/react/src/utils/versions'; @@ -41,7 +40,6 @@ import { addGitIgnoreEntry } from './lib/add-git-ignore-entry'; export async function reactNativeInitGenerator(host: Tree, schema: Schema) { addGitIgnoreEntry(host); - await addBabelInputs(host); const tasks: GeneratorCallback[] = []; tasks.push( diff --git a/packages/react/src/generators/application/application.spec.ts b/packages/react/src/generators/application/application.spec.ts index 04eae30f6480de..d51711c0a48ea3 100644 --- a/packages/react/src/generators/application/application.spec.ts +++ b/packages/react/src/generators/application/application.spec.ts @@ -849,12 +849,12 @@ describe('app', () => { ).toBeUndefined(); }); - describe('--skipWorkspaceJson', () => { + describe('--skipNxJson', () => { it('should update workspace with defaults when --skipprojectsConfigurations=false', async () => { await applicationGenerator(appTree, { ...schema, style: 'styled-components', - skipWorkspaceJson: false, + skipNxJson: false, }); const nxJson = readNxJson(appTree); diff --git a/packages/react/src/generators/application/application.ts b/packages/react/src/generators/application/application.ts index fc99d8fc8e981b..ab1eec504ba5e5 100644 --- a/packages/react/src/generators/application/application.ts +++ b/packages/react/src/generators/application/application.ts @@ -39,6 +39,7 @@ import { installCommonDependencies } from './lib/install-common-dependencies'; import { extractTsConfigBase } from '../../utils/create-ts-config'; import { addSwcDependencies } from '@nx/js/src/utils/swc/add-swc-dependencies'; import * as chalk from 'chalk'; +import { showPossibleWarnings } from './lib/show-possible-warnings'; async function addLinting(host: Tree, options: NormalizedSchema) { const tasks: GeneratorCallback[] = []; @@ -73,12 +74,7 @@ async function addLinting(host: Tree, options: NormalizedSchema) { const installTask = await addDependenciesToPackageJson( host, extraEslintDependencies.dependencies, - { - ...extraEslintDependencies.devDependencies, - ...(options.compiler === 'swc' - ? { 'swc-loader': swcLoaderVersion } - : {}), - } + extraEslintDependencies.devDependencies ); const addSwcTask = addSwcDependencies(host); tasks.push(installTask, addSwcTask); @@ -94,11 +90,11 @@ export async function applicationGenerator( const tasks = []; const options = normalizeOptions(host, schema); + showPossibleWarnings(host, options); const initTask = await reactInitGenerator(host, { ...options, skipFormat: true, - skipBabelConfig: options.bundler === 'vite', skipHelperLibs: options.bundler === 'vite', }); diff --git a/packages/react/src/generators/application/lib/install-common-dependencies.ts b/packages/react/src/generators/application/lib/install-common-dependencies.ts index b321a7453a865d..7c85882c9da79f 100644 --- a/packages/react/src/generators/application/lib/install-common-dependencies.ts +++ b/packages/react/src/generators/application/lib/install-common-dependencies.ts @@ -1,8 +1,10 @@ import { addDependenciesToPackageJson, Tree } from '@nx/devkit'; import { + babelPresetReactVersion, lessVersion, sassVersion, stylusVersion, + swcLoaderVersion, } from '../../../utils/versions'; import { NormalizedSchema } from '../schema'; @@ -10,26 +12,33 @@ export function installCommonDependencies( host: Tree, options: NormalizedSchema ) { - let devDependencies = null; + const devDependencies: Record = {}; // Vite requires style preprocessors to be installed manually. // `@nx/webpack` installs them automatically for now. - // TODO(jack): Once we clean up webpack we can remove this check if (options.bundler === 'vite' || options.unitTestRunner === 'vitest') { switch (options.style) { case 'scss': - devDependencies = { sass: sassVersion }; + devDependencies['sass'] = sassVersion; break; case 'less': - devDependencies = { less: lessVersion }; + devDependencies['less'] = lessVersion; break; case 'styl': // @TODO(17): deprecated, going to be removed in Nx 17 - devDependencies = { stylus: stylusVersion }; + devDependencies['stylus'] = stylusVersion; break; } } - return devDependencies - ? addDependenciesToPackageJson(host, {}, devDependencies) - : function noop() {}; + if (options.bundler === 'webpack') { + if (options.compiler === 'swc') { + devDependencies['swc-loader'] = swcLoaderVersion; + } else if (options.compiler === 'babel') { + // babel-loader is currently included in @nx/webpack + // TODO(jack): Install babel-loader and other babel packages only as needed + devDependencies['@babel/preset-react'] = babelPresetReactVersion; + } + } + + return addDependenciesToPackageJson(host, {}, devDependencies); } diff --git a/packages/react/src/generators/application/lib/set-defaults.ts b/packages/react/src/generators/application/lib/set-defaults.ts index cad40197967570..0406985f151e77 100644 --- a/packages/react/src/generators/application/lib/set-defaults.ts +++ b/packages/react/src/generators/application/lib/set-defaults.ts @@ -2,7 +2,7 @@ import { readNxJson, Tree, updateNxJson } from '@nx/devkit'; import { NormalizedSchema } from '../schema'; export function setDefaults(host: Tree, options: NormalizedSchema) { - if (options.skipWorkspaceJson) { + if (options.skipNxJson) { return; } diff --git a/packages/react/src/generators/application/lib/show-possible-warnings.ts b/packages/react/src/generators/application/lib/show-possible-warnings.ts new file mode 100644 index 00000000000000..cba69ccc2e6218 --- /dev/null +++ b/packages/react/src/generators/application/lib/show-possible-warnings.ts @@ -0,0 +1,16 @@ +import * as chalk from 'chalk'; +import { logger, Tree } from '@nx/devkit'; +import { NormalizedSchema, Schema } from '../schema'; + +export function showPossibleWarnings( + tree: Tree, + options: NormalizedSchema +) { + if (options.style === 'styled-jsx' && options.compiler === 'swc') { + logger.warn( + `styled-jsx may not work with SWC. Try using ${chalk.bold( + 'nx g @nx/react:app --compiler=babel' + )} instead.` + ); + } +} diff --git a/packages/react/src/generators/application/schema.d.ts b/packages/react/src/generators/application/schema.d.ts index ab83ef80b1ca71..7b8ae279ddbac1 100644 --- a/packages/react/src/generators/application/schema.d.ts +++ b/packages/react/src/generators/application/schema.d.ts @@ -14,7 +14,7 @@ export interface Schema { pascalCaseFiles?: boolean; classComponent?: boolean; routing?: boolean; - skipWorkspaceJson?: boolean; + skipNxJson?: boolean; js?: boolean; globalCss?: boolean; strict?: boolean; diff --git a/packages/react/src/generators/application/schema.json b/packages/react/src/generators/application/schema.json index 5eb0249f8015dc..f0dc9d5d152195 100644 --- a/packages/react/src/generators/application/schema.json +++ b/packages/react/src/generators/application/schema.json @@ -98,8 +98,8 @@ "default": false, "x-priority": "internal" }, - "skipWorkspaceJson": { - "description": "Skip updating `workspace.json` with default options based on values provided to this app (e.g. babel, style).", + "skipNxJson": { + "description": "Skip updating `nx.json` with default options based on values provided to this app.", "type": "boolean", "default": false, "x-priority": "internal" diff --git a/packages/react/src/generators/host/schema.d.ts b/packages/react/src/generators/host/schema.d.ts index e8c63c6e83c032..3a524244ef30a7 100644 --- a/packages/react/src/generators/host/schema.d.ts +++ b/packages/react/src/generators/host/schema.d.ts @@ -15,7 +15,7 @@ export interface Schema { remotes?: string[]; setParserOptionsProject?: boolean; skipFormat?: boolean; - skipWorkspaceJson?: boolean; + skipNxJson?: boolean; ssr?: boolean; strict?: boolean; style: SupportedStyles; diff --git a/packages/react/src/generators/host/schema.json b/packages/react/src/generators/host/schema.json index 628dcc09201646..8f7fc3e742e8e5 100644 --- a/packages/react/src/generators/host/schema.json +++ b/packages/react/src/generators/host/schema.json @@ -79,7 +79,7 @@ "default": false, "x-priority": "internal" }, - "skipWorkspaceJson": { + "skipNxJson": { "description": "Skip updating workspace.json with default options based on values provided to this app (e.g. babel, style).", "type": "boolean", "default": false, diff --git a/packages/react/src/generators/init/init.spec.ts b/packages/react/src/generators/init/init.spec.ts index cfff15bda301ce..914ddce0827836 100644 --- a/packages/react/src/generators/init/init.spec.ts +++ b/packages/react/src/generators/init/init.spec.ts @@ -30,9 +30,4 @@ describe('init', () => { await reactInitGenerator(tree, { ...schema, unitTestRunner: 'none' }); expect(tree.exists('jest.config.js')).toEqual(false); }); - - it('should not add babel.config.json if skipBabelConfig is true', async () => { - await reactInitGenerator(tree, { ...schema, skipBabelConfig: true }); - expect(tree.exists('babel.config.json')).toEqual(false); - }); }); diff --git a/packages/react/src/generators/init/init.ts b/packages/react/src/generators/init/init.ts index dee9e57e2ad757..39d12b9f24d510 100755 --- a/packages/react/src/generators/init/init.ts +++ b/packages/react/src/generators/init/init.ts @@ -8,7 +8,6 @@ import { runTasksInSerial, Tree, updateNxJson, - writeJson, } from '@nx/devkit'; import { initGenerator as jsInitGenerator } from '@nx/js'; @@ -65,25 +64,6 @@ function updateDependencies(host: Tree, schema: InitSchema) { }); } -function initRootBabelConfig(tree: Tree, schema: InitSchema) { - if (tree.exists('/babel.config.json') || tree.exists('/babel.config.js')) { - return; - } - - if (!schema.skipBabelConfig) { - writeJson(tree, '/babel.config.json', { - babelrcRoots: ['*'], // Make sure .babelrc files other than root can be loaded in a monorepo - }); - } - - const nxJson = readNxJson(tree); - - if (nxJson.namedInputs?.sharedGlobals) { - nxJson.namedInputs.sharedGlobals.push('{workspaceRoot}/babel.config.json'); - } - updateNxJson(tree, nxJson); -} - export async function reactInitGenerator(host: Tree, schema: InitSchema) { const tasks: GeneratorCallback[] = []; @@ -106,21 +86,6 @@ export async function reactInitGenerator(host: Tree, schema: InitSchema) { tasks.push(cypressTask); } - if (!schema.skipPackageJson && !schema.skipBabelConfig) { - const installBabelTask = addDependenciesToPackageJson( - host, - {}, - { - '@babel/preset-react': babelPresetReactVersion, - } - ); - tasks.push(installBabelTask); - } - - if (!schema.skipBabelConfig) { - initRootBabelConfig(host, schema); - } - if (!schema.skipPackageJson) { const installTask = updateDependencies(host, schema); tasks.push(installTask); diff --git a/packages/react/src/generators/init/schema.d.ts b/packages/react/src/generators/init/schema.d.ts index b89e5ad49986f3..9892a322415a93 100644 --- a/packages/react/src/generators/init/schema.d.ts +++ b/packages/react/src/generators/init/schema.d.ts @@ -1,7 +1,6 @@ export interface InitSchema { unitTestRunner?: 'jest' | 'vitest' | 'none'; e2eTestRunner?: 'cypress' | 'none'; - skipBabelConfig?: boolean; skipFormat?: boolean; skipPackageJson?: boolean; skipHelperLibs?: boolean; diff --git a/packages/react/src/generators/init/schema.json b/packages/react/src/generators/init/schema.json index 1c6800c0244a90..78b86fa7791cd2 100644 --- a/packages/react/src/generators/init/schema.json +++ b/packages/react/src/generators/init/schema.json @@ -28,11 +28,6 @@ "type": "boolean", "default": false }, - "skipBabelConfig": { - "description": "Do not generate a root babel.config.json (if babel is not needed).", - "type": "boolean", - "default": false - }, "skipHelperLibs": { "description": "Do not install tslib.", "type": "boolean", diff --git a/packages/react/src/generators/library/files/common/.babelrc__tmpl__ b/packages/react/src/generators/library/files/common/.babelrc__tmpl__ deleted file mode 100644 index b4962b709b3c56..00000000000000 --- a/packages/react/src/generators/library/files/common/.babelrc__tmpl__ +++ /dev/null @@ -1,16 +0,0 @@ -{ - "presets": [ - [ - "@nx/react/babel", { - "runtime": "automatic", - "useBuiltIns": "usage" - <% if (style === '@emotion/styled') { %>,"importSource": "@emotion/react"<% } %> - } - ] - ], - "plugins": [ - <% if (style === 'styled-components') { %>["styled-components", { "pure": true, "ssr": true }]<% } %> - <% if (style === 'styled-jsx') { %>"styled-jsx/babel"<% } %> - <% if (style === '@emotion/styled') { %>"@emotion/babel-plugin"<% } %> - ] -} diff --git a/packages/react/src/generators/library/lib/create-files.ts b/packages/react/src/generators/library/lib/create-files.ts index ebbdcb397a067b..e5163ff7c6c2bb 100644 --- a/packages/react/src/generators/library/lib/create-files.ts +++ b/packages/react/src/generators/library/lib/create-files.ts @@ -5,6 +5,7 @@ import { names, offsetFromRoot, toJS, + writeJson, } from '@nx/devkit'; import { getRelativePathToRootTsConfig } from '@nx/js'; @@ -38,10 +39,33 @@ export function createFiles(host: Tree, options: NormalizedSchema) { options.projectRoot, substitutions ); + } - if (host.exists(joinPathFragments(options.projectRoot, '.babelrc'))) { - host.delete(joinPathFragments(options.projectRoot, '.babelrc')); - } + if (options.compiler === 'babel') { + writeJson(host, joinPathFragments(options.projectRoot, '.babelrc'), { + presets: [ + [ + '@nx/react/babel', + { + runtime: 'automatic', + useBuiltIns: 'usage', + importSource: + options.style === '@emotion/styled' + ? '@emotion/react' + : undefined, + }, + ], + ], + plugins: [ + options.style === 'styled-components' + ? ['styled-components', { pure: true, ssr: true }] + : undefined, + options.style === 'styled-jsx' ? 'styled-jsx/babel' : undefined, + options.style === '@emotion/styled' + ? '@emotion/babel-plugin' + : undefined, + ].filter(Boolean), + }); } if (!options.publishable && !options.buildable) { diff --git a/packages/react/src/generators/library/lib/install-common-dependencies.ts b/packages/react/src/generators/library/lib/install-common-dependencies.ts index 6759aa6e146797..038b354e5ab162 100644 --- a/packages/react/src/generators/library/lib/install-common-dependencies.ts +++ b/packages/react/src/generators/library/lib/install-common-dependencies.ts @@ -6,6 +6,7 @@ import { } from '@nx/devkit'; import { addSwcDependencies } from '@nx/js/src/utils/swc/add-swc-dependencies'; import { + babelPresetReactVersion, lessVersion, reactDomVersion, reactVersion, @@ -50,6 +51,14 @@ export function installCommonDependencies( if (options.compiler === 'swc') { tasks.push(addSwcDependencies(host)); + } else if (options.compiler === 'babel') { + tasks.push( + addDependenciesToPackageJson( + host, + {}, + { '@babel/preset-react': babelPresetReactVersion } + ) + ); } return runTasksInSerial(...tasks); diff --git a/packages/react/src/generators/library/library.spec.ts b/packages/react/src/generators/library/library.spec.ts index 4ea26b3f522a53..bf3c008d1e0974 100644 --- a/packages/react/src/generators/library/library.spec.ts +++ b/packages/react/src/generators/library/library.spec.ts @@ -47,152 +47,148 @@ describe('lib', () => { }); }); - describe('not nested', () => { - it('should update project configuration', async () => { - await libraryGenerator(tree, defaultSchema); - const project = readProjectConfiguration(tree, 'my-lib'); - expect(project.root).toEqual('libs/my-lib'); - expect(project.targets.build).toBeUndefined(); - expect(project.targets.lint).toEqual({ - executor: '@nx/linter:eslint', - outputs: ['{options.outputFile}'], - options: { - lintFilePatterns: ['libs/my-lib/**/*.{ts,tsx,js,jsx}'], - }, - }); + it('should update project configuration', async () => { + await libraryGenerator(tree, defaultSchema); + const project = readProjectConfiguration(tree, 'my-lib'); + expect(project.root).toEqual('libs/my-lib'); + expect(project.targets.build).toBeUndefined(); + expect(project.targets.lint).toEqual({ + executor: '@nx/linter:eslint', + outputs: ['{options.outputFile}'], + options: { + lintFilePatterns: ['libs/my-lib/**/*.{ts,tsx,js,jsx}'], + }, }); + }); - it('should add vite types to tsconfigs', async () => { - await libraryGenerator(tree, { - ...defaultSchema, - bundler: 'vite', - unitTestRunner: 'vitest', - }); - const tsconfigApp = readJson(tree, 'libs/my-lib/tsconfig.lib.json'); - expect(tsconfigApp.compilerOptions.types).toEqual([ - 'node', - 'vite/client', - ]); - const tsconfigSpec = readJson(tree, 'libs/my-lib/tsconfig.spec.json'); - expect(tsconfigSpec.compilerOptions.types).toEqual([ - 'vitest/globals', - 'vitest/importMeta', - 'vite/client', - 'node', - ]); - }); + it('should add vite types to tsconfigs', async () => { + await libraryGenerator(tree, { + ...defaultSchema, + bundler: 'vite', + unitTestRunner: 'vitest', + }); + const tsconfigApp = readJson(tree, 'libs/my-lib/tsconfig.lib.json'); + expect(tsconfigApp.compilerOptions.types).toEqual(['node', 'vite/client']); + const tsconfigSpec = readJson(tree, 'libs/my-lib/tsconfig.spec.json'); + expect(tsconfigSpec.compilerOptions.types).toEqual([ + 'vitest/globals', + 'vitest/importMeta', + 'vite/client', + 'node', + ]); + }); - it('should update tags', async () => { - await libraryGenerator(tree, { ...defaultSchema, tags: 'one,two' }); - const project = readProjectConfiguration(tree, 'my-lib'); - expect(project).toEqual( - expect.objectContaining({ - tags: ['one', 'two'], - }) - ); - }); + it('should update tags', async () => { + await libraryGenerator(tree, { ...defaultSchema, tags: 'one,two' }); + const project = readProjectConfiguration(tree, 'my-lib'); + expect(project).toEqual( + expect.objectContaining({ + tags: ['one', 'two'], + }) + ); + }); - it('should add react and react-dom packages to package.json if not already present', async () => { - await libraryGenerator(tree, defaultSchema); + it('should add react and react-dom packages to package.json if not already present', async () => { + await libraryGenerator(tree, defaultSchema); - const packageJson = readJson(tree, '/package.json'); + const packageJson = readJson(tree, '/package.json'); - expect(packageJson).toMatchObject({ - dependencies: { - react: expect.anything(), - 'react-dom': expect.anything(), - }, - }); + expect(packageJson).toMatchObject({ + dependencies: { + react: expect.anything(), + 'react-dom': expect.anything(), + }, }); + }); - it('should update root tsconfig.base.json', async () => { - await libraryGenerator(tree, defaultSchema); - const tsconfigJson = readJson(tree, '/tsconfig.base.json'); - expect(tsconfigJson.compilerOptions.paths['@proj/my-lib']).toEqual([ - 'libs/my-lib/src/index.ts', - ]); - }); + it('should update root tsconfig.base.json', async () => { + await libraryGenerator(tree, defaultSchema); + const tsconfigJson = readJson(tree, '/tsconfig.base.json'); + expect(tsconfigJson.compilerOptions.paths['@proj/my-lib']).toEqual([ + 'libs/my-lib/src/index.ts', + ]); + }); - it('should create tsconfig.base.json out of tsconfig.json', async () => { - tree.rename('tsconfig.base.json', 'tsconfig.json'); + it('should create tsconfig.base.json out of tsconfig.json', async () => { + tree.rename('tsconfig.base.json', 'tsconfig.json'); - await libraryGenerator(tree, defaultSchema); + await libraryGenerator(tree, defaultSchema); - expect(tree.exists('tsconfig.base.json')).toEqual(true); - const tsconfigJson = readJson(tree, 'tsconfig.base.json'); - expect(tsconfigJson.compilerOptions.paths['@proj/my-lib']).toEqual([ - 'libs/my-lib/src/index.ts', - ]); + expect(tree.exists('tsconfig.base.json')).toEqual(true); + const tsconfigJson = readJson(tree, 'tsconfig.base.json'); + expect(tsconfigJson.compilerOptions.paths['@proj/my-lib']).toEqual([ + 'libs/my-lib/src/index.ts', + ]); + }); + + it('should update root tsconfig.base.json (no existing path mappings)', async () => { + updateJson(tree, 'tsconfig.base.json', (json) => { + json.compilerOptions.paths = undefined; + return json; }); - it('should update root tsconfig.base.json (no existing path mappings)', async () => { - updateJson(tree, 'tsconfig.base.json', (json) => { - json.compilerOptions.paths = undefined; - return json; - }); + await libraryGenerator(tree, defaultSchema); + const tsconfigJson = readJson(tree, '/tsconfig.base.json'); + expect(tsconfigJson.compilerOptions.paths['@proj/my-lib']).toEqual([ + 'libs/my-lib/src/index.ts', + ]); + }); - await libraryGenerator(tree, defaultSchema); - const tsconfigJson = readJson(tree, '/tsconfig.base.json'); - expect(tsconfigJson.compilerOptions.paths['@proj/my-lib']).toEqual([ - 'libs/my-lib/src/index.ts', - ]); - }); + it('should create a local tsconfig.json', async () => { + await libraryGenerator(tree, defaultSchema); + + const tsconfigJson = readJson(tree, 'libs/my-lib/tsconfig.json'); + expect(tsconfigJson.extends).toBe('../../tsconfig.base.json'); + expect(tsconfigJson.references).toEqual([ + { + path: './tsconfig.lib.json', + }, + { + path: './tsconfig.spec.json', + }, + ]); + expect(tsconfigJson.compilerOptions.strict).toEqual(true); + }); - it('should create a local tsconfig.json', async () => { - await libraryGenerator(tree, defaultSchema); + it('should extend the local tsconfig.json with tsconfig.spec.json', async () => { + await libraryGenerator(tree, defaultSchema); + const tsconfigJson = readJson(tree, 'libs/my-lib/tsconfig.spec.json'); + expect(tsconfigJson.extends).toEqual('./tsconfig.json'); + }); - const tsconfigJson = readJson(tree, 'libs/my-lib/tsconfig.json'); - expect(tsconfigJson.extends).toBe('../../tsconfig.base.json'); - expect(tsconfigJson.references).toEqual([ - { - path: './tsconfig.lib.json', - }, - { - path: './tsconfig.spec.json', - }, - ]); - expect(tsconfigJson.compilerOptions.strict).toEqual(true); - }); - - it('should extend the local tsconfig.json with tsconfig.spec.json', async () => { - await libraryGenerator(tree, defaultSchema); - const tsconfigJson = readJson(tree, 'libs/my-lib/tsconfig.spec.json'); - expect(tsconfigJson.extends).toEqual('./tsconfig.json'); - }); - - it('should extend the local tsconfig.json with tsconfig.lib.json', async () => { - await libraryGenerator(tree, defaultSchema); - const tsconfigJson = readJson(tree, 'libs/my-lib/tsconfig.lib.json'); - expect(tsconfigJson.extends).toEqual('./tsconfig.json'); - }); - - it('should ignore test files in tsconfig.lib.json', async () => { - await libraryGenerator(tree, defaultSchema); - const tsconfigJson = readJson(tree, 'libs/my-lib/tsconfig.lib.json'); - expect(tsconfigJson.exclude).toEqual([ - 'jest.config.ts', - 'src/**/*.spec.ts', - 'src/**/*.test.ts', - 'src/**/*.spec.tsx', - 'src/**/*.test.tsx', - 'src/**/*.spec.js', - 'src/**/*.test.js', - 'src/**/*.spec.jsx', - 'src/**/*.test.jsx', - ]); - }); + it('should extend the local tsconfig.json with tsconfig.lib.json', async () => { + await libraryGenerator(tree, defaultSchema); + const tsconfigJson = readJson(tree, 'libs/my-lib/tsconfig.lib.json'); + expect(tsconfigJson.extends).toEqual('./tsconfig.json'); + }); - it('should generate files', async () => { - await libraryGenerator(tree, defaultSchema); - expect(tree.exists('libs/my-lib/package.json')).toBeFalsy(); - expect(tree.exists(`libs/my-lib/jest.config.ts`)).toBeTruthy(); - expect(tree.exists('libs/my-lib/src/index.ts')).toBeTruthy(); - expect(tree.exists('libs/my-lib/src/lib/my-lib.tsx')).toBeTruthy(); - expect(tree.exists('libs/my-lib/src/lib/my-lib.module.css')).toBeTruthy(); - expect(tree.exists('libs/my-lib/src/lib/my-lib.spec.tsx')).toBeTruthy(); + it('should ignore test files in tsconfig.lib.json', async () => { + await libraryGenerator(tree, defaultSchema); + const tsconfigJson = readJson(tree, 'libs/my-lib/tsconfig.lib.json'); + expect(tsconfigJson.exclude).toEqual([ + 'jest.config.ts', + 'src/**/*.spec.ts', + 'src/**/*.test.ts', + 'src/**/*.spec.tsx', + 'src/**/*.test.tsx', + 'src/**/*.spec.js', + 'src/**/*.test.js', + 'src/**/*.spec.jsx', + 'src/**/*.test.jsx', + ]); + }); - const eslintJson = readJson(tree, 'libs/my-lib/.eslintrc.json'); - expect(eslintJson).toMatchInlineSnapshot(` + it('should generate files', async () => { + await libraryGenerator(tree, defaultSchema); + expect(tree.exists('libs/my-lib/package.json')).toBeFalsy(); + expect(tree.exists(`libs/my-lib/jest.config.ts`)).toBeTruthy(); + expect(tree.exists('libs/my-lib/src/index.ts')).toBeTruthy(); + expect(tree.exists('libs/my-lib/src/lib/my-lib.tsx')).toBeTruthy(); + expect(tree.exists('libs/my-lib/src/lib/my-lib.module.css')).toBeTruthy(); + expect(tree.exists('libs/my-lib/src/lib/my-lib.spec.tsx')).toBeTruthy(); + + const eslintJson = readJson(tree, 'libs/my-lib/.eslintrc.json'); + expect(eslintJson).toMatchInlineSnapshot(` { "extends": [ "plugin:@nx/react", @@ -228,17 +224,28 @@ describe('lib', () => { ], } `); + }); + it('should update jest.config.ts for babel', async () => { + await libraryGenerator(tree, { + ...defaultSchema, + buildable: true, + compiler: 'babel', + }); + expect(tree.read('libs/my-lib/jest.config.ts', 'utf-8')).toContain( + "['babel-jest', { presets: ['@nx/react/babel'] }]" + ); + }); + + it('should add @babel/preset-react when using babel compiler', async () => { + await libraryGenerator(tree, { + ...defaultSchema, + compiler: 'babel', + directory: 'myDir', + tags: 'one', }); - it('should update jest.config.ts for babel', async () => { - await libraryGenerator(tree, { - ...defaultSchema, - buildable: true, - compiler: 'babel', - }); - expect(tree.read('libs/my-lib/jest.config.ts', 'utf-8')).toContain( - "['babel-jest', { presets: ['@nx/react/babel'] }]" - ); - }); + + const packageJson = readJson(tree, 'package.json'); + expect(packageJson.devDependencies['@babel/preset-react']).toBeDefined(); }); describe('nested', () => { diff --git a/packages/react/src/generators/library/library.ts b/packages/react/src/generators/library/library.ts index 1016650418710f..6e9123669b4acb 100644 --- a/packages/react/src/generators/library/library.ts +++ b/packages/react/src/generators/library/library.ts @@ -43,7 +43,6 @@ export async function libraryGenerator(host: Tree, schema: Schema) { ...options, e2eTestRunner: 'none', skipFormat: true, - skipBabelConfig: options.bundler === 'vite' || options.compiler === 'swc', skipHelperLibs: options.bundler === 'vite', }); tasks.push(initTask); diff --git a/packages/react/src/generators/remote/schema.d.ts b/packages/react/src/generators/remote/schema.d.ts index 2fa825a4e5791d..424385aa051bbf 100644 --- a/packages/react/src/generators/remote/schema.d.ts +++ b/packages/react/src/generators/remote/schema.d.ts @@ -17,7 +17,7 @@ export interface Schema { routing?: boolean; setParserOptionsProject?: boolean; skipFormat: boolean; - skipWorkspaceJson?: boolean; + skipNxJson?: boolean; ssr?: boolean; strict?: boolean; style: SupportedStyles; diff --git a/packages/react/src/generators/remote/schema.json b/packages/react/src/generators/remote/schema.json index 7e8b9acb9b4fae..bac051c1864345 100644 --- a/packages/react/src/generators/remote/schema.json +++ b/packages/react/src/generators/remote/schema.json @@ -84,7 +84,7 @@ "default": false, "x-priority": "internal" }, - "skipWorkspaceJson": { + "skipNxJson": { "description": "Skip updating workspace.json with default options based on values provided to this app (e.g. babel, style).", "type": "boolean", "default": false, diff --git a/packages/rollup/src/generators/init/init.spec.ts b/packages/rollup/src/generators/init/init.spec.ts index cce9883978169e..9d9a353bdfc629 100644 --- a/packages/rollup/src/generators/init/init.spec.ts +++ b/packages/rollup/src/generators/init/init.spec.ts @@ -11,23 +11,6 @@ describe('rollupInitGenerator', () => { tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); }); - it('should support babel', async () => { - updateJson(tree, 'nx.json', (json) => { - json.namedInputs = { - sharedGlobals: ['{workspaceRoot}/exiting-file.json'], - }; - return json; - }); - - await rollupInitGenerator(tree, { compiler: 'babel' }); - - expect(tree.exists('babel.config.json')); - const sharedGlobals = readJson(tree, 'nx.json') - .namedInputs.sharedGlobals; - expect(sharedGlobals).toContain('{workspaceRoot}/exiting-file.json'); - expect(sharedGlobals).toContain('{workspaceRoot}/babel.config.json'); - }); - it('should support swc', async () => { await rollupInitGenerator(tree, { compiler: 'swc' }); diff --git a/packages/rollup/src/generators/init/init.ts b/packages/rollup/src/generators/init/init.ts index 891b32c8001c1a..761bb50ee30bd3 100644 --- a/packages/rollup/src/generators/init/init.ts +++ b/packages/rollup/src/generators/init/init.ts @@ -17,10 +17,6 @@ import { addBabelInputs } from '@nx/js/src/utils/add-babel-inputs'; export async function rollupInitGenerator(tree: Tree, schema: Schema) { let task: GeneratorCallback; - if (schema.compiler === 'babel') { - addBabelInputs(tree); - } - if (schema.compiler === 'swc') { task = addDependenciesToPackageJson( tree, diff --git a/packages/web/src/generators/application/application.ts b/packages/web/src/generators/application/application.ts index d4fd45a0239362..2f6d643c7a72e0 100644 --- a/packages/web/src/generators/application/application.ts +++ b/packages/web/src/generators/application/application.ts @@ -184,8 +184,6 @@ export async function applicationGenerator(host: Tree, schema: Schema) { const webTask = await webInitGenerator(host, { ...options, skipFormat: true, - // Vite does not use babel by default - skipBabelConfig: options.bundler === 'vite', }); tasks.push(webTask); diff --git a/packages/web/src/generators/application/schema.json b/packages/web/src/generators/application/schema.json index 5ce0957d30e931..18045d87215da0 100644 --- a/packages/web/src/generators/application/schema.json +++ b/packages/web/src/generators/application/schema.json @@ -46,8 +46,8 @@ "compiler": { "type": "string", "description": "The compiler to use", - "enum": ["babel", "swc"], - "default": "babel", + "enum": ["swc", "babel"], + "default": "swc", "x-priority": "important" }, "bundler": { diff --git a/packages/web/src/generators/init/init.ts b/packages/web/src/generators/init/init.ts index a703a0cac0e653..e3ca235ca0492b 100644 --- a/packages/web/src/generators/init/init.ts +++ b/packages/web/src/generators/init/init.ts @@ -8,8 +8,6 @@ import { runTasksInSerial, Tree, } from '@nx/devkit'; - -import { addBabelInputs } from '@nx/js/src/utils/add-babel-inputs'; import { initGenerator as jsInitGenerator } from '@nx/js'; import { nxVersion, @@ -65,7 +63,6 @@ export async function webInitGenerator(tree: Tree, schema: Schema) { const installTask = updateDependencies(tree, schema); tasks.push(installTask); } - addBabelInputs(tree); if (!schema.skipFormat) { await formatFiles(tree); diff --git a/packages/web/src/generators/init/schema.d.ts b/packages/web/src/generators/init/schema.d.ts index 7276adf217146c..00c2cc6a747670 100644 --- a/packages/web/src/generators/init/schema.d.ts +++ b/packages/web/src/generators/init/schema.d.ts @@ -4,5 +4,4 @@ export interface Schema { e2eTestRunner?: 'cypress' | 'none'; skipFormat?: boolean; skipPackageJson?: boolean; - skipBabelConfig?: boolean; } diff --git a/packages/web/src/generators/init/schema.json b/packages/web/src/generators/init/schema.json index b8be6c1f8fc359..ab86ca8d8c19e9 100644 --- a/packages/web/src/generators/init/schema.json +++ b/packages/web/src/generators/init/schema.json @@ -34,11 +34,6 @@ "type": "boolean", "default": false, "x-priority": "internal" - }, - "skipBabelConfig": { - "description": "Do not generate a root babel.config.json (if babel is not needed).", - "type": "boolean", - "default": false } }, "required": [] diff --git a/packages/webpack/src/generators/init/init.spec.ts b/packages/webpack/src/generators/init/init.spec.ts index da710f2c81e252..8ac0257cb6d499 100644 --- a/packages/webpack/src/generators/init/init.spec.ts +++ b/packages/webpack/src/generators/init/init.spec.ts @@ -10,23 +10,6 @@ describe('webpackInitGenerator', () => { tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); }); - it('should support babel', async () => { - updateJson(tree, 'nx.json', (json) => { - json.namedInputs = { - sharedGlobals: ['{workspaceRoot}/exiting-file.json'], - }; - return json; - }); - - await webpackInitGenerator(tree, { compiler: 'babel' }); - - expect(tree.exists('babel.config.json')); - const sharedGlobals = readJson(tree, 'nx.json') - .namedInputs.sharedGlobals; - expect(sharedGlobals).toContain('{workspaceRoot}/exiting-file.json'); - expect(sharedGlobals).toContain('{workspaceRoot}/babel.config.json'); - }); - it('should support swc', async () => { await webpackInitGenerator(tree, { compiler: 'swc' }); diff --git a/packages/webpack/src/generators/init/init.ts b/packages/webpack/src/generators/init/init.ts index 37728706130ca5..81ab64d5b8bfab 100644 --- a/packages/webpack/src/generators/init/init.ts +++ b/packages/webpack/src/generators/init/init.ts @@ -22,9 +22,6 @@ import { addBabelInputs } from '@nx/js/src/utils/add-babel-inputs'; export async function webpackInitGenerator(tree: Tree, schema: Schema) { const tasks: GeneratorCallback[] = []; - if (schema.compiler === 'babel') { - addBabelInputs(tree); - } const devDependencies = { '@nx/webpack': nxVersion, };