feat(bundling): remove esbuild 0.16.0 support (#16435)

This commit is contained in:
Jack Hsu 2023-04-20 10:14:52 -04:00 committed by GitHub
parent b0d4cba79f
commit bef152d94e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 94 additions and 255 deletions

View File

@ -178,41 +178,6 @@ describe('EsBuild Plugin', () => {
expect(runCommand(`node dist/libs/${myPkg}`)).toMatch(/Hello/); expect(runCommand(`node dist/libs/${myPkg}`)).toMatch(/Hello/);
}, 300_000); }, 300_000);
it('should support new watch API in >= 0.17.0 and old watch API in < 0.17.0', async () => {
const myPkg = uniq('my-pkg');
runCLI(`generate @nrwl/js:lib ${myPkg} --bundler=esbuild`);
updateFile(`libs/${myPkg}/src/index.ts`, `console.log('new API');\n`);
let watchProcess = await runCommandUntil(
`build ${myPkg} --bundle=false --watch`,
(output) => {
return output.includes('build succeeded');
}
);
watchProcess.kill();
// Check that the build is correct
expect(runCommand(`node dist/libs/${myPkg}`)).toMatch(/new API/);
// Now install legacy esbuild and do a build watch
packageInstall('esbuild', undefined, '0.16.17');
rmDist();
watchProcess = await runCommandUntil(
`build ${myPkg} --bundle=false --watch`,
(output) => {
return output.includes('build succeeded');
}
);
watchProcess.kill();
// Check that the build is correct
expect(runCommand(`node dist/libs/${myPkg}`)).toMatch(/new API/);
}, 120_000);
it('should support additional entry points', () => { it('should support additional entry points', () => {
const myPkg = uniq('my-pkg'); const myPkg = uniq('my-pkg');
runCLI(`generate @nrwl/js:lib ${myPkg} --bundler=esbuild`); runCLI(`generate @nrwl/js:lib ${myPkg} --bundler=esbuild`);

View File

@ -22,6 +22,15 @@
"alwaysAddToPackageJson": false "alwaysAddToPackageJson": false
} }
} }
},
"16.0.0": {
"version": "16.0.0-beta.5",
"packages": {
"esbuild": {
"version": "0.17.17",
"alwaysAddToPackageJson": false
}
}
} }
} }
} }

View File

