feat(js): do not generate root babel.config.json for babel projects (#17289)
This commit is contained in:
parent
5c7db06508
commit
08339ee49f
@ -50,10 +50,16 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Frontend project that needs to access this application. This sets up proxy configuration."
|
"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": {
|
"babelJest": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Use `babel` instead `ts-jest`.",
|
"description": "Use `babel` instead `ts-jest`.",
|
||||||
"default": false
|
"default": false,
|
||||||
|
"x-deprecated": "Use --swcJest instead for faster compilation"
|
||||||
},
|
},
|
||||||
"pascalCaseFiles": {
|
"pascalCaseFiles": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
|
|||||||
@ -54,10 +54,16 @@
|
|||||||
"description": "Frontend project that needs to access this application. This sets up proxy configuration.",
|
"description": "Frontend project that needs to access this application. This sets up proxy configuration.",
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
|
"swcJest": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use `@swc/jest` instead `ts-jest` for faster test compilation.",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
"babelJest": {
|
"babelJest": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Use `babel` instead of `ts-jest`.",
|
"description": "Use `babel` instead `ts-jest`.",
|
||||||
"default": false
|
"default": false,
|
||||||
|
"x-deprecated": "Use --swcJest instead for faster compilation"
|
||||||
},
|
},
|
||||||
"pascalCaseFiles": {
|
"pascalCaseFiles": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
|
|||||||
@ -92,8 +92,8 @@
|
|||||||
"default": false,
|
"default": false,
|
||||||
"x-priority": "internal"
|
"x-priority": "internal"
|
||||||
},
|
},
|
||||||
"skipWorkspaceJson": {
|
"skipNxJson": {
|
||||||
"description": "Skip updating `workspace.json` with default options based on values provided to this app (e.g. babel, style).",
|
"description": "Skip updating `nx.json` with default options based on values provided to this app.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": false,
|
||||||
"x-priority": "internal"
|
"x-priority": "internal"
|
||||||
|
|||||||
@ -73,7 +73,7 @@
|
|||||||
"default": false,
|
"default": false,
|
||||||
"x-priority": "internal"
|
"x-priority": "internal"
|
||||||
},
|
},
|
||||||
"skipWorkspaceJson": {
|
"skipNxJson": {
|
||||||
"description": "Skip updating workspace.json with default options based on values provided to this app (e.g. babel, style).",
|
"description": "Skip updating workspace.json with default options based on values provided to this app (e.g. babel, style).",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": false,
|
||||||
|
|||||||
@ -31,11 +31,6 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
"skipBabelConfig": {
|
|
||||||
"description": "Do not generate a root babel.config.json (if babel is not needed).",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"skipHelperLibs": {
|
"skipHelperLibs": {
|
||||||
"description": "Do not install tslib.",
|
"description": "Do not install tslib.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
|
|||||||
@ -78,7 +78,7 @@
|
|||||||
"default": false,
|
"default": false,
|
||||||
"x-priority": "internal"
|
"x-priority": "internal"
|
||||||
},
|
},
|
||||||
"skipWorkspaceJson": {
|
"skipNxJson": {
|
||||||
"description": "Skip updating workspace.json with default options based on values provided to this app (e.g. babel, style).",
|
"description": "Skip updating workspace.json with default options based on values provided to this app (e.g. babel, style).",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": false,
|
||||||
|
|||||||
@ -43,8 +43,8 @@
|
|||||||
"compiler": {
|
"compiler": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The compiler to use",
|
"description": "The compiler to use",
|
||||||
"enum": ["babel", "swc"],
|
"enum": ["swc", "babel"],
|
||||||
"default": "babel",
|
"default": "swc",
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"bundler": {
|
"bundler": {
|
||||||
|
|||||||
@ -37,11 +37,6 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": false,
|
||||||
"x-priority": "internal"
|
"x-priority": "internal"
|
||||||
},
|
|
||||||
"skipBabelConfig": {
|
|
||||||
"description": "Do not generate a root babel.config.json (if babel is not needed).",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [],
|
"required": [],
|
||||||
|
|||||||
@ -21,7 +21,7 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["babel", "swc", "tsc"],
|
"enum": ["babel", "swc", "tsc"],
|
||||||
"description": "The compiler to use to build source.",
|
"description": "The compiler to use to build source.",
|
||||||
"default": "babel"
|
"default": "swc"
|
||||||
},
|
},
|
||||||
"main": {
|
"main": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
@ -7,7 +7,6 @@ import {
|
|||||||
killPorts,
|
killPorts,
|
||||||
newProject,
|
newProject,
|
||||||
readFile,
|
readFile,
|
||||||
removeFile,
|
|
||||||
rmDist,
|
rmDist,
|
||||||
runCLI,
|
runCLI,
|
||||||
runCLIAsync,
|
runCLIAsync,
|
||||||
@ -100,10 +99,10 @@ describe('Web Components Applications', () => {
|
|||||||
checkFilesExist(`dist/libs/${libName}/_should_keep.txt`);
|
checkFilesExist(`dist/libs/${libName}/_should_keep.txt`);
|
||||||
}, 120000);
|
}, 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');
|
const appName = uniq('app');
|
||||||
runCLI(
|
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) => {
|
updateFile(`apps/${appName}/src/app/app.element.ts`, (content) => {
|
||||||
@ -155,6 +154,48 @@ describe('Web Components Applications', () => {
|
|||||||
);
|
);
|
||||||
}, 120000);
|
}, 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 () => {
|
it('should support custom webpackConfig option', async () => {
|
||||||
const appName = uniq('app');
|
const appName = uniq('app');
|
||||||
runCLI(
|
runCLI(
|
||||||
@ -257,7 +298,7 @@ describe('CLI - Environment Variables', () => {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
runCLI(
|
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);
|
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];`;
|
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(
|
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);
|
const content2 = readFile(main2);
|
||||||
@ -401,16 +442,16 @@ describe('index.html interpolation', () => {
|
|||||||
const srcPath = `apps/${appName}/src`;
|
const srcPath = `apps/${appName}/src`;
|
||||||
const indexPath = `${srcPath}/index.html`;
|
const indexPath = `${srcPath}/index.html`;
|
||||||
const indexContent = `<!DOCTYPE html>
|
const indexContent = `<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang='en'>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset='utf-8' />
|
||||||
<title>BestReactApp</title>
|
<title>BestReactApp</title>
|
||||||
<base href="/" />
|
<base href='/' />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name='viewport' content='width=device-width, initial-scale=1' />
|
||||||
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
<link rel='icon' type='image/x-icon' href='favicon.ico' />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id='root'></div>
|
||||||
<div>Nx Variable: %NX_VARIABLE%</div>
|
<div>Nx Variable: %NX_VARIABLE%</div>
|
||||||
<div>Some other variable: %SOME_OTHER_VARIABLE%</div>
|
<div>Some other variable: %SOME_OTHER_VARIABLE%</div>
|
||||||
<div>Deploy Url: %DEPLOY_URL%</div>
|
<div>Deploy Url: %DEPLOY_URL%</div>
|
||||||
|
|||||||
@ -10,6 +10,8 @@ export interface Schema {
|
|||||||
tags?: string;
|
tags?: string;
|
||||||
linter: Linter;
|
linter: Linter;
|
||||||
frontendProject?: string;
|
frontendProject?: string;
|
||||||
|
swcJest?: boolean;
|
||||||
|
/** @deprecated use `swcJest` instead */
|
||||||
babelJest?: boolean;
|
babelJest?: boolean;
|
||||||
js: boolean;
|
js: boolean;
|
||||||
pascalCaseFiles: boolean;
|
pascalCaseFiles: boolean;
|
||||||
|
|||||||
@ -50,10 +50,16 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Frontend project that needs to access this application. This sets up proxy configuration."
|
"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": {
|
"babelJest": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Use `babel` instead `ts-jest`.",
|
"description": "Use `babel` instead `ts-jest`.",
|
||||||
"default": false
|
"default": false,
|
||||||
|
"x-deprecated": "Use --swcJest instead for faster compilation"
|
||||||
},
|
},
|
||||||
"pascalCaseFiles": {
|
"pascalCaseFiles": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
|
|||||||
@ -8,7 +8,12 @@ export default {
|
|||||||
transform: {
|
transform: {
|
||||||
'^.+\\\\.[tj]sx?$': [
|
'^.+\\\\.[tj]sx?$': [
|
||||||
'@swc/jest',
|
'@swc/jest',
|
||||||
{ jsc: { transform: { react: { runtime: 'automatic' } } } },
|
{
|
||||||
|
jsc: {
|
||||||
|
parser: { syntax: 'typescript', tsx: true },
|
||||||
|
transform: { react: { runtime: 'automatic' } },
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
||||||
|
|||||||
@ -60,15 +60,6 @@ describe('jestProject', () => {
|
|||||||
expect(tree.read('libs/lib1/jest.config.ts', 'utf-8')).toMatchSnapshot();
|
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 () => {
|
it('should alter project configuration', async () => {
|
||||||
await jestProjectGenerator(tree, {
|
await jestProjectGenerator(tree, {
|
||||||
...defaultOptions,
|
...defaultOptions,
|
||||||
|
|||||||
@ -21,7 +21,7 @@ export function createFiles(tree: Tree, options: NormalizedJestProjectSchema) {
|
|||||||
transformer = '@swc/jest';
|
transformer = '@swc/jest';
|
||||||
if (options.supportTsx) {
|
if (options.supportTsx) {
|
||||||
transformerOptions =
|
transformerOptions =
|
||||||
"{ jsc: { transform: { react: { runtime: 'automatic' } } } }";
|
"{ jsc: { parser: { syntax: 'typescript', tsx: true }, transform: { react: { runtime: 'automatic' } } } }";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
transformer = 'ts-jest';
|
transformer = 'ts-jest';
|
||||||
@ -48,15 +48,6 @@ export function createFiles(tree: Tree, options: NormalizedJestProjectSchema) {
|
|||||||
tree.delete(join(projectConfig.root, './src/test-setup.ts'));
|
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) {
|
if (options.js) {
|
||||||
tree.rename(
|
tree.rename(
|
||||||
join(projectConfig.root, 'jest.config.ts'),
|
join(projectConfig.root, 'jest.config.ts'),
|
||||||
|
|||||||
@ -91,10 +91,6 @@ export async function projectGenerator(
|
|||||||
});
|
});
|
||||||
tasks.push(viteTask);
|
tasks.push(viteTask);
|
||||||
}
|
}
|
||||||
if (options.bundler === 'rollup') {
|
|
||||||
ensureBabelRootConfigExists(tree);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.linter !== 'none') {
|
if (options.linter !== 'none') {
|
||||||
const lintCallback = await addLint(tree, options);
|
const lintCallback = await addLint(tree, options);
|
||||||
tasks.push(lintCallback);
|
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) {
|
function getOutputPath(options: NormalizedSchema, destinationDir?: string) {
|
||||||
const parts = ['dist'];
|
const parts = ['dist'];
|
||||||
if (destinationDir) {
|
if (destinationDir) {
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
formatFiles,
|
|
||||||
joinPathFragments,
|
joinPathFragments,
|
||||||
readNxJson,
|
readNxJson,
|
||||||
Tree,
|
Tree,
|
||||||
@ -7,6 +6,8 @@ import {
|
|||||||
writeJson,
|
writeJson,
|
||||||
} from '@nx/devkit';
|
} 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) {
|
export function addBabelInputs(tree: Tree) {
|
||||||
const nxJson = readNxJson(tree);
|
const nxJson = readNxJson(tree);
|
||||||
let globalBabelFile = ['babel.config.js', 'babel.config.json'].find((file) =>
|
let globalBabelFile = ['babel.config.js', 'babel.config.json'].find((file) =>
|
||||||
|
|||||||
@ -65,7 +65,6 @@ export async function nextInitGenerator(host: Tree, schema: InitSchema) {
|
|||||||
const reactTask = await reactInitGenerator(host, {
|
const reactTask = await reactInitGenerator(host, {
|
||||||
...schema,
|
...schema,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
skipBabelConfig: true,
|
|
||||||
});
|
});
|
||||||
tasks.push(reactTask);
|
tasks.push(reactTask);
|
||||||
|
|
||||||
|
|||||||
@ -13,67 +13,6 @@ describe('next library', () => {
|
|||||||
let mockedInstalledCypressVersion: jest.Mock<
|
let mockedInstalledCypressVersion: jest.Mock<
|
||||||
ReturnType<typeof installedCypressVersion>
|
ReturnType<typeof installedCypressVersion>
|
||||||
> = installedCypressVersion as never;
|
> = 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 () => {
|
it('should use @nx/next images.d.ts file', async () => {
|
||||||
const baseOptions: Schema = {
|
const baseOptions: Schema = {
|
||||||
name: '',
|
name: '',
|
||||||
|
|||||||
@ -71,36 +71,6 @@ export async function libraryGenerator(host: Tree, rawOptions: Schema) {
|
|||||||
);
|
);
|
||||||
addTsConfigPath(host, `${options.importPath}/server`, [serverEntryPath]);
|
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(
|
updateJson(
|
||||||
host,
|
host,
|
||||||
joinPathFragments(options.projectRoot, 'tsconfig.json'),
|
joinPathFragments(options.projectRoot, 'tsconfig.json'),
|
||||||
|
|||||||
@ -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 () => {
|
it('should use babel for jest', async () => {
|
||||||
await applicationGenerator(tree, {
|
await applicationGenerator(tree, {
|
||||||
name: 'myNodeApp',
|
name: 'myNodeApp',
|
||||||
@ -368,6 +394,7 @@ describe('app', () => {
|
|||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('--js flag', () => {
|
describe('--js flag', () => {
|
||||||
it('should generate js files instead of ts files', async () => {
|
it('should generate js files instead of ts files', async () => {
|
||||||
await applicationGenerator(tree, {
|
await applicationGenerator(tree, {
|
||||||
|
|||||||
@ -398,7 +398,7 @@ export async function applicationGenerator(tree: Tree, schema: Schema) {
|
|||||||
skipSerializers: true,
|
skipSerializers: true,
|
||||||
supportTsx: options.js,
|
supportTsx: options.js,
|
||||||
testEnvironment: 'node',
|
testEnvironment: 'node',
|
||||||
compiler: 'tsc',
|
compiler: options.swcJest ? 'swc' : 'tsc',
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
});
|
});
|
||||||
tasks.push(jestTask);
|
tasks.push(jestTask);
|
||||||
|
|||||||
@ -10,6 +10,8 @@ export interface Schema {
|
|||||||
linter?: Linter;
|
linter?: Linter;
|
||||||
tags?: string;
|
tags?: string;
|
||||||
frontendProject?: string;
|
frontendProject?: string;
|
||||||
|
swcJest?: boolean;
|
||||||
|
/** @deprecated use `swcJest` instead */
|
||||||
babelJest?: boolean;
|
babelJest?: boolean;
|
||||||
js?: boolean;
|
js?: boolean;
|
||||||
pascalCaseFiles?: boolean;
|
pascalCaseFiles?: boolean;
|
||||||
|
|||||||
@ -54,10 +54,16 @@
|
|||||||
"description": "Frontend project that needs to access this application. This sets up proxy configuration.",
|
"description": "Frontend project that needs to access this application. This sets up proxy configuration.",
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
|
"swcJest": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use `@swc/jest` instead `ts-jest` for faster test compilation.",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
"babelJest": {
|
"babelJest": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Use `babel` instead of `ts-jest`.",
|
"description": "Use `babel` instead `ts-jest`.",
|
||||||
"default": false
|
"default": false,
|
||||||
|
"x-deprecated": "Use --swcJest instead for faster compilation"
|
||||||
},
|
},
|
||||||
"pascalCaseFiles": {
|
"pascalCaseFiles": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
|
|||||||
@ -35,47 +35,4 @@ describe('init', () => {
|
|||||||
expect(content).toMatch(/# React Native/);
|
expect(content).toMatch(/# React Native/);
|
||||||
expect(content).toMatch(/# Nested node_modules/);
|
expect(content).toMatch(/# Nested node_modules/);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('babel config', () => {
|
|
||||||
it('should create babel config if not present', async () => {
|
|
||||||
updateJson<NxJsonConfiguration>(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<NxJsonConfiguration>(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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -10,7 +10,6 @@ import {
|
|||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { Schema } from './schema';
|
import { Schema } from './schema';
|
||||||
|
|
||||||
import { addBabelInputs } from '@nx/js/src/utils/add-babel-inputs';
|
|
||||||
import { jestInitGenerator } from '@nx/jest';
|
import { jestInitGenerator } from '@nx/jest';
|
||||||
import { detoxInitGenerator } from '@nx/detox';
|
import { detoxInitGenerator } from '@nx/detox';
|
||||||
import { babelPresetReactVersion } from '@nx/react/src/utils/versions';
|
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) {
|
export async function reactNativeInitGenerator(host: Tree, schema: Schema) {
|
||||||
addGitIgnoreEntry(host);
|
addGitIgnoreEntry(host);
|
||||||
await addBabelInputs(host);
|
|
||||||
const tasks: GeneratorCallback[] = [];
|
const tasks: GeneratorCallback[] = [];
|
||||||
|
|
||||||
tasks.push(
|
tasks.push(
|
||||||
|
|||||||
@ -1,4 +1,10 @@
|
|||||||
import { ExecutorContext, logger, workspaceRoot } from '@nx/devkit';
|
import {
|
||||||
|
createProjectGraphAsync,
|
||||||
|
ExecutorContext,
|
||||||
|
logger,
|
||||||
|
ProjectGraphProjectNode,
|
||||||
|
workspaceRoot,
|
||||||
|
} from '@nx/devkit';
|
||||||
import { composePluginsSync } from '@nx/webpack/src/utils/config';
|
import { composePluginsSync } from '@nx/webpack/src/utils/config';
|
||||||
import { NormalizedWebpackExecutorOptions } from '@nx/webpack/src/executors/webpack/schema';
|
import { NormalizedWebpackExecutorOptions } from '@nx/webpack/src/executors/webpack/schema';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
@ -10,6 +16,7 @@ import {
|
|||||||
} from 'webpack';
|
} from 'webpack';
|
||||||
import { mergePlugins } from './merge-plugins';
|
import { mergePlugins } from './merge-plugins';
|
||||||
import { withReact } from '../with-react';
|
import { withReact } from '../with-react';
|
||||||
|
import { existsSync } from 'fs';
|
||||||
|
|
||||||
// This is shamelessly taken from CRA and modified for NX use
|
// This is shamelessly taken from CRA and modified for NX use
|
||||||
// https://github.com/facebook/create-react-app/blob/4784997f0682e75eb32a897b4ffe34d735912e6c/packages/react-scripts/config/env.js#L71
|
// https://github.com/facebook/create-react-app/blob/4784997f0682e75eb32a897b4ffe34d735912e6c/packages/react-scripts/config/env.js#L71
|
||||||
@ -58,6 +65,90 @@ export const core = (prev, options) => ({
|
|||||||
disableWebpackDefaults: true,
|
disableWebpackDefaults: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
interface NxProjectData {
|
||||||
|
workspaceRoot: string;
|
||||||
|
projectRoot: string;
|
||||||
|
sourceRoot: string;
|
||||||
|
projectNode?: ProjectGraphProjectNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getProjectData = async (
|
||||||
|
storybookOptions: any
|
||||||
|
): Promise<NxProjectData> => {
|
||||||
|
const fallbackData = {
|
||||||
|
workspaceRoot: storybookOptions.configDir,
|
||||||
|
projectRoot: '',
|
||||||
|
sourceRoot: '',
|
||||||
|
};
|
||||||
|
// Edge-case: not running from Nx
|
||||||
|
if (!process.env.NX_WORKSPACE_ROOT) return fallbackData;
|
||||||
|
|
||||||
|
const projectGraph = await createProjectGraphAsync();
|
||||||
|
const projectNode = projectGraph.nodes[process.env.NX_TASK_TARGET_PROJECT];
|
||||||
|
|
||||||
|
return projectNode
|
||||||
|
? {
|
||||||
|
workspaceRoot: process.env.NX_WORKSPACE_ROOT,
|
||||||
|
projectRoot: projectNode.data.root,
|
||||||
|
sourceRoot: projectNode.data.sourceRoot,
|
||||||
|
projectNode,
|
||||||
|
}
|
||||||
|
: // Edge-case: missing project node
|
||||||
|
fallbackData;
|
||||||
|
};
|
||||||
|
|
||||||
|
const fixBabelConfigurationIfNeeded = (
|
||||||
|
webpackConfig: Configuration,
|
||||||
|
projectData: NxProjectData
|
||||||
|
): void => {
|
||||||
|
if (!projectData.projectNode) return;
|
||||||
|
|
||||||
|
const isUsingBabelUpwardRootMode = Object.keys(
|
||||||
|
projectData.projectNode.data.targets
|
||||||
|
).find((k) => {
|
||||||
|
const targetConfig = projectData.projectNode.data.targets[k];
|
||||||
|
return (
|
||||||
|
(targetConfig.executor === '@nx/webpack:webpack' ||
|
||||||
|
targetConfig.executor === '@nrwl/webpack:webpack') &&
|
||||||
|
targetConfig.options?.babelUpwardRootMode
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isUsingBabelUpwardRootMode) return;
|
||||||
|
|
||||||
|
let babelrcPath: string;
|
||||||
|
for (const ext of ['', '.json', '.js', '.cjs', '.mjs', '.cts']) {
|
||||||
|
const candidate = join(
|
||||||
|
projectData.workspaceRoot,
|
||||||
|
projectData.projectRoot,
|
||||||
|
`.babelrc${ext}`
|
||||||
|
);
|
||||||
|
if (existsSync(candidate)) {
|
||||||
|
babelrcPath = candidate;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unexpected setup, skip.
|
||||||
|
if (!babelrcPath) return;
|
||||||
|
|
||||||
|
let babelRuleItem;
|
||||||
|
for (const rule of webpackConfig.module.rules) {
|
||||||
|
if (typeof rule === 'string') continue;
|
||||||
|
if (!Array.isArray(rule.use)) continue;
|
||||||
|
for (const item of rule.use) {
|
||||||
|
if (typeof item !== 'string' && item['loader'].includes('babel-loader')) {
|
||||||
|
babelRuleItem = item;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (babelRuleItem) {
|
||||||
|
babelRuleItem.options.configFile = babelrcPath;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const webpack = async (
|
export const webpack = async (
|
||||||
storybookWebpackConfig: Configuration = {},
|
storybookWebpackConfig: Configuration = {},
|
||||||
options: any
|
options: any
|
||||||
@ -78,12 +169,15 @@ export const webpack = async (
|
|||||||
const { withNx, withWeb } = require('@nx/webpack');
|
const { withNx, withWeb } = require('@nx/webpack');
|
||||||
const tsconfigPath = join(options.configDir, 'tsconfig.json');
|
const tsconfigPath = join(options.configDir, 'tsconfig.json');
|
||||||
|
|
||||||
|
const projectData = await getProjectData(options);
|
||||||
|
|
||||||
|
fixBabelConfigurationIfNeeded(storybookWebpackConfig, projectData);
|
||||||
|
|
||||||
const builderOptions: NormalizedWebpackExecutorOptions = {
|
const builderOptions: NormalizedWebpackExecutorOptions = {
|
||||||
...options,
|
...options,
|
||||||
root: options.configDir,
|
root: projectData.workspaceRoot,
|
||||||
// These are blank because root is the absolute path to .storybook folder
|
projectRoot: projectData.projectRoot,
|
||||||
projectRoot: '',
|
sourceRoot: projectData.sourceRoot,
|
||||||
sourceRoot: '',
|
|
||||||
fileReplacements: [],
|
fileReplacements: [],
|
||||||
sourceMap: true,
|
sourceMap: true,
|
||||||
styles: options.styles ?? [],
|
styles: options.styles ?? [],
|
||||||
|
|||||||
@ -849,12 +849,12 @@ describe('app', () => {
|
|||||||
).toBeUndefined();
|
).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('--skipWorkspaceJson', () => {
|
describe('--skipNxJson', () => {
|
||||||
it('should update workspace with defaults when --skipprojectsConfigurations=false', async () => {
|
it('should update workspace with defaults when --skipprojectsConfigurations=false', async () => {
|
||||||
await applicationGenerator(appTree, {
|
await applicationGenerator(appTree, {
|
||||||
...schema,
|
...schema,
|
||||||
style: 'styled-components',
|
style: 'styled-components',
|
||||||
skipWorkspaceJson: false,
|
skipNxJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const nxJson = readNxJson(appTree);
|
const nxJson = readNxJson(appTree);
|
||||||
|
|||||||
@ -39,6 +39,7 @@ import { installCommonDependencies } from './lib/install-common-dependencies';
|
|||||||
import { extractTsConfigBase } from '../../utils/create-ts-config';
|
import { extractTsConfigBase } from '../../utils/create-ts-config';
|
||||||
import { addSwcDependencies } from '@nx/js/src/utils/swc/add-swc-dependencies';
|
import { addSwcDependencies } from '@nx/js/src/utils/swc/add-swc-dependencies';
|
||||||
import * as chalk from 'chalk';
|
import * as chalk from 'chalk';
|
||||||
|
import { showPossibleWarnings } from './lib/show-possible-warnings';
|
||||||
|
|
||||||
async function addLinting(host: Tree, options: NormalizedSchema) {
|
async function addLinting(host: Tree, options: NormalizedSchema) {
|
||||||
const tasks: GeneratorCallback[] = [];
|
const tasks: GeneratorCallback[] = [];
|
||||||
@ -73,12 +74,7 @@ async function addLinting(host: Tree, options: NormalizedSchema) {
|
|||||||
const installTask = await addDependenciesToPackageJson(
|
const installTask = await addDependenciesToPackageJson(
|
||||||
host,
|
host,
|
||||||
extraEslintDependencies.dependencies,
|
extraEslintDependencies.dependencies,
|
||||||
{
|
extraEslintDependencies.devDependencies
|
||||||
...extraEslintDependencies.devDependencies,
|
|
||||||
...(options.compiler === 'swc'
|
|
||||||
? { 'swc-loader': swcLoaderVersion }
|
|
||||||
: {}),
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
const addSwcTask = addSwcDependencies(host);
|
const addSwcTask = addSwcDependencies(host);
|
||||||
tasks.push(installTask, addSwcTask);
|
tasks.push(installTask, addSwcTask);
|
||||||
@ -94,11 +90,11 @@ export async function applicationGenerator(
|
|||||||
const tasks = [];
|
const tasks = [];
|
||||||
|
|
||||||
const options = normalizeOptions(host, schema);
|
const options = normalizeOptions(host, schema);
|
||||||
|
showPossibleWarnings(host, options);
|
||||||
|
|
||||||
const initTask = await reactInitGenerator(host, {
|
const initTask = await reactInitGenerator(host, {
|
||||||
...options,
|
...options,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
skipBabelConfig: options.bundler === 'vite',
|
|
||||||
skipHelperLibs: options.bundler === 'vite',
|
skipHelperLibs: options.bundler === 'vite',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
import { addDependenciesToPackageJson, Tree } from '@nx/devkit';
|
import { addDependenciesToPackageJson, Tree } from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
|
babelPresetReactVersion,
|
||||||
lessVersion,
|
lessVersion,
|
||||||
sassVersion,
|
sassVersion,
|
||||||
stylusVersion,
|
stylusVersion,
|
||||||
|
swcLoaderVersion,
|
||||||
} from '../../../utils/versions';
|
} from '../../../utils/versions';
|
||||||
import { NormalizedSchema } from '../schema';
|
import { NormalizedSchema } from '../schema';
|
||||||
|
|
||||||
@ -10,26 +12,33 @@ export function installCommonDependencies(
|
|||||||
host: Tree,
|
host: Tree,
|
||||||
options: NormalizedSchema
|
options: NormalizedSchema
|
||||||
) {
|
) {
|
||||||
let devDependencies = null;
|
const devDependencies: Record<string, string> = {};
|
||||||
|
|
||||||
// Vite requires style preprocessors to be installed manually.
|
// Vite requires style preprocessors to be installed manually.
|
||||||
// `@nx/webpack` installs them automatically for now.
|
// `@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') {
|
if (options.bundler === 'vite' || options.unitTestRunner === 'vitest') {
|
||||||
switch (options.style) {
|
switch (options.style) {
|
||||||
case 'scss':
|
case 'scss':
|
||||||
devDependencies = { sass: sassVersion };
|
devDependencies['sass'] = sassVersion;
|
||||||
break;
|
break;
|
||||||
case 'less':
|
case 'less':
|
||||||
devDependencies = { less: lessVersion };
|
devDependencies['less'] = lessVersion;
|
||||||
break;
|
break;
|
||||||
case 'styl': // @TODO(17): deprecated, going to be removed in Nx 17
|
case 'styl': // @TODO(17): deprecated, going to be removed in Nx 17
|
||||||
devDependencies = { stylus: stylusVersion };
|
devDependencies['stylus'] = stylusVersion;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return devDependencies
|
if (options.bundler === 'webpack') {
|
||||||
? addDependenciesToPackageJson(host, {}, devDependencies)
|
if (options.compiler === 'swc') {
|
||||||
: function noop() {};
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { readNxJson, Tree, updateNxJson } from '@nx/devkit';
|
|||||||
import { NormalizedSchema } from '../schema';
|
import { NormalizedSchema } from '../schema';
|
||||||
|
|
||||||
export function setDefaults(host: Tree, options: NormalizedSchema) {
|
export function setDefaults(host: Tree, options: NormalizedSchema) {
|
||||||
if (options.skipWorkspaceJson) {
|
if (options.skipNxJson) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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<Schema>
|
||||||
|
) {
|
||||||
|
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.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -14,7 +14,7 @@ export interface Schema {
|
|||||||
pascalCaseFiles?: boolean;
|
pascalCaseFiles?: boolean;
|
||||||
classComponent?: boolean;
|
classComponent?: boolean;
|
||||||
routing?: boolean;
|
routing?: boolean;
|
||||||
skipWorkspaceJson?: boolean;
|
skipNxJson?: boolean;
|
||||||
js?: boolean;
|
js?: boolean;
|
||||||
globalCss?: boolean;
|
globalCss?: boolean;
|
||||||
strict?: boolean;
|
strict?: boolean;
|
||||||
|
|||||||
@ -98,8 +98,8 @@
|
|||||||
"default": false,
|
"default": false,
|
||||||
"x-priority": "internal"
|
"x-priority": "internal"
|
||||||
},
|
},
|
||||||
"skipWorkspaceJson": {
|
"skipNxJson": {
|
||||||
"description": "Skip updating `workspace.json` with default options based on values provided to this app (e.g. babel, style).",
|
"description": "Skip updating `nx.json` with default options based on values provided to this app.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": false,
|
||||||
"x-priority": "internal"
|
"x-priority": "internal"
|
||||||
|
|||||||
@ -15,7 +15,7 @@ export interface Schema {
|
|||||||
remotes?: string[];
|
remotes?: string[];
|
||||||
setParserOptionsProject?: boolean;
|
setParserOptionsProject?: boolean;
|
||||||
skipFormat?: boolean;
|
skipFormat?: boolean;
|
||||||
skipWorkspaceJson?: boolean;
|
skipNxJson?: boolean;
|
||||||
ssr?: boolean;
|
ssr?: boolean;
|
||||||
strict?: boolean;
|
strict?: boolean;
|
||||||
style: SupportedStyles;
|
style: SupportedStyles;
|
||||||
|
|||||||
@ -79,7 +79,7 @@
|
|||||||
"default": false,
|
"default": false,
|
||||||
"x-priority": "internal"
|
"x-priority": "internal"
|
||||||
},
|
},
|
||||||
"skipWorkspaceJson": {
|
"skipNxJson": {
|
||||||
"description": "Skip updating workspace.json with default options based on values provided to this app (e.g. babel, style).",
|
"description": "Skip updating workspace.json with default options based on values provided to this app (e.g. babel, style).",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": false,
|
||||||
|
|||||||
@ -30,9 +30,4 @@ describe('init', () => {
|
|||||||
await reactInitGenerator(tree, { ...schema, unitTestRunner: 'none' });
|
await reactInitGenerator(tree, { ...schema, unitTestRunner: 'none' });
|
||||||
expect(tree.exists('jest.config.js')).toEqual(false);
|
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);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -8,7 +8,6 @@ import {
|
|||||||
runTasksInSerial,
|
runTasksInSerial,
|
||||||
Tree,
|
Tree,
|
||||||
updateNxJson,
|
updateNxJson,
|
||||||
writeJson,
|
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
|
|
||||||
import { initGenerator as jsInitGenerator } from '@nx/js';
|
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) {
|
export async function reactInitGenerator(host: Tree, schema: InitSchema) {
|
||||||
const tasks: GeneratorCallback[] = [];
|
const tasks: GeneratorCallback[] = [];
|
||||||
|
|
||||||
@ -106,21 +86,6 @@ export async function reactInitGenerator(host: Tree, schema: InitSchema) {
|
|||||||
tasks.push(cypressTask);
|
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) {
|
if (!schema.skipPackageJson) {
|
||||||
const installTask = updateDependencies(host, schema);
|
const installTask = updateDependencies(host, schema);
|
||||||
tasks.push(installTask);
|
tasks.push(installTask);
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
export interface InitSchema {
|
export interface InitSchema {
|
||||||
unitTestRunner?: 'jest' | 'vitest' | 'none';
|
unitTestRunner?: 'jest' | 'vitest' | 'none';
|
||||||
e2eTestRunner?: 'cypress' | 'none';
|
e2eTestRunner?: 'cypress' | 'none';
|
||||||
skipBabelConfig?: boolean;
|
|
||||||
skipFormat?: boolean;
|
skipFormat?: boolean;
|
||||||
skipPackageJson?: boolean;
|
skipPackageJson?: boolean;
|
||||||
skipHelperLibs?: boolean;
|
skipHelperLibs?: boolean;
|
||||||
|
|||||||
@ -28,11 +28,6 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
"skipBabelConfig": {
|
|
||||||
"description": "Do not generate a root babel.config.json (if babel is not needed).",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"skipHelperLibs": {
|
"skipHelperLibs": {
|
||||||
"description": "Do not install tslib.",
|
"description": "Do not install tslib.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
|
|||||||
@ -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"<% } %>
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -5,6 +5,7 @@ import {
|
|||||||
names,
|
names,
|
||||||
offsetFromRoot,
|
offsetFromRoot,
|
||||||
toJS,
|
toJS,
|
||||||
|
writeJson,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { getRelativePathToRootTsConfig } from '@nx/js';
|
import { getRelativePathToRootTsConfig } from '@nx/js';
|
||||||
|
|
||||||
@ -38,10 +39,33 @@ export function createFiles(host: Tree, options: NormalizedSchema) {
|
|||||||
options.projectRoot,
|
options.projectRoot,
|
||||||
substitutions
|
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) {
|
if (!options.publishable && !options.buildable) {
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import {
|
|||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { addSwcDependencies } from '@nx/js/src/utils/swc/add-swc-dependencies';
|
import { addSwcDependencies } from '@nx/js/src/utils/swc/add-swc-dependencies';
|
||||||
import {
|
import {
|
||||||
|
babelPresetReactVersion,
|
||||||
lessVersion,
|
lessVersion,
|
||||||
reactDomVersion,
|
reactDomVersion,
|
||||||
reactVersion,
|
reactVersion,
|
||||||
@ -50,6 +51,14 @@ export function installCommonDependencies(
|
|||||||
|
|
||||||
if (options.compiler === 'swc') {
|
if (options.compiler === 'swc') {
|
||||||
tasks.push(addSwcDependencies(host));
|
tasks.push(addSwcDependencies(host));
|
||||||
|
} else if (options.compiler === 'babel') {
|
||||||
|
tasks.push(
|
||||||
|
addDependenciesToPackageJson(
|
||||||
|
host,
|
||||||
|
{},
|
||||||
|
{ '@babel/preset-react': babelPresetReactVersion }
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return runTasksInSerial(...tasks);
|
return runTasksInSerial(...tasks);
|
||||||
|
|||||||
@ -47,7 +47,6 @@ describe('lib', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('not nested', () => {
|
|
||||||
it('should update project configuration', async () => {
|
it('should update project configuration', async () => {
|
||||||
await libraryGenerator(tree, defaultSchema);
|
await libraryGenerator(tree, defaultSchema);
|
||||||
const project = readProjectConfiguration(tree, 'my-lib');
|
const project = readProjectConfiguration(tree, 'my-lib');
|
||||||
@ -69,10 +68,7 @@ describe('lib', () => {
|
|||||||
unitTestRunner: 'vitest',
|
unitTestRunner: 'vitest',
|
||||||
});
|
});
|
||||||
const tsconfigApp = readJson(tree, 'libs/my-lib/tsconfig.lib.json');
|
const tsconfigApp = readJson(tree, 'libs/my-lib/tsconfig.lib.json');
|
||||||
expect(tsconfigApp.compilerOptions.types).toEqual([
|
expect(tsconfigApp.compilerOptions.types).toEqual(['node', 'vite/client']);
|
||||||
'node',
|
|
||||||
'vite/client',
|
|
||||||
]);
|
|
||||||
const tsconfigSpec = readJson(tree, 'libs/my-lib/tsconfig.spec.json');
|
const tsconfigSpec = readJson(tree, 'libs/my-lib/tsconfig.spec.json');
|
||||||
expect(tsconfigSpec.compilerOptions.types).toEqual([
|
expect(tsconfigSpec.compilerOptions.types).toEqual([
|
||||||
'vitest/globals',
|
'vitest/globals',
|
||||||
@ -239,6 +235,17 @@ describe('lib', () => {
|
|||||||
"['babel-jest', { presets: ['@nx/react/babel'] }]"
|
"['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',
|
||||||
|
});
|
||||||
|
|
||||||
|
const packageJson = readJson(tree, 'package.json');
|
||||||
|
expect(packageJson.devDependencies['@babel/preset-react']).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('nested', () => {
|
describe('nested', () => {
|
||||||
|
|||||||
@ -43,7 +43,6 @@ export async function libraryGenerator(host: Tree, schema: Schema) {
|
|||||||
...options,
|
...options,
|
||||||
e2eTestRunner: 'none',
|
e2eTestRunner: 'none',
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
skipBabelConfig: options.bundler === 'vite' || options.compiler === 'swc',
|
|
||||||
skipHelperLibs: options.bundler === 'vite',
|
skipHelperLibs: options.bundler === 'vite',
|
||||||
});
|
});
|
||||||
tasks.push(initTask);
|
tasks.push(initTask);
|
||||||
|
|||||||
@ -17,7 +17,7 @@ export interface Schema {
|
|||||||
routing?: boolean;
|
routing?: boolean;
|
||||||
setParserOptionsProject?: boolean;
|
setParserOptionsProject?: boolean;
|
||||||
skipFormat: boolean;
|
skipFormat: boolean;
|
||||||
skipWorkspaceJson?: boolean;
|
skipNxJson?: boolean;
|
||||||
ssr?: boolean;
|
ssr?: boolean;
|
||||||
strict?: boolean;
|
strict?: boolean;
|
||||||
style: SupportedStyles;
|
style: SupportedStyles;
|
||||||
|
|||||||
@ -84,7 +84,7 @@
|
|||||||
"default": false,
|
"default": false,
|
||||||
"x-priority": "internal"
|
"x-priority": "internal"
|
||||||
},
|
},
|
||||||
"skipWorkspaceJson": {
|
"skipNxJson": {
|
||||||
"description": "Skip updating workspace.json with default options based on values provided to this app (e.g. babel, style).",
|
"description": "Skip updating workspace.json with default options based on values provided to this app (e.g. babel, style).",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": false,
|
||||||
|
|||||||
@ -11,23 +11,6 @@ describe('rollupInitGenerator', () => {
|
|||||||
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support babel', async () => {
|
|
||||||
updateJson<NxJsonConfiguration>(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<NxJsonConfiguration>(tree, 'nx.json')
|
|
||||||
.namedInputs.sharedGlobals;
|
|
||||||
expect(sharedGlobals).toContain('{workspaceRoot}/exiting-file.json');
|
|
||||||
expect(sharedGlobals).toContain('{workspaceRoot}/babel.config.json');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should support swc', async () => {
|
it('should support swc', async () => {
|
||||||
await rollupInitGenerator(tree, { compiler: 'swc' });
|
await rollupInitGenerator(tree, { compiler: 'swc' });
|
||||||
|
|
||||||
|
|||||||
@ -17,10 +17,6 @@ import { addBabelInputs } from '@nx/js/src/utils/add-babel-inputs';
|
|||||||
export async function rollupInitGenerator(tree: Tree, schema: Schema) {
|
export async function rollupInitGenerator(tree: Tree, schema: Schema) {
|
||||||
let task: GeneratorCallback;
|
let task: GeneratorCallback;
|
||||||
|
|
||||||
if (schema.compiler === 'babel') {
|
|
||||||
addBabelInputs(tree);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (schema.compiler === 'swc') {
|
if (schema.compiler === 'swc') {
|
||||||
task = addDependenciesToPackageJson(
|
task = addDependenciesToPackageJson(
|
||||||
tree,
|
tree,
|
||||||
|
|||||||
@ -184,8 +184,6 @@ export async function applicationGenerator(host: Tree, schema: Schema) {
|
|||||||
const webTask = await webInitGenerator(host, {
|
const webTask = await webInitGenerator(host, {
|
||||||
...options,
|
...options,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
// Vite does not use babel by default
|
|
||||||
skipBabelConfig: options.bundler === 'vite',
|
|
||||||
});
|
});
|
||||||
tasks.push(webTask);
|
tasks.push(webTask);
|
||||||
|
|
||||||
|
|||||||
@ -46,8 +46,8 @@
|
|||||||
"compiler": {
|
"compiler": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The compiler to use",
|
"description": "The compiler to use",
|
||||||
"enum": ["babel", "swc"],
|
"enum": ["swc", "babel"],
|
||||||
"default": "babel",
|
"default": "swc",
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"bundler": {
|
"bundler": {
|
||||||
|
|||||||
@ -8,8 +8,6 @@ import {
|
|||||||
runTasksInSerial,
|
runTasksInSerial,
|
||||||
Tree,
|
Tree,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
|
|
||||||
import { addBabelInputs } from '@nx/js/src/utils/add-babel-inputs';
|
|
||||||
import { initGenerator as jsInitGenerator } from '@nx/js';
|
import { initGenerator as jsInitGenerator } from '@nx/js';
|
||||||
import {
|
import {
|
||||||
nxVersion,
|
nxVersion,
|
||||||
@ -65,7 +63,6 @@ export async function webInitGenerator(tree: Tree, schema: Schema) {
|
|||||||
const installTask = updateDependencies(tree, schema);
|
const installTask = updateDependencies(tree, schema);
|
||||||
tasks.push(installTask);
|
tasks.push(installTask);
|
||||||
}
|
}
|
||||||
addBabelInputs(tree);
|
|
||||||
|
|
||||||
if (!schema.skipFormat) {
|
if (!schema.skipFormat) {
|
||||||
await formatFiles(tree);
|
await formatFiles(tree);
|
||||||
|
|||||||
1
packages/web/src/generators/init/schema.d.ts
vendored
1
packages/web/src/generators/init/schema.d.ts
vendored
@ -4,5 +4,4 @@ export interface Schema {
|
|||||||
e2eTestRunner?: 'cypress' | 'none';
|
e2eTestRunner?: 'cypress' | 'none';
|
||||||
skipFormat?: boolean;
|
skipFormat?: boolean;
|
||||||
skipPackageJson?: boolean;
|
skipPackageJson?: boolean;
|
||||||
skipBabelConfig?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,11 +34,6 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": false,
|
||||||
"x-priority": "internal"
|
"x-priority": "internal"
|
||||||
},
|
|
||||||
"skipBabelConfig": {
|
|
||||||
"description": "Do not generate a root babel.config.json (if babel is not needed).",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": []
|
"required": []
|
||||||
|
|||||||
@ -70,28 +70,16 @@ export interface WebpackExecutorOptions {
|
|||||||
webpackConfig?: string;
|
webpackConfig?: string;
|
||||||
babelConfig?: string;
|
babelConfig?: string;
|
||||||
babelUpwardRootMode?: boolean;
|
babelUpwardRootMode?: boolean;
|
||||||
// TODO(jack): Also deprecate these in schema.json once we have migration from executor options to webpack.config.js file.
|
|
||||||
/** @deprecated Moved to withWeb options from `@nx/webpack` */
|
|
||||||
baseHref?: string;
|
baseHref?: string;
|
||||||
/** @deprecated Moved to withWeb options from `@nx/webpack` */
|
|
||||||
crossOrigin?: 'none' | 'anonymous' | 'use-credentials';
|
crossOrigin?: 'none' | 'anonymous' | 'use-credentials';
|
||||||
/** @deprecated Moved to withWeb options from `@nx/webpack` */
|
|
||||||
deployUrl?: string;
|
deployUrl?: string;
|
||||||
/** @deprecated Moved to withWeb options from `@nx/webpack` */
|
|
||||||
extractCss?: boolean;
|
extractCss?: boolean;
|
||||||
/** @deprecated Moved to withWeb options from `@nx/webpack` */
|
|
||||||
generateIndexHtml?: boolean;
|
generateIndexHtml?: boolean;
|
||||||
/** @deprecated Moved to withWeb options from `@nx/webpack` */
|
|
||||||
index?: string;
|
index?: string;
|
||||||
/** @deprecated Moved to withWeb options from `@nx/webpack` */
|
|
||||||
postcssConfig?: string;
|
postcssConfig?: string;
|
||||||
/** @deprecated Moved to withWeb options from `@nx/webpack` */
|
|
||||||
scripts?: Array<ExtraEntryPointClass | string>;
|
scripts?: Array<ExtraEntryPointClass | string>;
|
||||||
/** @deprecated Moved to withWeb options from `@nx/webpack` */
|
|
||||||
stylePreprocessorOptions?: any;
|
stylePreprocessorOptions?: any;
|
||||||
/** @deprecated Moved to withWeb options from `@nx/webpack` */
|
|
||||||
styles?: Array<ExtraEntryPointClass | string>;
|
styles?: Array<ExtraEntryPointClass | string>;
|
||||||
/** @deprecated Moved to withWeb options from `@nx/webpack` */
|
|
||||||
subresourceIntegrity?: boolean;
|
subresourceIntegrity?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,23 +10,6 @@ describe('webpackInitGenerator', () => {
|
|||||||
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support babel', async () => {
|
|
||||||
updateJson<NxJsonConfiguration>(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<NxJsonConfiguration>(tree, 'nx.json')
|
|
||||||
.namedInputs.sharedGlobals;
|
|
||||||
expect(sharedGlobals).toContain('{workspaceRoot}/exiting-file.json');
|
|
||||||
expect(sharedGlobals).toContain('{workspaceRoot}/babel.config.json');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should support swc', async () => {
|
it('should support swc', async () => {
|
||||||
await webpackInitGenerator(tree, { compiler: 'swc' });
|
await webpackInitGenerator(tree, { compiler: 'swc' });
|
||||||
|
|
||||||
|
|||||||
@ -22,9 +22,6 @@ import { addBabelInputs } from '@nx/js/src/utils/add-babel-inputs';
|
|||||||
|
|
||||||
export async function webpackInitGenerator(tree: Tree, schema: Schema) {
|
export async function webpackInitGenerator(tree: Tree, schema: Schema) {
|
||||||
const tasks: GeneratorCallback[] = [];
|
const tasks: GeneratorCallback[] = [];
|
||||||
if (schema.compiler === 'babel') {
|
|
||||||
addBabelInputs(tree);
|
|
||||||
}
|
|
||||||
const devDependencies = {
|
const devDependencies = {
|
||||||
'@nx/webpack': nxVersion,
|
'@nx/webpack': nxVersion,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -21,7 +21,7 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["babel", "swc", "tsc"],
|
"enum": ["babel", "swc", "tsc"],
|
||||||
"description": "The compiler to use to build source.",
|
"description": "The compiler to use to build source.",
|
||||||
"default": "babel"
|
"default": "swc"
|
||||||
},
|
},
|
||||||
"main": {
|
"main": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
import type { ProjectConfiguration, Tree } from '@nx/devkit';
|
import type { Tree } from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
convertNxGenerator,
|
convertNxGenerator,
|
||||||
formatFiles,
|
formatFiles,
|
||||||
joinPathFragments,
|
joinPathFragments,
|
||||||
readProjectConfiguration,
|
readProjectConfiguration,
|
||||||
updateProjectConfiguration,
|
updateProjectConfiguration,
|
||||||
|
writeJson,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
|
|
||||||
import { webpackInitGenerator } from '../init/init';
|
import { webpackInitGenerator } from '../init/init';
|
||||||
@ -58,7 +59,7 @@ function addBuildTarget(tree: Tree, options: WebpackProjectGeneratorSchema) {
|
|||||||
const buildOptions: WebpackExecutorOptions = {
|
const buildOptions: WebpackExecutorOptions = {
|
||||||
target: options.target,
|
target: options.target,
|
||||||
outputPath: joinPathFragments('dist', project.root),
|
outputPath: joinPathFragments('dist', project.root),
|
||||||
compiler: options.compiler ?? 'babel',
|
compiler: options.compiler ?? 'swc',
|
||||||
main: options.main ?? joinPathFragments(project.root, 'src/main.ts'),
|
main: options.main ?? joinPathFragments(project.root, 'src/main.ts'),
|
||||||
tsConfig:
|
tsConfig:
|
||||||
options.tsConfig ?? joinPathFragments(project.root, 'tsconfig.app.json'),
|
options.tsConfig ?? joinPathFragments(project.root, 'tsconfig.app.json'),
|
||||||
@ -71,8 +72,11 @@ function addBuildTarget(tree: Tree, options: WebpackProjectGeneratorSchema) {
|
|||||||
|
|
||||||
if (options.babelConfig) {
|
if (options.babelConfig) {
|
||||||
buildOptions.babelConfig = options.babelConfig;
|
buildOptions.babelConfig = options.babelConfig;
|
||||||
} else {
|
} else if (options.compiler === 'babel') {
|
||||||
buildOptions.babelUpwardRootMode = true;
|
// If no babel config file is provided then write a default one, otherwise build will fail.
|
||||||
|
writeJson(tree, joinPathFragments(project.root, '.babelrc'), {
|
||||||
|
presets: ['@nx/js/babel'],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.target === 'web') {
|
if (options.target === 'web') {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user