nx/packages/js/babel.ts
Jack Hsu 2e621f324c
feat(misc): v19 cleanup for Nx plugins (#23104)
This PR removes deprecated code that's been slated for removal in Nx 19
- mentioned as `TODO(v19)` comments.

## Breaking Changes

- **CNW:** `create-nx-workspace` no longer support `--preset=empty` and
`--preset=core`, use `--preset=apps` and `--preset=npm` respectively.
Deprecated in Nx 15.9.
- **Next.js:** `NX_` environment variables are no longer bundled into
Next.js apps, use `NEXT_PUBLIC` instead. Deprecated in Nx 16.8.
- **Webpack, Storybook, Esbuild:** `NX_` environment variables are no
longer bundled into browser bundles, use `NX_PUBLIC` instead. This
removes the possibility of intentional bundling of `NX_` variables.
Deprecated in Nx 18.
- **Cypress:** `cypressComponentConfiguration` generator removed from
`@nx/cypress`, use `configurationGenerator`instead. Deprecated in Nx
16.8.
- **Cypress:** `cypressProjectGenerator` generator removed from
`@nx/cypress`, use `configurationGenerator` instead. Deprecated in Nx
15.9.
- **Expo:** `withNxWebpack` removed from `@nx/expo`, use [metro
bundler](https://docs.expo.dev/guides/customizing-metro/)
(https://docs.expo.dev/guides/customizing-metro/) in app.json instead.
There is a migration to handle this in Nx 19. Deprecated in Nx 15.8.

## Deferred to v20

- **JS:** `classProperties.loose` option removed from `@nx/js/babel`
preset, use `loose` instead. Deprecated in Nx 17.0.
- **ESLint:** Low priority task to "deviations from
@typescript-eslint/recommended" for our lint rules. @JamesHenry will
look at this later before Nx 20, but it is unimportant.
- **React:** component testing does not work with Project Crystal, and
we need the executor + built-in webpack configs to run CT. Will do a
follow-up on this after Nx 19 release. Related issue:
https://github.com/nrwl/nx/issues/21546
- **Next.js:** `withStylus` removal from `@nx/next`, use SASS instead.
It hasn't worked, but we kept the file to throw an error when used.
Deprecated in Nx 17.0.
- **Next.js**: `@nx/next:component` and `@nx/next:page` generators to
not derive the `components` and `app`/`pages` directory. Use `nx g
@nx/next:component apps/myapp/components/button` instead. Deprecated in
Nx 17.0.
- **Webpack:** `isolatedConfig` option removal from
`@nx/webpack:webpack` executor. There is a migration to handle this in
Nx 19. Deprecated in in Nx 17.2.
- **Angular:** `executeWebpackDevServerBuilder` removal from
`@nx/angular/executors`, use `executeDevServerBuilder` instead.
Deprecated in Nx 17.0.
2024-05-02 13:37:12 -04:00

148 lines
4.6 KiB
TypeScript

import { dirname } from 'path';
import { parse } from 'semver';
import { logger } from '@nx/devkit';
/*
* Babel preset to provide TypeScript support and module/nomodule for Nx.
*/
export interface NxWebBabelPresetOptions {
useBuiltIns?: boolean | string;
decorators?: {
decoratorsBeforeExport?: boolean;
legacy?: boolean;
};
loose?: boolean;
/** @deprecated Use `loose` option instead of `classProperties.loose`
*/
classProperties?: {
loose?: boolean;
};
}
module.exports = function (api: any, options: NxWebBabelPresetOptions = {}) {
api.assertVersion(7);
const isModern = api.caller((caller) => caller?.isModern);
// use by @nx/cypress react component testing to prevent core js build issues
const isTest = api.caller((caller) => caller?.isTest);
// This is set by `@nx/rollup:rollup` executor
const isNxPackage = api.caller((caller) => caller?.isNxPackage);
const emitDecoratorMetadata = api.caller(
(caller) => caller?.emitDecoratorMetadata ?? true
);
// Determine settings for `@babel//babel-plugin-transform-class-properties`,
// so that we can sync the `loose` option with `@babel/preset-env`.
// TODO(v20): Remove classProperties since it's no longer needed, now that the class props transform is in preset-env.
const loose = options.classProperties?.loose ?? options.loose ?? true;
if (options.classProperties) {
logger.warn(
`Use =\`loose\` option instead of \`classProperties.loose\`. The \`classProperties\` option will be removed in Nx 19`
);
}
return {
presets: [
// Support module/nomodule pattern.
[
require.resolve('@babel/preset-env'),
// For Jest tests, NODE_ENV is set as 'test' and we only want to set target as Node.
// All other options will fail in Jest since Node does not support some ES features
// such as import syntax.
isTest || process.env.NODE_ENV === 'test' || process.env.JEST_WORKER_ID
? { targets: { node: 'current' }, loose: true }
: createBabelPresetEnvOptions(options.useBuiltIns, isModern, loose),
],
[
require.resolve('@babel/preset-typescript'),
{
allowDeclareFields: true,
},
],
],
plugins: [
!isNxPackage
? [
require.resolve('@babel/plugin-transform-runtime'),
{
corejs: false,
helpers: true,
regenerator: true,
useESModules: isModern,
absoluteRuntime: dirname(
require.resolve('@babel/runtime/package.json')
),
},
]
: null,
require.resolve('babel-plugin-macros'),
emitDecoratorMetadata
? require.resolve('babel-plugin-transform-typescript-metadata')
: undefined,
// Must use legacy decorators to remain compatible with TypeScript.
[
require.resolve('@babel/plugin-proposal-decorators'),
options.decorators ?? { legacy: true },
],
[require.resolve('@babel/plugin-transform-class-properties'), { loose }],
].filter(Boolean),
overrides: [
// Convert `const enum` to `enum`. The former cannot be supported by babel
// but at least we can get it to not error out.
{
test: /\.tsx?$/,
plugins: [
[
require.resolve('babel-plugin-const-enum'),
{
transform: 'removeConst',
},
],
],
},
],
};
};
function createBabelPresetEnvOptions(
useBuiltIns: string | boolean,
isModern: boolean,
loose: boolean
) {
const presetOptions: any = {
// Do not transform modules to CJS
modules: false,
targets: isModern ? { esmodules: 'intersect' } : undefined,
bugfixes: true,
// Exclude transforms that make all code slower
exclude: ['transform-typeof-symbol'],
// This must match the setting for `@babel/plugin-proposal-class-properties`
loose,
};
// If core-js is installed then set corresponding options, otherwise don't use core-js.
// Previously, core-js was required for all projects, but it is not longer required when using only stable JS features that does not need to be transpiled.
const coreJsVersion = findCoreJsVersion();
if (coreJsVersion) {
presetOptions.useBuiltIns = useBuiltIns ?? 'entry';
presetOptions.corejs = useBuiltIns !== false ? coreJsVersion : null;
}
return presetOptions;
}
function findCoreJsVersion(): string | null {
try {
// nx-ignore-next-line
const v = require('core-js/package.json').version;
const { major, minor } = parse(v);
return `${major}.${minor}`;
} catch (e) {
return null;
}
}