@ -91,236 +91,103 @@ export async function* esbuildExecutor(
packageJsonResult = await copyPackageJson(cpjOptions, context); packageJsonResult = await copyPackageJson(cpjOptions, context);
} }
if ('context' in esbuild) { if (options.watch) {
// 0.17.0+ adds esbuild.context and context.watch() return yield* createAsyncIterable<{ success: boolean; outfile?: string }>(
if (options.watch) { async ({ next, done }) => {
return yield* createAsyncIterable<{ success: boolean; outfile?: string }>( let hasTypeErrors = false;
async ({ next, done }) => { const disposeFns = await Promise.all(
let hasTypeErrors = false; options.format.map(async (format, idx) => {
const disposeFns = await Promise.all( const esbuildOptions = buildEsbuildOptions(
options.format.map(async (format, idx) => { format,
const esbuildOptions = buildEsbuildOptions( options,
format, context
options, );
context const ctx = await esbuild.context({
); ...esbuildOptions,
const ctx = await esbuild.context({ plugins: [
...esbuildOptions,
plugins: [
// Only emit info on one of the watch processes.
idx === 0
? {
name: 'nx-watch-plugin',
setup(build: esbuild.PluginBuild) {
build.onEnd(async (result: esbuild.BuildResult) => {
if (!options.skipTypeCheck) {
const { errors } = await runTypeCheck(
options,
context
);
hasTypeErrors = errors.length > 0;
}
const success =
result.errors.length === 0 && !hasTypeErrors;
if (!success) {
logger.info(BUILD_WATCH_FAILED);
} else {
logger.info(BUILD_WATCH_SUCCEEDED);
}
next({
success,
// Need to call getOutfile directly in the case of bundle=false and outfile is not set for esbuild.
outfile: join(
context.root,
getOutfile(format, options, context)
),
});
});
},
}
: null,
].filter(Boolean),
});
await ctx.watch();
return () => ctx.dispose();
})
);
registerCleanupCallback(() => {
assetsResult?.stop();
packageJsonResult?.stop();
disposeFns.forEach((fn) => fn());
done(); // return from async iterable
});
}
);
} else {
// Run type-checks first and bail if they don't pass.
if (!options.skipTypeCheck) {
const { errors } = await runTypeCheck(options, context);
if (errors.length > 0) {
yield { success: false };
return;
}
}
// Emit a build event for each file format.
for (let i = 0; i < options.format.length; i++) {
const format = options.format[i];
const esbuildOptions = buildEsbuildOptions(format, options, context);
const buildResult = await esbuild.build(esbuildOptions);
if (options.metafile) {
const filename =
options.format.length === 1
? 'meta.json'
: `meta.${options.format[i]}.json`;
writeJsonSync(
joinPathFragments(options.outputPath, filename),
buildResult.metafile
);
}
yield {
success: buildResult.errors.length === 0,
// Need to call getOutfile directly in the case of bundle=false and outfile is not set for esbuild.
// This field is needed for `@nx/js:node` executor to work.
outfile: join(context.root, getOutfile(format, options, context)),
};
}
}
} else {
// TODO(jack): Remove in Nx 16
// < 0.17.0 takes watch as an argument to build()
if (options.watch) {
return yield* createAsyncIterable<{ success: boolean; outfile?: string }>(
async ({ next, done }) => {
let hasTypeErrors = false;
const results = await Promise.all(
options.format.map(async (format, idx) => {
const esbuildOptions = buildEsbuildOptions(
format,
options,
context
);
const watch =
// Only emit info on one of the watch processes. // Only emit info on one of the watch processes.
idx === 0 idx === 0
? { ? {
onRebuild: async ( name: 'nx-watch-plugin',
error: esbuild.BuildFailure, setup(build: esbuild.PluginBuild) {
result: esbuild.BuildResult build.onEnd(async (result: esbuild.BuildResult) => {
) => { if (!options.skipTypeCheck) {
if (!options.skipTypeCheck) { const { errors } = await runTypeCheck(
const { errors } = await runTypeCheck( options,
options, context
context );
); hasTypeErrors = errors.length > 0;
hasTypeErrors = errors.length > 0; }
} const success =
const success = !error && !hasTypeErrors; result.errors.length === 0 && !hasTypeErrors;
if (!success) { if (!success) {
logger.info(BUILD_WATCH_FAILED); logger.info(BUILD_WATCH_FAILED);
} else { } else {
logger.info(BUILD_WATCH_SUCCEEDED); logger.info(BUILD_WATCH_SUCCEEDED);
} }
next({ next({
success, success,
// Need to call getOutfile directly in the case of bundle=false and outfile is not set for esbuild. // Need to call getOutfile directly in the case of bundle=false and outfile is not set for esbuild.
// This field is needed for `@nx/js:node` executor to work. outfile: join(
outfile: join( context.root,
context.root, getOutfile(format, options, context)
getOutfile(format, options, context) ),
), });
}); });
}, },
} }
: true; : null,
try { ].filter(Boolean),
const result = await esbuild.build({ });
...esbuildOptions,
watch,
});
next({ await ctx.watch();
success: true, return () => ctx.dispose();
// Need to call getOutfile directly in the case of bundle=false and outfile is not set for esbuild. })
outfile: join( );
context.root,
getOutfile(format, options, context)
),
});
return result; registerCleanupCallback(() => {
} catch { assetsResult?.stop();
next({ success: false }); packageJsonResult?.stop();
} disposeFns.forEach((fn) => fn());
}) done(); // return from async iterable
); });
}
);
} else {
// Run type-checks first and bail if they don't pass.
if (!options.skipTypeCheck) {
const { errors } = await runTypeCheck(options, context);
if (errors.length > 0) {
yield { success: false };
return;
}
}
registerCleanupCallback(() => { // Emit a build event for each file format.
assetsResult?.stop(); for (let i = 0; i < options.format.length; i++) {
packageJsonResult?.stop(); const format = options.format[i];
results.forEach((r) => const esbuildOptions = buildEsbuildOptions(format, options, context);
// result.stop() is no in esbuild 0.17.0+ but it exists in earlier versions const buildResult = await esbuild.build(esbuildOptions);
r?.['stop']?.()
);
done();
});
if (!options.skipTypeCheck) { if (options.metafile) {
const { errors } = await runTypeCheck(options, context); const filename =
hasTypeErrors = errors.length > 0; options.format.length === 1
} ? 'meta.json'
: `meta.${options.format[i]}.json`;
const success = writeJsonSync(
results.every((r) => r.errors?.length === 0) && !hasTypeErrors; joinPathFragments(options.outputPath, filename),
buildResult.metafile
if (!success) { );
logger.info(BUILD_WATCH_FAILED);
} else {
logger.info(BUILD_WATCH_SUCCEEDED);
}
}
);
} else {
// Run type-checks first and bail if they don't pass.
if (!options.skipTypeCheck) {
const { errors } = await runTypeCheck(options, context);
if (errors.length > 0) {
yield { success: false };
return;
}
} }
// Emit a build event for each file format. yield {
for (let i = 0; i < options.format.length; i++) { success: buildResult.errors.length === 0,
const format = options.format[i]; // Need to call getOutfile directly in the case of bundle=false and outfile is not set for esbuild.
const esbuildOptions = buildEsbuildOptions(format, options, context); // This field is needed for `@nx/js:node` executor to work.
const buildResult = await (esbuild as EsBuild).build(esbuildOptions); outfile: join(context.root, getOutfile(format, options, context)),
};
if (options.metafile) {
const filename =
options.format.length === 1
? 'meta.json'
: `meta.${options.format[i]}.json`;
writeJsonSync(
joinPathFragments(options.outputPath, filename),
buildResult.metafile
);
}
yield {
success: buildResult.errors.length === 0,
// Need to call getOutfile directly in the case of bundle=false and outfile is not set for esbuild.
outfile: join(context.root, getOutfile(format, options, context)),
};
}
} }
} }
} }

