fix(react): update .swcrc with plugin for CSS-in-JS solution when SWC is used for apps (#17295)

This commit is contained in:
Jack Hsu 2023-05-30 01:33:08 -04:00 committed by GitHub
parent 4398932d0e
commit c8a264a932
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 208 additions and 52 deletions

View File

@ -1,6 +1,7 @@
import { import {
convertNxGenerator, convertNxGenerator,
formatFiles, formatFiles,
joinPathFragments,
runTasksInSerial, runTasksInSerial,
Tree, Tree,
} from '@nx/devkit'; } from '@nx/devkit';
@ -36,7 +37,10 @@ export async function applicationGenerator(host: Tree, schema: Schema) {
const lintTask = await addLinting(host, options); const lintTask = await addLinting(host, options);
updateJestConfig(host, options); updateJestConfig(host, options);
updateCypressTsConfig(host, options); updateCypressTsConfig(host, options);
const styledTask = addStyleDependencies(host, options.style); const styledTask = addStyleDependencies(host, {
style: options.style,
swc: !host.exists(joinPathFragments(options.appProjectRoot, '.babelrc')),
});
setDefaults(host, options); setDefaults(host, options);
if (options.customServer) { if (options.customServer) {

View File

@ -2,6 +2,8 @@ import {
convertNxGenerator, convertNxGenerator,
formatFiles, formatFiles,
getProjects, getProjects,
joinPathFragments,
readProjectConfiguration,
runTasksInSerial, runTasksInSerial,
Tree, Tree,
} from '@nx/devkit'; } from '@nx/devkit';
@ -37,6 +39,7 @@ function getDirectory(host: Tree, options: Schema) {
* extra dependencies for css, sass, less, styl style options. * extra dependencies for css, sass, less, styl style options.
*/ */
export async function componentGenerator(host: Tree, options: Schema) { export async function componentGenerator(host: Tree, options: Schema) {
const project = readProjectConfiguration(host, options.project);
const componentInstall = await reactComponentGenerator(host, { const componentInstall = await reactComponentGenerator(host, {
...options, ...options,
directory: getDirectory(host, options), directory: getDirectory(host, options),
@ -45,7 +48,10 @@ export async function componentGenerator(host: Tree, options: Schema) {
skipFormat: true, skipFormat: true,
}); });
const styledInstall = addStyleDependencies(host, options.style); const styledInstall = addStyleDependencies(host, {
style: options.style,
swc: !host.exists(joinPathFragments(project.root, '.babelrc')),
});
if (!options.skipFormat) { if (!options.skipFormat) {
await formatFiles(host); await formatFiles(host);

View File

@ -2,6 +2,8 @@ import { componentGenerator as reactComponentGenerator } from '@nx/react';
import { import {
convertNxGenerator, convertNxGenerator,
formatFiles, formatFiles,
joinPathFragments,
readProjectConfiguration,
runTasksInSerial, runTasksInSerial,
Tree, Tree,
} from '@nx/devkit'; } from '@nx/devkit';
@ -15,6 +17,7 @@ import { Schema } from './schema';
* it is under `pages` folder. * it is under `pages` folder.
*/ */
export async function pageGenerator(host: Tree, options: Schema) { export async function pageGenerator(host: Tree, options: Schema) {
const project = readProjectConfiguration(host, options.project);
const directory = options.directory ? `pages/${options.directory}` : 'pages'; const directory = options.directory ? `pages/${options.directory}` : 'pages';
const componentTask = await reactComponentGenerator(host, { const componentTask = await reactComponentGenerator(host, {
...options, ...options,
@ -29,7 +32,10 @@ export async function pageGenerator(host: Tree, options: Schema) {
skipFormat: true, skipFormat: true,
}); });
const styledTask = addStyleDependencies(host, options.style); const styledTask = addStyleDependencies(host, {
style: options.style,
swc: !host.exists(joinPathFragments(project.root, '.babelrc')),
});
if (!options.skipFormat) { if (!options.skipFormat) {
await formatFiles(host); await formatFiles(host);

View File

@ -6,7 +6,10 @@ import {
} from '@nx/devkit'; } from '@nx/devkit';
import { lessVersion, stylusVersion } from '@nx/react/src/utils/versions'; import { lessVersion, stylusVersion } from '@nx/react/src/utils/versions';
import { CSS_IN_JS_DEPENDENCIES } from '@nx/react/src/utils/styled'; import {
cssInJsDependenciesBabel,
cssInJsDependenciesSwc,
} from '@nx/react/src/utils/styled';
import { import {
babelPluginStyledComponentsVersion, babelPluginStyledComponentsVersion,
emotionServerVersion, emotionServerVersion,
@ -15,21 +18,7 @@ import {
stylusLoader, stylusLoader,
} from './versions'; } from './versions';
export const NEXT_SPECIFIC_STYLE_DEPENDENCIES = { const nextSpecificStyleDependenciesCommon = {
'styled-components': {
dependencies: CSS_IN_JS_DEPENDENCIES['styled-components'].dependencies,
devDependencies: {
...CSS_IN_JS_DEPENDENCIES['styled-components'].devDependencies,
'babel-plugin-styled-components': babelPluginStyledComponentsVersion,
},
},
'@emotion/styled': {
dependencies: {
...CSS_IN_JS_DEPENDENCIES['@emotion/styled'].dependencies,
'@emotion/server': emotionServerVersion,
},
devDependencies: CSS_IN_JS_DEPENDENCIES['@emotion/styled'].devDependencies,
},
css: { css: {
dependencies: {}, dependencies: {},
devDependencies: {}, devDependencies: {},
@ -54,11 +43,50 @@ export const NEXT_SPECIFIC_STYLE_DEPENDENCIES = {
}, },
}; };
export const nextSpecificStyleDependenciesBabel = {
...nextSpecificStyleDependenciesCommon,
'styled-components': {
dependencies: cssInJsDependenciesBabel['styled-components'].dependencies,
devDependencies: {
...cssInJsDependenciesBabel['styled-components'].devDependencies,
'babel-plugin-styled-components': babelPluginStyledComponentsVersion,
},
},
'@emotion/styled': {
dependencies: {
...cssInJsDependenciesBabel['@emotion/styled'].dependencies,
'@emotion/server': emotionServerVersion,
},
devDependencies:
cssInJsDependenciesBabel['@emotion/styled'].devDependencies,
},
};
export const nextSpecificStyleDependenciesSwc = {
...nextSpecificStyleDependenciesCommon,
'styled-components': {
dependencies: cssInJsDependenciesSwc['styled-components'].dependencies,
devDependencies: {
...cssInJsDependenciesSwc['styled-components'].devDependencies,
'babel-plugin-styled-components': babelPluginStyledComponentsVersion,
},
},
'@emotion/styled': {
dependencies: {
...cssInJsDependenciesSwc['@emotion/styled'].dependencies,
'@emotion/server': emotionServerVersion,
},
devDependencies: cssInJsDependenciesSwc['@emotion/styled'].devDependencies,
},
};
export function addStyleDependencies( export function addStyleDependencies(
host: Tree, host: Tree,
style: string options: { style?: string; swc?: boolean }
): GeneratorCallback { ): GeneratorCallback {
const extraDependencies = NEXT_SPECIFIC_STYLE_DEPENDENCIES[style]; const extraDependencies = options.swc
? nextSpecificStyleDependenciesSwc[options.style]
: nextSpecificStyleDependenciesBabel[options.style];
if (!extraDependencies) return () => {}; if (!extraDependencies) return () => {};
@ -70,7 +98,10 @@ export function addStyleDependencies(
// @zeit/next-less & @zeit/next-stylus internal configuration is working only // @zeit/next-less & @zeit/next-stylus internal configuration is working only
// for specific CSS loader version, causing PNPM resolution to fail. // for specific CSS loader version, causing PNPM resolution to fail.
if (host.exists('pnpm-lock.yaml') && (style === 'less' || style === 'styl')) { if (
host.exists('pnpm-lock.yaml') &&
(options.style === 'less' || options.style === 'styl')
) {
updateJson(host, `package.json`, (json) => { updateJson(host, `package.json`, (json) => {
json.resolutions = { ...json.resolutions, 'css-loader': '1.0.1' }; json.resolutions = { ...json.resolutions, 'css-loader': '1.0.1' };
return json; return json;

View File

@ -2,7 +2,7 @@ export {
extraEslintDependencies, extraEslintDependencies,
extendReactEslintJson, extendReactEslintJson,
} from './src/utils/lint'; } from './src/utils/lint';
export { CSS_IN_JS_DEPENDENCIES } from './src/utils/styled'; export { cssInJsDependenciesBabel } from './src/utils/styled';
export { assertValidStyle } from './src/utils/assertion'; export { assertValidStyle } from './src/utils/assertion';
export { reactDomVersion, reactVersion } from './src/utils/versions'; export { reactDomVersion, reactVersion } from './src/utils/versions';
export { applicationGenerator } from './src/generators/application/application'; export { applicationGenerator } from './src/generators/application/application';

View File

@ -205,7 +205,7 @@ export async function applicationGenerator(
updateSpecConfig(host, options); updateSpecConfig(host, options);
const stylePreprocessorTask = installCommonDependencies(host, options); const stylePreprocessorTask = installCommonDependencies(host, options);
tasks.push(stylePreprocessorTask); tasks.push(stylePreprocessorTask);
const styledTask = addStyledModuleDependencies(host, options.styledModule); const styledTask = addStyledModuleDependencies(host, options);
tasks.push(styledTask); tasks.push(styledTask);
const routingTask = addRouting(host, options); const routingTask = addRouting(host, options);
tasks.push(routingTask); tasks.push(routingTask);

View File

@ -1,13 +0,0 @@
{
"presets": [
[
"@nx/react/babel", {
"runtime": "automatic"<% if (style === '@emotion/styled') { %>,<% } %>
<% 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"<% } %>
]
}

View File

@ -1,4 +1,11 @@
import { names, offsetFromRoot, Tree, toJS, generateFiles } from '@nx/devkit'; import {
generateFiles,
names,
offsetFromRoot,
toJS,
Tree,
writeJson,
} from '@nx/devkit';
import { getRelativePathToRootTsConfig } from '@nx/js'; import { getRelativePathToRootTsConfig } from '@nx/js';
import { join } from 'path'; import { join } from 'path';
import { createTsConfig } from '../../../utils/create-ts-config'; import { createTsConfig } from '../../../utils/create-ts-config';
@ -34,16 +41,86 @@ export function createApplicationFiles(host: Tree, options: NormalizedSchema) {
inSourceVitestTests: getInSourceVitestTestsTemplate(appTests), inSourceVitestTests: getInSourceVitestTestsTemplate(appTests),
}; };
let fileDirectory: string;
if (options.bundler === 'vite') { if (options.bundler === 'vite') {
fileDirectory = join(__dirname, '../files/base-vite'); generateFiles(
host,
join(__dirname, '../files/base-vite'),
options.appProjectRoot,
templateVariables
);
} else if (options.bundler === 'webpack') { } else if (options.bundler === 'webpack') {
fileDirectory = join(__dirname, '../files/base-webpack'); generateFiles(
} else if (options.bundler === 'rspack') { host,
fileDirectory = join(__dirname, '../files/base-rspack'); join(__dirname, '../files/base-webpack'),
} options.appProjectRoot,
templateVariables
);
if (options.compiler === 'babel') {
writeJson(host, `${options.appProjectRoot}/.babelrc`, {
presets: [
[
'@nx/react/babel',
{
runtime: 'automatic',
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),
});
} else if (
options.style === 'styled-components' ||
options.style === '@emotion/styled' ||
options.style === 'styled-jsx'
) {
writeJson(
host,
`${options.appProjectRoot}/.swcrc`,
generateFiles(host, fileDirectory, options.appProjectRoot, templateVariables); {
jsc: {
experimental: {
plugins: [
options.style === 'styled-components'
? [
'@swc/plugin-styled-components',
{
displayName: true,
ssr: true,
},
]
: undefined,
options.style === 'styled-jsx'
? ['@swc/plugin-styled-jsx', {}]
: undefined,
options.style === '@emotion/styled'
? ['@swc/plugin-emotion', {}]
: undefined,
].filter(Boolean),
},
},
}
);
}
} else if (options.bundler === 'rspack') {
generateFiles(
host,
join(__dirname, '../files/base-rspack'),
options.appProjectRoot,
templateVariables
);
}
if ( if (
options.unitTestRunner === 'none' || options.unitTestRunner === 'none' ||

View File

@ -30,7 +30,7 @@ export async function componentGenerator(host: Tree, schema: Schema) {
const tasks: GeneratorCallback[] = []; const tasks: GeneratorCallback[] = [];
const styledTask = addStyledModuleDependencies(host, options.styledModule); const styledTask = addStyledModuleDependencies(host, options);
tasks.push(styledTask); tasks.push(styledTask);
addExportsToBarrel(host, options); addExportsToBarrel(host, options);

View File

@ -1,8 +1,17 @@
import { CSS_IN_JS_DEPENDENCIES } from '../utils/styled';
import { addDependenciesToPackageJson, Tree } from '@nx/devkit'; import { addDependenciesToPackageJson, Tree } from '@nx/devkit';
import {
cssInJsDependenciesBabel,
cssInJsDependenciesSwc,
} from '../utils/styled';
export function addStyledModuleDependencies(host: Tree, styledModule: string) { export function addStyledModuleDependencies(
const extraDependencies = CSS_IN_JS_DEPENDENCIES[styledModule]; host: Tree,
options: { styledModule?: string; compiler?: 'babel' | 'swc' }
) {
const extraDependencies =
options.compiler === 'swc'
? cssInJsDependenciesSwc[options.styledModule]
: cssInJsDependenciesBabel[options.styledModule];
if (extraDependencies) { if (extraDependencies) {
return addDependenciesToPackageJson( return addDependenciesToPackageJson(

View File

@ -6,14 +6,15 @@ import {
reactIsVersion, reactIsVersion,
styledComponentsVersion, styledComponentsVersion,
styledJsxVersion, styledJsxVersion,
swcPluginEmotionVersion,
swcPluginStyledComponentsVersion,
swcPluginStyledJsxVersion,
typesReactIsVersion, typesReactIsVersion,
typesStyledComponentsVersion, typesStyledComponentsVersion,
} from './versions'; } from './versions';
import { PackageDependencies } from './dependencies'; import { PackageDependencies } from './dependencies';
export const CSS_IN_JS_DEPENDENCIES: { export const cssInJsDependenciesBabel: Record<string, PackageDependencies> = {
[style: string]: PackageDependencies;
} = {
'styled-components': { 'styled-components': {
dependencies: { dependencies: {
'react-is': reactIsVersion, 'react-is': reactIsVersion,
@ -41,3 +42,34 @@ export const CSS_IN_JS_DEPENDENCIES: {
devDependencies: {}, devDependencies: {},
}, },
}; };
export const cssInJsDependenciesSwc: Record<string, PackageDependencies> = {
'styled-components': {
dependencies: {
'react-is': reactIsVersion,
'styled-components': styledComponentsVersion,
},
devDependencies: {
'@types/styled-components': typesStyledComponentsVersion,
'@types/react-is': typesReactIsVersion,
'@swc/plugin-styled-components': swcPluginStyledComponentsVersion,
},
},
'@emotion/styled': {
dependencies: {
'@emotion/styled': emotionStyledVersion,
'@emotion/react': emotionReactVersion,
},
devDependencies: {
'@swc/plugin-emotion': swcPluginEmotionVersion,
},
},
'styled-jsx': {
dependencies: {
'styled-jsx': styledJsxVersion,
},
devDependencies: {
'@swc/plugin-styled-jsx': swcPluginStyledJsxVersion,
},
},
};

View File

@ -63,3 +63,7 @@ export const stylusVersion = '^0.55.0';
// rollup plugins (if needed) // rollup plugins (if needed)
export const rollupPluginUrlVersion = '^7.0.0'; export const rollupPluginUrlVersion = '^7.0.0';
export const svgrRollupVersion = '^8.0.1'; export const svgrRollupVersion = '^8.0.1';
export const swcPluginStyledJsxVersion = '^1.5.67';
export const swcPluginEmotionVersion = '^2.5.67';
export const swcPluginStyledComponentsVersion = '^1.5.67';