Skip to content

Commit

Permalink
fix(react): update .swcrc with plugin for CSS-in-JS solution when SWC…
Browse files Browse the repository at this point in the history
… is used for apps (#17295)
  • Loading branch information
jaysoo authored May 30, 2023
1 parent 4398932 commit c8a264a
Show file tree
Hide file tree
Showing 12 changed files with 207 additions and 51 deletions.
6 changes: 5 additions & 1 deletion packages/next/src/generators/application/application.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
convertNxGenerator,
formatFiles,
joinPathFragments,
runTasksInSerial,
Tree,
} from '@nx/devkit';
Expand Down Expand Up @@ -36,7 +37,10 @@ export async function applicationGenerator(host: Tree, schema: Schema) {
const lintTask = await addLinting(host, options);
updateJestConfig(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);

if (options.customServer) {
Expand Down
8 changes: 7 additions & 1 deletion packages/next/src/generators/component/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import {
convertNxGenerator,
formatFiles,
getProjects,
joinPathFragments,
readProjectConfiguration,
runTasksInSerial,
Tree,
} from '@nx/devkit';
Expand Down Expand Up @@ -37,6 +39,7 @@ function getDirectory(host: Tree, options: Schema) {
* extra dependencies for css, sass, less, styl style options.
*/
export async function componentGenerator(host: Tree, options: Schema) {
const project = readProjectConfiguration(host, options.project);
const componentInstall = await reactComponentGenerator(host, {
...options,
directory: getDirectory(host, options),
Expand All @@ -45,7 +48,10 @@ export async function componentGenerator(host: Tree, options: Schema) {
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) {
await formatFiles(host);
Expand Down
8 changes: 7 additions & 1 deletion packages/next/src/generators/page/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { componentGenerator as reactComponentGenerator } from '@nx/react';
import {
convertNxGenerator,
formatFiles,
joinPathFragments,
readProjectConfiguration,
runTasksInSerial,
Tree,
} from '@nx/devkit';
Expand All @@ -15,6 +17,7 @@ import { Schema } from './schema';
* it is under `pages` folder.
*/
export async function pageGenerator(host: Tree, options: Schema) {
const project = readProjectConfiguration(host, options.project);
const directory = options.directory ? `pages/${options.directory}` : 'pages';
const componentTask = await reactComponentGenerator(host, {
...options,
Expand All @@ -29,7 +32,10 @@ export async function pageGenerator(host: Tree, options: Schema) {
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) {
await formatFiles(host);
Expand Down
69 changes: 50 additions & 19 deletions packages/next/src/utils/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import {
} from '@nx/devkit';

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 {
babelPluginStyledComponentsVersion,
emotionServerVersion,
Expand All @@ -15,21 +18,7 @@ import {
stylusLoader,
} from './versions';

export const NEXT_SPECIFIC_STYLE_DEPENDENCIES = {
'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,
},
const nextSpecificStyleDependenciesCommon = {
css: {
dependencies: {},
devDependencies: {},
Expand All @@ -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(
host: Tree,
style: string
options: { style?: string; swc?: boolean }
): GeneratorCallback {
const extraDependencies = NEXT_SPECIFIC_STYLE_DEPENDENCIES[style];
const extraDependencies = options.swc
? nextSpecificStyleDependenciesSwc[options.style]
: nextSpecificStyleDependenciesBabel[options.style];

if (!extraDependencies) return () => {};

Expand All @@ -70,7 +98,10 @@ export function addStyleDependencies(

// @zeit/next-less & @zeit/next-stylus internal configuration is working only
// 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) => {
json.resolutions = { ...json.resolutions, 'css-loader': '1.0.1' };
return json;
Expand Down
2 changes: 1 addition & 1 deletion packages/react/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export {
extraEslintDependencies,
extendReactEslintJson,
} 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 { reactDomVersion, reactVersion } from './src/utils/versions';
export { applicationGenerator } from './src/generators/application/application';
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/generators/application/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ export async function applicationGenerator(
updateSpecConfig(host, options);
const stylePreprocessorTask = installCommonDependencies(host, options);
tasks.push(stylePreprocessorTask);
const styledTask = addStyledModuleDependencies(host, options.styledModule);
const styledTask = addStyledModuleDependencies(host, options);
tasks.push(styledTask);
const routingTask = addRouting(host, options);
tasks.push(routingTask);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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 { join } from 'path';
import { createTsConfig } from '../../../utils/create-ts-config';
Expand Down Expand Up @@ -34,17 +41,87 @@ export function createApplicationFiles(host: Tree, options: NormalizedSchema) {
inSourceVitestTests: getInSourceVitestTestsTemplate(appTests),
};

let fileDirectory: string;
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') {
fileDirectory = join(__dirname, '../files/base-webpack');
generateFiles(
host,
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`,

{
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') {
fileDirectory = join(__dirname, '../files/base-rspack');
generateFiles(
host,
join(__dirname, '../files/base-rspack'),
options.appProjectRoot,
templateVariables
);
}

generateFiles(host, fileDirectory, options.appProjectRoot, templateVariables);

if (
options.unitTestRunner === 'none' ||
(options.unitTestRunner === 'vitest' && options.inSourceTests == true)
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/generators/component/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export async function componentGenerator(host: Tree, schema: Schema) {

const tasks: GeneratorCallback[] = [];

const styledTask = addStyledModuleDependencies(host, options.styledModule);
const styledTask = addStyledModuleDependencies(host, options);
tasks.push(styledTask);

addExportsToBarrel(host, options);
Expand Down
15 changes: 12 additions & 3 deletions packages/react/src/rules/add-styled-dependencies.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import { CSS_IN_JS_DEPENDENCIES } from '../utils/styled';
import { addDependenciesToPackageJson, Tree } from '@nx/devkit';
import {
cssInJsDependenciesBabel,
cssInJsDependenciesSwc,
} from '../utils/styled';

export function addStyledModuleDependencies(host: Tree, styledModule: string) {
const extraDependencies = CSS_IN_JS_DEPENDENCIES[styledModule];
export function addStyledModuleDependencies(
host: Tree,
options: { styledModule?: string; compiler?: 'babel' | 'swc' }
) {
const extraDependencies =
options.compiler === 'swc'
? cssInJsDependenciesSwc[options.styledModule]
: cssInJsDependenciesBabel[options.styledModule];

if (extraDependencies) {
return addDependenciesToPackageJson(
Expand Down
Loading

1 comment on commit c8a264a

@vercel
Copy link

@vercel vercel bot commented on c8a264a May 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nx-dev – ./

nx-five.vercel.app
nx-dev-nrwl.vercel.app
nx.dev
nx-dev-git-master-nrwl.vercel.app

Please sign in to comment.