View File

@ -1,6 +1,6 @@
export const nxVersion = require('../../package.json').version; export const nxVersion = require('../../package.json').version;
export const esbuildVersion = '^0.17.5'; export const esbuildVersion = '^0.17.17';
export const prettierVersion = '^2.6.2'; export const prettierVersion = '^2.6.2';
export const swcCliVersion = '~0.1.62'; export const swcCliVersion = '~0.1.62';
export const swcCoreVersion = '~1.3.51'; export const swcCoreVersion = '~1.3.51';

View File

@ -30,7 +30,6 @@ import { join } from 'path';
import { initGenerator } from '../init/init'; import { initGenerator } from '../init/init';
import { import {
esbuildVersion,
expressTypingsVersion, expressTypingsVersion,
expressVersion, expressVersion,
fastifyAutoloadVersion, fastifyAutoloadVersion,
@ -46,6 +45,7 @@ import { setupDockerGenerator } from '../setup-docker/setup-docker';
import { Schema } from './schema'; import { Schema } from './schema';
import { mapLintPattern } from '@nx/linter/src/generators/lint-project/lint-project'; import { mapLintPattern } from '@nx/linter/src/generators/lint-project/lint-project';
import { esbuildVersion } from '@nx/js/src/utils/versions';
export interface NormalizedSchema extends Schema { export interface NormalizedSchema extends Schema {
appProjectRoot: string; appProjectRoot: string;

View File

@ -4,8 +4,6 @@ export const tslibVersion = '^2.3.0';
export const typesNodeVersion = '~18.7.1'; export const typesNodeVersion = '~18.7.1';
export const esbuildVersion = '^0.17.5';
export const expressVersion = '~4.18.1'; export const expressVersion = '~4.18.1';
export const expressTypingsVersion = '~4.17.13'; export const expressTypingsVersion = '~4.17.13';