feat(js): support esbuild and swc bundlers with the new ts solution config setup (#28409)
<!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> <!-- If this is a particularly complex change or feature addition, you can request a dedicated Nx release for this pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate. --> ## Current Behavior <!-- This is the behavior we have today --> ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes # --------- Co-authored-by: Jack Hsu <jack.hsu@gmail.com>
This commit is contained in:
parent
74bdc583b9
commit
db47dc30a5
@ -24,6 +24,8 @@
|
|||||||
"description": "The bundler to use. Choosing 'none' means this library is not buildable.",
|
"description": "The bundler to use. Choosing 'none' means this library is not buildable.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["swc", "tsc", "rollup", "vite", "esbuild", "none"],
|
"enum": ["swc", "tsc", "rollup", "vite", "esbuild", "none"],
|
||||||
|
"default": "tsc",
|
||||||
|
"x-prompt": "Which bundler would you like to use to build the library? Choose 'none' to skip build setup.",
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"linter": {
|
"linter": {
|
||||||
|
|||||||
@ -48,6 +48,7 @@ describe('EsBuild Plugin', () => {
|
|||||||
private: true,
|
private: true,
|
||||||
type: 'commonjs',
|
type: 'commonjs',
|
||||||
main: './index.cjs',
|
main: './index.cjs',
|
||||||
|
typings: './index.d.ts',
|
||||||
dependencies: {},
|
dependencies: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,30 +1,39 @@
|
|||||||
|
import { joinPathFragments, logger, type ExecutorContext } from '@nx/devkit';
|
||||||
|
import { readTsConfig } from '@nx/js';
|
||||||
|
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
|
import * as esbuild from 'esbuild';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import {
|
import * as pc from 'picocolors';
|
||||||
|
import type {
|
||||||
EsBuildExecutorOptions,
|
EsBuildExecutorOptions,
|
||||||
NormalizedEsBuildExecutorOptions,
|
NormalizedEsBuildExecutorOptions,
|
||||||
} from '../schema';
|
} from '../schema';
|
||||||
import { ExecutorContext, joinPathFragments, logger } from '@nx/devkit';
|
|
||||||
import * as pc from 'picocolors';
|
|
||||||
import * as esbuild from 'esbuild';
|
|
||||||
import { readTsConfig } from '@nx/js';
|
|
||||||
|
|
||||||
export function normalizeOptions(
|
export function normalizeOptions(
|
||||||
options: EsBuildExecutorOptions,
|
options: EsBuildExecutorOptions,
|
||||||
context: ExecutorContext
|
context: ExecutorContext
|
||||||
): NormalizedEsBuildExecutorOptions {
|
): NormalizedEsBuildExecutorOptions {
|
||||||
|
const isTsSolutionSetup = isUsingTsSolutionSetup();
|
||||||
|
if (isTsSolutionSetup && options.generatePackageJson) {
|
||||||
|
throw new Error(
|
||||||
|
`Setting 'generatePackageJson: true' is not allowed with the current TypeScript setup. Please update the 'package.json' file at the project root as needed and don't set the 'generatePackageJson' option.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const tsConfig = readTsConfig(options.tsConfig);
|
const tsConfig = readTsConfig(options.tsConfig);
|
||||||
|
|
||||||
// If we're not generating package.json file, then copy it as-is as an asset.
|
// If we're not generating package.json file, then copy it as-is as an asset when not using ts solution setup.
|
||||||
const assets = options.generatePackageJson
|
const assets =
|
||||||
? options.assets
|
options.generatePackageJson || isTsSolutionSetup
|
||||||
: [
|
? options.assets
|
||||||
...options.assets,
|
: [
|
||||||
joinPathFragments(
|
...options.assets,
|
||||||
context.projectGraph.nodes[context.projectName].data.root,
|
joinPathFragments(
|
||||||
'package.json'
|
context.projectGraph.nodes[context.projectName].data.root,
|
||||||
),
|
'package.json'
|
||||||
];
|
),
|
||||||
|
];
|
||||||
|
|
||||||
if (!options.bundle && options.thirdParty) {
|
if (!options.bundle && options.thirdParty) {
|
||||||
logger.info(
|
logger.info(
|
||||||
@ -33,7 +42,7 @@ export function normalizeOptions(
|
|||||||
'bundle:false'
|
'bundle:false'
|
||||||
)} and ${pc.bold(
|
)} and ${pc.bold(
|
||||||
'thirdParty:true'
|
'thirdParty:true'
|
||||||
)}. Your package.json depedencies might not be generated correctly so we added an update ${pc.bold(
|
)}. Your package.json dependencies might not be generated correctly so we added an update ${pc.bold(
|
||||||
'thirdParty:false'
|
'thirdParty:false'
|
||||||
)}`
|
)}`
|
||||||
)
|
)
|
||||||
@ -42,8 +51,6 @@ export function normalizeOptions(
|
|||||||
|
|
||||||
const thirdParty = !options.bundle ? false : options.thirdParty;
|
const thirdParty = !options.bundle ? false : options.thirdParty;
|
||||||
|
|
||||||
const { root: projectRoot } =
|
|
||||||
context.projectsConfigurations.projects[context.projectName];
|
|
||||||
const declarationRootDir = options.declarationRootDir
|
const declarationRootDir = options.declarationRootDir
|
||||||
? path.join(context.root, options.declarationRootDir)
|
? path.join(context.root, options.declarationRootDir)
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
import { ExecutorContext, readJsonFile } from '@nx/devkit';
|
import { ExecutorContext, output, readJsonFile } from '@nx/devkit';
|
||||||
import { assetGlobsToFiles, FileInputOutput } from '../../utils/assets/assets';
|
|
||||||
import { sync as globSync } from 'fast-glob';
|
import { sync as globSync } from 'fast-glob';
|
||||||
import { rmSync } from 'node:fs';
|
import { rmSync } from 'node:fs';
|
||||||
import { dirname, join, relative, resolve, normalize } from 'path';
|
import { dirname, join, normalize, relative, resolve } from 'path';
|
||||||
import { copyAssets } from '../../utils/assets';
|
import { copyAssets } from '../../utils/assets';
|
||||||
|
import { assetGlobsToFiles, FileInputOutput } from '../../utils/assets/assets';
|
||||||
|
import type { DependentBuildableProjectNode } from '../../utils/buildable-libs-utils';
|
||||||
import { checkDependencies } from '../../utils/check-dependencies';
|
import { checkDependencies } from '../../utils/check-dependencies';
|
||||||
import {
|
import {
|
||||||
getHelperDependency,
|
getHelperDependency,
|
||||||
@ -13,16 +14,20 @@ import {
|
|||||||
handleInliningBuild,
|
handleInliningBuild,
|
||||||
isInlineGraphEmpty,
|
isInlineGraphEmpty,
|
||||||
postProcessInlinedDependencies,
|
postProcessInlinedDependencies,
|
||||||
|
type InlineProjectGraph,
|
||||||
} from '../../utils/inline';
|
} from '../../utils/inline';
|
||||||
import { copyPackageJson } from '../../utils/package-json';
|
import {
|
||||||
|
copyPackageJson,
|
||||||
|
type CopyPackageJsonResult,
|
||||||
|
} from '../../utils/package-json';
|
||||||
import {
|
import {
|
||||||
NormalizedSwcExecutorOptions,
|
NormalizedSwcExecutorOptions,
|
||||||
SwcCliOptions,
|
|
||||||
SwcExecutorOptions,
|
SwcExecutorOptions,
|
||||||
} from '../../utils/schema';
|
} from '../../utils/schema';
|
||||||
import { compileSwc, compileSwcWatch } from '../../utils/swc/compile-swc';
|
import { compileSwc, compileSwcWatch } from '../../utils/swc/compile-swc';
|
||||||
import { getSwcrcPath } from '../../utils/swc/get-swcrc-path';
|
import { getSwcrcPath } from '../../utils/swc/get-swcrc-path';
|
||||||
import { generateTmpSwcrc } from '../../utils/swc/inline';
|
import { generateTmpSwcrc } from '../../utils/swc/inline';
|
||||||
|
import { isUsingTsSolutionSetup } from '../../utils/typescript/ts-solution-setup';
|
||||||
|
|
||||||
function normalizeOptions(
|
function normalizeOptions(
|
||||||
options: SwcExecutorOptions,
|
options: SwcExecutorOptions,
|
||||||
@ -30,6 +35,25 @@ function normalizeOptions(
|
|||||||
sourceRoot: string,
|
sourceRoot: string,
|
||||||
projectRoot: string
|
projectRoot: string
|
||||||
): NormalizedSwcExecutorOptions {
|
): NormalizedSwcExecutorOptions {
|
||||||
|
const isTsSolutionSetup = isUsingTsSolutionSetup();
|
||||||
|
if (isTsSolutionSetup) {
|
||||||
|
if (options.generateLockfile) {
|
||||||
|
throw new Error(
|
||||||
|
`Setting 'generateLockfile: true' is not supported with the current TypeScript setup. Unset the 'generateLockfile' option and try again.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (options.generateExportsField) {
|
||||||
|
throw new Error(
|
||||||
|
`Setting 'generateExportsField: true' is not supported with the current TypeScript setup. Set 'exports' field in the 'package.json' file at the project root and unset the 'generateExportsField' option.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (options.additionalEntryPoints?.length) {
|
||||||
|
throw new Error(
|
||||||
|
`Setting 'additionalEntryPoints' is not supported with the current TypeScript setup. Set additional entry points in the 'package.json' file at the project root and unset the 'additionalEntryPoints' option.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const outputPath = join(root, options.outputPath);
|
const outputPath = join(root, options.outputPath);
|
||||||
|
|
||||||
if (options.skipTypeCheck == null) {
|
if (options.skipTypeCheck == null) {
|
||||||
@ -87,6 +111,7 @@ function normalizeOptions(
|
|||||||
tsConfig: join(root, options.tsConfig),
|
tsConfig: join(root, options.tsConfig),
|
||||||
swcCliOptions,
|
swcCliOptions,
|
||||||
tmpSwcrcPath,
|
tmpSwcrcPath,
|
||||||
|
isTsSolutionSetup: isTsSolutionSetup,
|
||||||
} as NormalizedSwcExecutorOptions;
|
} as NormalizedSwcExecutorOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,56 +122,61 @@ export async function* swcExecutor(
|
|||||||
const { sourceRoot, root } =
|
const { sourceRoot, root } =
|
||||||
context.projectsConfigurations.projects[context.projectName];
|
context.projectsConfigurations.projects[context.projectName];
|
||||||
const options = normalizeOptions(_options, context.root, sourceRoot, root);
|
const options = normalizeOptions(_options, context.root, sourceRoot, root);
|
||||||
const { tmpTsConfig, dependencies } = checkDependencies(
|
|
||||||
context,
|
|
||||||
options.tsConfig
|
|
||||||
);
|
|
||||||
|
|
||||||
if (tmpTsConfig) {
|
let swcHelperDependency: DependentBuildableProjectNode;
|
||||||
options.tsConfig = tmpTsConfig;
|
let inlineProjectGraph: InlineProjectGraph;
|
||||||
}
|
if (!options.isTsSolutionSetup) {
|
||||||
|
const { tmpTsConfig, dependencies } = checkDependencies(
|
||||||
|
context,
|
||||||
|
options.tsConfig
|
||||||
|
);
|
||||||
|
|
||||||
const swcHelperDependency = getHelperDependency(
|
if (tmpTsConfig) {
|
||||||
HelperDependency.swc,
|
options.tsConfig = tmpTsConfig;
|
||||||
options.swcCliOptions.swcrcPath,
|
|
||||||
dependencies,
|
|
||||||
context.projectGraph
|
|
||||||
);
|
|
||||||
|
|
||||||
if (swcHelperDependency) {
|
|
||||||
dependencies.push(swcHelperDependency);
|
|
||||||
}
|
|
||||||
|
|
||||||
const inlineProjectGraph = handleInliningBuild(
|
|
||||||
context,
|
|
||||||
options,
|
|
||||||
options.tsConfig
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!isInlineGraphEmpty(inlineProjectGraph)) {
|
|
||||||
if (options.stripLeadingPaths) {
|
|
||||||
throw new Error(`Cannot use --strip-leading-paths with inlining.`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
options.projectRoot = '.'; // set to root of workspace to include other libs for type check
|
swcHelperDependency = getHelperDependency(
|
||||||
|
HelperDependency.swc,
|
||||||
// remap paths for SWC compilation
|
|
||||||
options.inline = true;
|
|
||||||
options.swcCliOptions.swcCwd = '.';
|
|
||||||
options.swcCliOptions.srcPath = options.swcCliOptions.swcCwd;
|
|
||||||
options.swcCliOptions.destPath = join(
|
|
||||||
options.swcCliOptions.destPath.split(normalize('../')).at(-1),
|
|
||||||
options.swcCliOptions.srcPath
|
|
||||||
);
|
|
||||||
|
|
||||||
// tmp swcrc with dependencies to exclude
|
|
||||||
// - buildable libraries
|
|
||||||
// - other libraries that are not dependent on the current project
|
|
||||||
options.swcCliOptions.swcrcPath = generateTmpSwcrc(
|
|
||||||
inlineProjectGraph,
|
|
||||||
options.swcCliOptions.swcrcPath,
|
options.swcCliOptions.swcrcPath,
|
||||||
options.tmpSwcrcPath
|
dependencies,
|
||||||
|
context.projectGraph
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (swcHelperDependency) {
|
||||||
|
dependencies.push(swcHelperDependency);
|
||||||
|
}
|
||||||
|
|
||||||
|
inlineProjectGraph = handleInliningBuild(
|
||||||
|
context,
|
||||||
|
options,
|
||||||
|
options.tsConfig
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!isInlineGraphEmpty(inlineProjectGraph)) {
|
||||||
|
if (options.stripLeadingPaths) {
|
||||||
|
throw new Error(`Cannot use --strip-leading-paths with inlining.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
options.projectRoot = '.'; // set to root of workspace to include other libs for type check
|
||||||
|
|
||||||
|
// remap paths for SWC compilation
|
||||||
|
options.inline = true;
|
||||||
|
options.swcCliOptions.swcCwd = '.';
|
||||||
|
options.swcCliOptions.srcPath = options.swcCliOptions.swcCwd;
|
||||||
|
options.swcCliOptions.destPath = join(
|
||||||
|
options.swcCliOptions.destPath.split(normalize('../')).at(-1),
|
||||||
|
options.swcCliOptions.srcPath
|
||||||
|
);
|
||||||
|
|
||||||
|
// tmp swcrc with dependencies to exclude
|
||||||
|
// - buildable libraries
|
||||||
|
// - other libraries that are not dependent on the current project
|
||||||
|
options.swcCliOptions.swcrcPath = generateTmpSwcrc(
|
||||||
|
inlineProjectGraph,
|
||||||
|
options.swcCliOptions.swcrcPath,
|
||||||
|
options.tmpSwcrcPath
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function determineModuleFormatFromSwcrc(
|
function determineModuleFormatFromSwcrc(
|
||||||
@ -163,16 +193,19 @@ export async function* swcExecutor(
|
|||||||
|
|
||||||
return yield* compileSwcWatch(context, options, async () => {
|
return yield* compileSwcWatch(context, options, async () => {
|
||||||
const assetResult = await copyAssets(options, context);
|
const assetResult = await copyAssets(options, context);
|
||||||
const packageJsonResult = await copyPackageJson(
|
let packageJsonResult: CopyPackageJsonResult;
|
||||||
{
|
if (!options.isTsSolutionSetup) {
|
||||||
...options,
|
packageJsonResult = await copyPackageJson(
|
||||||
additionalEntryPoints: createEntryPoints(options, context),
|
{
|
||||||
format: [
|
...options,
|
||||||
determineModuleFormatFromSwcrc(options.swcCliOptions.swcrcPath),
|
additionalEntryPoints: createEntryPoints(options, context),
|
||||||
],
|
format: [
|
||||||
},
|
determineModuleFormatFromSwcrc(options.swcCliOptions.swcrcPath),
|
||||||
context
|
],
|
||||||
);
|
},
|
||||||
|
context
|
||||||
|
);
|
||||||
|
}
|
||||||
removeTmpSwcrc(options.swcCliOptions.swcrcPath);
|
removeTmpSwcrc(options.swcCliOptions.swcrcPath);
|
||||||
disposeFn = () => {
|
disposeFn = () => {
|
||||||
assetResult?.stop();
|
assetResult?.stop();
|
||||||
@ -182,23 +215,25 @@ export async function* swcExecutor(
|
|||||||
} else {
|
} else {
|
||||||
return yield compileSwc(context, options, async () => {
|
return yield compileSwc(context, options, async () => {
|
||||||
await copyAssets(options, context);
|
await copyAssets(options, context);
|
||||||
await copyPackageJson(
|
if (!options.isTsSolutionSetup) {
|
||||||
{
|
await copyPackageJson(
|
||||||
...options,
|
{
|
||||||
additionalEntryPoints: createEntryPoints(options, context),
|
...options,
|
||||||
format: [
|
additionalEntryPoints: createEntryPoints(options, context),
|
||||||
determineModuleFormatFromSwcrc(options.swcCliOptions.swcrcPath),
|
format: [
|
||||||
],
|
determineModuleFormatFromSwcrc(options.swcCliOptions.swcrcPath),
|
||||||
extraDependencies: swcHelperDependency ? [swcHelperDependency] : [],
|
],
|
||||||
},
|
extraDependencies: swcHelperDependency ? [swcHelperDependency] : [],
|
||||||
context
|
},
|
||||||
);
|
context
|
||||||
|
);
|
||||||
|
postProcessInlinedDependencies(
|
||||||
|
options.outputPath,
|
||||||
|
options.originalProjectRoot,
|
||||||
|
inlineProjectGraph
|
||||||
|
);
|
||||||
|
}
|
||||||
removeTmpSwcrc(options.swcCliOptions.swcrcPath);
|
removeTmpSwcrc(options.swcCliOptions.swcrcPath);
|
||||||
postProcessInlinedDependencies(
|
|
||||||
options.outputPath,
|
|
||||||
options.originalProjectRoot,
|
|
||||||
inlineProjectGraph
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1561,6 +1561,7 @@ describe('lib', () => {
|
|||||||
"name": "@proj/my-lib",
|
"name": "@proj/my-lib",
|
||||||
"nx": {
|
"nx": {
|
||||||
"name": "my-lib",
|
"name": "my-lib",
|
||||||
|
"sourceRoot": "my-lib/src",
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
|
|||||||
@ -266,31 +266,6 @@ async function configureProject(
|
|||||||
updateNxJson(tree, nxJson);
|
updateNxJson(tree, nxJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.useProjectJson) {
|
|
||||||
// we create a cleaner project configuration for the package.json file
|
|
||||||
const projectConfiguration: ProjectConfiguration = {
|
|
||||||
root: options.projectRoot,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (options.name !== options.importPath) {
|
|
||||||
// if the name is different than the package.json name, we need to set
|
|
||||||
// the proper name in the configuration
|
|
||||||
projectConfiguration.name = options.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.parsedTags?.length) {
|
|
||||||
projectConfiguration.tags = options.parsedTags;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.publishable) {
|
|
||||||
await addProjectToNxReleaseConfig(tree, options, projectConfiguration);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateProjectConfiguration(tree, options.name, projectConfiguration);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const projectConfiguration: ProjectConfiguration = {
|
const projectConfiguration: ProjectConfiguration = {
|
||||||
root: options.projectRoot,
|
root: options.projectRoot,
|
||||||
sourceRoot: joinPathFragments(options.projectRoot, 'src'),
|
sourceRoot: joinPathFragments(options.projectRoot, 'src'),
|
||||||
@ -300,34 +275,42 @@ async function configureProject(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (
|
if (
|
||||||
options.bundler &&
|
options.config !== 'npm-scripts' &&
|
||||||
options.bundler !== 'none' &&
|
(options.bundler === 'swc' ||
|
||||||
options.config !== 'npm-scripts'
|
options.bundler === 'esbuild' ||
|
||||||
|
(!options.isUsingTsSolutionConfig && options.bundler === 'tsc'))
|
||||||
) {
|
) {
|
||||||
if (options.bundler !== 'rollup') {
|
const outputPath = getOutputPath(options);
|
||||||
const outputPath = getOutputPath(options);
|
const executor = getBuildExecutor(options.bundler);
|
||||||
const executor = getBuildExecutor(options.bundler);
|
addBuildTargetDefaults(tree, executor);
|
||||||
addBuildTargetDefaults(tree, executor);
|
|
||||||
|
|
||||||
projectConfiguration.targets.build = {
|
projectConfiguration.targets.build = {
|
||||||
executor,
|
executor,
|
||||||
outputs: ['{options.outputPath}'],
|
outputs: ['{options.outputPath}'],
|
||||||
options: {
|
options: {
|
||||||
outputPath,
|
outputPath,
|
||||||
main:
|
main: `${options.projectRoot}/src/index` + (options.js ? '.js' : '.ts'),
|
||||||
`${options.projectRoot}/src/index` + (options.js ? '.js' : '.ts'),
|
tsConfig: `${options.projectRoot}/tsconfig.lib.json`,
|
||||||
tsConfig: `${options.projectRoot}/tsconfig.lib.json`,
|
},
|
||||||
assets: [],
|
};
|
||||||
},
|
|
||||||
};
|
if (options.bundler === 'esbuild') {
|
||||||
|
projectConfiguration.targets.build.options.format = ['cjs'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.bundler === 'swc' && options.skipTypeCheck) {
|
||||||
|
projectConfiguration.targets.build.options.skipTypeCheck = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.isUsingTsSolutionConfig) {
|
||||||
|
if (options.bundler === 'esbuild') {
|
||||||
|
projectConfiguration.targets.build.options.declarationRootDir = `${options.projectRoot}/src`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
projectConfiguration.targets.build.options.assets = [];
|
||||||
|
|
||||||
if (options.bundler === 'esbuild') {
|
if (options.bundler === 'esbuild') {
|
||||||
projectConfiguration.targets.build.options.generatePackageJson = true;
|
projectConfiguration.targets.build.options.generatePackageJson = true;
|
||||||
projectConfiguration.targets.build.options.format = ['cjs'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.bundler === 'swc' && options.skipTypeCheck) {
|
|
||||||
projectConfiguration.targets.build.options.skipTypeCheck = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.minimal) {
|
if (!options.minimal) {
|
||||||
@ -337,8 +320,10 @@ async function configureProject(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (options.publishable) {
|
if (options.publishable) {
|
||||||
|
if (!options.isUsingTsSolutionConfig) {
|
||||||
const packageRoot = joinPathFragments(
|
const packageRoot = joinPathFragments(
|
||||||
defaultOutputDirectory,
|
defaultOutputDirectory,
|
||||||
'{projectRoot}'
|
'{projectRoot}'
|
||||||
@ -361,12 +346,22 @@ async function configureProject(
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
await addProjectToNxReleaseConfig(tree, options, projectConfiguration);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await addProjectToNxReleaseConfig(tree, options, projectConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.config === 'workspace' || options.config === 'project') {
|
if (!options.useProjectJson) {
|
||||||
|
// we want the package.json as clean as possible, with the bare minimum
|
||||||
|
if (!projectConfiguration.tags?.length) {
|
||||||
|
delete projectConfiguration.tags;
|
||||||
|
}
|
||||||
|
// automatically inferred as `library`
|
||||||
|
delete projectConfiguration.projectType;
|
||||||
|
|
||||||
|
// empty targets are cleaned up automatically by `updateProjectConfiguration`
|
||||||
|
updateProjectConfiguration(tree, options.name, projectConfiguration);
|
||||||
|
} else if (options.config === 'workspace' || options.config === 'project') {
|
||||||
addProjectConfiguration(tree, options.name, projectConfiguration);
|
addProjectConfiguration(tree, options.name, projectConfiguration);
|
||||||
} else {
|
} else {
|
||||||
addProjectConfiguration(tree, options.name, {
|
addProjectConfiguration(tree, options.name, {
|
||||||
@ -716,30 +711,6 @@ async function normalizeOptions(
|
|||||||
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(tree);
|
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(tree);
|
||||||
|
|
||||||
if (isUsingTsSolutionConfig) {
|
if (isUsingTsSolutionConfig) {
|
||||||
if (options.bundler === 'esbuild' || options.bundler === 'swc') {
|
|
||||||
throw new Error(
|
|
||||||
`Cannot use the "${options.bundler}" bundler when using the @nx/js/typescript plugin.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.bundler === undefined && options.compiler === undefined) {
|
|
||||||
options.bundler = await promptWhenInteractive<{ bundler: Bundler }>(
|
|
||||||
{
|
|
||||||
type: 'select',
|
|
||||||
name: 'bundler',
|
|
||||||
message: `Which bundler would you like to use to build the library? Choose 'none' to skip build setup.`,
|
|
||||||
choices: [
|
|
||||||
{ name: 'tsc' },
|
|
||||||
{ name: 'rollup' },
|
|
||||||
{ name: 'vite' },
|
|
||||||
{ name: 'none' },
|
|
||||||
],
|
|
||||||
initial: 0,
|
|
||||||
},
|
|
||||||
{ bundler: 'tsc' }
|
|
||||||
).then(({ bundler }) => bundler);
|
|
||||||
}
|
|
||||||
|
|
||||||
options.linter ??= await promptWhenInteractive<{
|
options.linter ??= await promptWhenInteractive<{
|
||||||
linter: 'none' | 'eslint';
|
linter: 'none' | 'eslint';
|
||||||
}>(
|
}>(
|
||||||
@ -766,50 +737,6 @@ async function normalizeOptions(
|
|||||||
{ unitTestRunner: 'none' }
|
{ unitTestRunner: 'none' }
|
||||||
).then(({ unitTestRunner }) => unitTestRunner);
|
).then(({ unitTestRunner }) => unitTestRunner);
|
||||||
} else {
|
} else {
|
||||||
if (options.bundler === undefined && options.compiler === undefined) {
|
|
||||||
options.bundler = await promptWhenInteractive<{ bundler: Bundler }>(
|
|
||||||
{
|
|
||||||
type: 'select',
|
|
||||||
name: 'bundler',
|
|
||||||
message: `Which bundler would you like to use to build the library? Choose 'none' to skip build setup.`,
|
|
||||||
choices: [
|
|
||||||
{ name: 'swc' },
|
|
||||||
{ name: 'tsc' },
|
|
||||||
{ name: 'rollup' },
|
|
||||||
{ name: 'vite' },
|
|
||||||
{ name: 'esbuild' },
|
|
||||||
{ name: 'none' },
|
|
||||||
],
|
|
||||||
initial: 1,
|
|
||||||
},
|
|
||||||
{ bundler: 'tsc' }
|
|
||||||
).then(({ bundler }) => bundler);
|
|
||||||
} else {
|
|
||||||
/**
|
|
||||||
* We are deprecating the compiler and the buildable options.
|
|
||||||
* However, we want to keep the existing behavior for now.
|
|
||||||
*
|
|
||||||
* So, if the user has not provided a bundler, we will use the compiler option, if any.
|
|
||||||
*
|
|
||||||
* If the user has not provided a bundler and no compiler, but has set buildable to true,
|
|
||||||
* we will use tsc, since that is the compiler the old generator used to default to, if buildable was true
|
|
||||||
* and no compiler was provided.
|
|
||||||
*
|
|
||||||
* If the user has not provided a bundler and no compiler, and has not set buildable to true, then
|
|
||||||
* set the bundler to tsc, to preserve old default behaviour (buildable: true by default).
|
|
||||||
*
|
|
||||||
* If it's publishable, we need to build the code before publishing it, so again
|
|
||||||
* we default to `tsc`. In the previous version of this, it would set `buildable` to true
|
|
||||||
* and that would default to `tsc`.
|
|
||||||
*
|
|
||||||
* In the past, the only way to get a non-buildable library was to set buildable to false.
|
|
||||||
* Now, the only way to get a non-buildble library is to set bundler to none.
|
|
||||||
* By default, with nothing provided, libraries are buildable with `@nx/js:tsc`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
options.bundler ??= options.compiler;
|
|
||||||
}
|
|
||||||
|
|
||||||
options.linter ??= await promptWhenInteractive<{
|
options.linter ??= await promptWhenInteractive<{
|
||||||
linter: 'none' | 'eslint';
|
linter: 'none' | 'eslint';
|
||||||
}>(
|
}>(
|
||||||
@ -843,6 +770,29 @@ async function normalizeOptions(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We are deprecating the compiler and the buildable options.
|
||||||
|
* However, we want to keep the existing behavior for now.
|
||||||
|
*
|
||||||
|
* So, if the user has not provided a bundler, we will use the compiler option, if any.
|
||||||
|
*
|
||||||
|
* If the user has not provided a bundler and no compiler, but has set buildable to true,
|
||||||
|
* we will use tsc, since that is the compiler the old generator used to default to, if buildable was true
|
||||||
|
* and no compiler was provided.
|
||||||
|
*
|
||||||
|
* If the user has not provided a bundler and no compiler, and has not set buildable to true, then
|
||||||
|
* set the bundler to tsc, to preserve old default behaviour (buildable: true by default).
|
||||||
|
*
|
||||||
|
* If it's publishable, we need to build the code before publishing it, so again
|
||||||
|
* we default to `tsc`. In the previous version of this, it would set `buildable` to true
|
||||||
|
* and that would default to `tsc`.
|
||||||
|
*
|
||||||
|
* In the past, the only way to get a non-buildable library was to set buildable to false.
|
||||||
|
* Now, the only way to get a non-buildble library is to set bundler to none.
|
||||||
|
* By default, with nothing provided, libraries are buildable with `@nx/js:tsc`.
|
||||||
|
*/
|
||||||
|
options.bundler ??= options.compiler ?? 'tsc';
|
||||||
|
|
||||||
// ensure programmatic runs have an expected default
|
// ensure programmatic runs have an expected default
|
||||||
if (!options.config) {
|
if (!options.config) {
|
||||||
options.config = 'project';
|
options.config = 'project';
|
||||||
@ -994,6 +944,11 @@ function getBuildExecutor(bundler: Bundler) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getOutputPath(options: NormalizedLibraryGeneratorOptions) {
|
function getOutputPath(options: NormalizedLibraryGeneratorOptions) {
|
||||||
|
if (options.isUsingTsSolutionConfig) {
|
||||||
|
// Executors expect paths relative to workspace root, so we prepend the project root
|
||||||
|
return joinPathFragments(options.projectRoot, 'dist');
|
||||||
|
}
|
||||||
|
|
||||||
const parts = [defaultOutputDirectory];
|
const parts = [defaultOutputDirectory];
|
||||||
if (options.projectRoot === '.') {
|
if (options.projectRoot === '.') {
|
||||||
parts.push(options.name);
|
parts.push(options.name);
|
||||||
@ -1170,8 +1125,12 @@ function determineEntryFields(
|
|||||||
case 'swc':
|
case 'swc':
|
||||||
return {
|
return {
|
||||||
type: 'commonjs',
|
type: 'commonjs',
|
||||||
main: './src/index.js',
|
main: options.isUsingTsSolutionConfig
|
||||||
typings: './src/index.d.ts',
|
? './dist/src/index.js'
|
||||||
|
: './src/index.js',
|
||||||
|
typings: options.isUsingTsSolutionConfig
|
||||||
|
? './dist/src/index.d.ts'
|
||||||
|
: './src/index.d.ts',
|
||||||
};
|
};
|
||||||
case 'rollup':
|
case 'rollup':
|
||||||
return {
|
return {
|
||||||
@ -1202,8 +1161,12 @@ function determineEntryFields(
|
|||||||
// For libraries intended for Node, use CJS.
|
// For libraries intended for Node, use CJS.
|
||||||
return {
|
return {
|
||||||
type: 'commonjs',
|
type: 'commonjs',
|
||||||
main: './index.cjs',
|
main: options.isUsingTsSolutionConfig
|
||||||
// typings is missing for esbuild currently
|
? './dist/index.cjs'
|
||||||
|
: './index.cjs',
|
||||||
|
typings: options.isUsingTsSolutionConfig
|
||||||
|
? './dist/index.d.ts'
|
||||||
|
: './index.d.ts',
|
||||||
};
|
};
|
||||||
default: {
|
default: {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -24,6 +24,8 @@
|
|||||||
"description": "The bundler to use. Choosing 'none' means this library is not buildable.",
|
"description": "The bundler to use. Choosing 'none' means this library is not buildable.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["swc", "tsc", "rollup", "vite", "esbuild", "none"],
|
"enum": ["swc", "tsc", "rollup", "vite", "esbuild", "none"],
|
||||||
|
"default": "tsc",
|
||||||
|
"x-prompt": "Which bundler would you like to use to build the library? Choose 'none' to skip build setup.",
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"linter": {
|
"linter": {
|
||||||
|
|||||||
1
packages/js/src/utils/schema.d.ts
vendored
1
packages/js/src/utils/schema.d.ts
vendored
@ -53,6 +53,7 @@ export interface NormalizedSwcExecutorOptions
|
|||||||
skipTypeCheck: boolean;
|
skipTypeCheck: boolean;
|
||||||
swcCliOptions: SwcCliOptions;
|
swcCliOptions: SwcCliOptions;
|
||||||
tmpSwcrcPath: string;
|
tmpSwcrcPath: string;
|
||||||
|
isTsSolutionSetup: boolean;
|
||||||
sourceRoot?: string;
|
sourceRoot?: string;
|
||||||
// TODO(v21): remove inline feature
|
// TODO(v21): remove inline feature
|
||||||
inline?: boolean;
|
inline?: boolean;
|
||||||
|
|||||||
@ -1,4 +1,11 @@
|
|||||||
import { output, readJson, readNxJson, type Tree } from '@nx/devkit';
|
import {
|
||||||
|
output,
|
||||||
|
readJson,
|
||||||
|
readNxJson,
|
||||||
|
workspaceRoot,
|
||||||
|
type Tree,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import { FsTree } from 'nx/src/generators/tree';
|
||||||
import { isUsingPackageManagerWorkspaces } from '../package-manager-workspaces';
|
import { isUsingPackageManagerWorkspaces } from '../package-manager-workspaces';
|
||||||
|
|
||||||
export function isUsingTypeScriptPlugin(tree: Tree): boolean {
|
export function isUsingTypeScriptPlugin(tree: Tree): boolean {
|
||||||
@ -13,7 +20,9 @@ export function isUsingTypeScriptPlugin(tree: Tree): boolean {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isUsingTsSolutionSetup(tree: Tree): boolean {
|
export function isUsingTsSolutionSetup(tree?: Tree): boolean {
|
||||||
|
tree ??= new FsTree(workspaceRoot, false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
isUsingPackageManagerWorkspaces(tree) &&
|
isUsingPackageManagerWorkspaces(tree) &&
|
||||||
isWorkspaceSetupWithTsSolution(tree)
|
isWorkspaceSetupWithTsSolution(tree)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user