From 5a0f05491db3a5c9d128c8e72ac499919b1bbdf1 Mon Sep 17 00:00:00 2001 From: puku0x Date: Thu, 25 Nov 2021 01:17:42 +0900 Subject: [PATCH] fix(react): fix external option for @emotion/react --- packages/react/migrations.json | 5 ++ .../src/generators/library/library.spec.ts | 2 +- .../react/src/generators/library/library.ts | 6 +- ...pdate-external-emotion-jsx-runtime.spec.ts | 64 +++++++++++++++++++ .../update-external-emotion-jsx-runtime.ts | 58 +++++++++++++++++ 5 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 packages/react/src/migrations/update-13-2-3/update-external-emotion-jsx-runtime.spec.ts create mode 100644 packages/react/src/migrations/update-13-2-3/update-external-emotion-jsx-runtime.ts diff --git a/packages/react/migrations.json b/packages/react/migrations.json index f7e1395e2fc0b6..f85ab51552fd42 100644 --- a/packages/react/migrations.json +++ b/packages/react/migrations.json @@ -104,6 +104,11 @@ "version": "13.0.0-beta.0", "description": "Migrate Storybook to use webpack 5", "factory": "./src/migrations/update-13-0-0/migrate-storybook-to-webpack-5" + }, + "update-external-emotion-jsx-runtime-13.2.3": { + "version": "13.2.3-beta.0", + "description": "Update external option in projects for Emotion", + "factory": "./src/migrations/update-13-2-3/update-external-emotion-jsx-runtime" } }, "packageJsonUpdates": { diff --git a/packages/react/src/generators/library/library.spec.ts b/packages/react/src/generators/library/library.spec.ts index ed4d95292dfed7..d800b8d3e4dd5a 100644 --- a/packages/react/src/generators/library/library.spec.ts +++ b/packages/react/src/generators/library/library.spec.ts @@ -507,7 +507,7 @@ describe('lib', () => { expect(workspaceJson.projects['my-lib'].architect.build).toMatchObject({ options: { - external: ['react/jsx-runtime', '@emotion/styled/base'], + external: ['@emotion/react/jsx-runtime'], }, }); expect(babelrc.plugins).toEqual(['@emotion/babel-plugin']); diff --git a/packages/react/src/generators/library/library.ts b/packages/react/src/generators/library/library.ts index 8639aa0b88532e..ec14db7848b958 100644 --- a/packages/react/src/generators/library/library.ts +++ b/packages/react/src/generators/library/library.ts @@ -173,10 +173,12 @@ function addProject(host: Tree, options: NormalizedSchema) { if (options.publishable || options.buildable) { const { libsDir } = getWorkspaceLayout(host); - const external = ['react/jsx-runtime']; + const external: string[] = []; if (options.style === '@emotion/styled') { - external.push('@emotion/styled/base'); + external.push('@emotion/react/jsx-runtime'); + } else { + external.push('react/jsx-runtime'); } targets.build = { diff --git a/packages/react/src/migrations/update-13-2-3/update-external-emotion-jsx-runtime.spec.ts b/packages/react/src/migrations/update-13-2-3/update-external-emotion-jsx-runtime.spec.ts new file mode 100644 index 00000000000000..3efe7518ac5d76 --- /dev/null +++ b/packages/react/src/migrations/update-13-2-3/update-external-emotion-jsx-runtime.spec.ts @@ -0,0 +1,64 @@ +import { + addProjectConfiguration, + readProjectConfiguration, +} from '@nrwl/devkit'; +import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; + +import { updateExternalEmotionJsxRuntime } from './update-external-emotion-jsx-runtime'; + +describe('updateExternalEmotionJsxRuntime', () => { + it('should update external for Emotion', async () => { + // ARRANGE + const tree = createTreeWithEmptyWorkspace(2); + addProjectConfiguration(tree, 'components', { + root: 'libs/components', + targets: { + build: { + executor: '@nrwl/web:package', + options: { + external: ['@emotion/styled/base', 'react/jsx-runtime'], + }, + }, + }, + }); + tree.write( + 'libs/components/.babelrc', + JSON.stringify({ + presets: [ + [ + '@nrwl/react/babel', + { + runtime: 'automatic', + importSource: '@emotion/react', + }, + ], + ], + plugins: ['@emotion/babel-plugin'], + }) + ); + + // ACT + await updateExternalEmotionJsxRuntime(tree); + + // ASSERT + const { targets } = readProjectConfiguration(tree, 'components'); + expect(targets.build.options.external).toEqual([ + '@emotion/react/jsx-runtime', + ]); + }); + + it('should not fail for projects with no targets', async () => { + // ARRANGE + const tree = createTreeWithEmptyWorkspace(2); + addProjectConfiguration(tree, 'components', { + root: 'apps/components', + }); + + // ACT + await updateExternalEmotionJsxRuntime(tree); + + // ASSERT + const { targets } = readProjectConfiguration(tree, 'components'); + expect(targets).toBeUndefined(); + }); +}); diff --git a/packages/react/src/migrations/update-13-2-3/update-external-emotion-jsx-runtime.ts b/packages/react/src/migrations/update-13-2-3/update-external-emotion-jsx-runtime.ts new file mode 100644 index 00000000000000..5b751239e1d163 --- /dev/null +++ b/packages/react/src/migrations/update-13-2-3/update-external-emotion-jsx-runtime.ts @@ -0,0 +1,58 @@ +import { + Tree, + readJson, + readProjectConfiguration, + updateProjectConfiguration, +} from '@nrwl/devkit'; +import { WebPackageOptions } from '@nrwl/web/src/executors/package/schema'; +import { forEachExecutorOptions } from '@nrwl/workspace/src/utilities/executor-options-utils'; + +export async function updateExternalEmotionJsxRuntime(tree: Tree) { + forEachExecutorOptions( + tree, + '@nrwl/web:package', + (options: any, projectName, targetName, configurationName) => { + const projectConfiguration = readProjectConfiguration(tree, projectName); + + let hasEmotion = false; + const babelrcPath = `${projectConfiguration.root}/.babelrc`; + if (tree.exists(babelrcPath)) { + const babelrc = readJson(tree, babelrcPath); + if (babelrc.presets) { + for (const [idx, preset] of babelrc.presets.entries()) { + if (Array.isArray(preset)) { + if (!preset[0].includes('@nrwl/react/babel')) continue; + const emotionOptions = preset[1]; + hasEmotion = emotionOptions.importSource === '@emotion/react'; + break; + } + } + } + } + + if (hasEmotion) { + const config = configurationName + ? projectConfiguration.targets[targetName].configurations[ + configurationName + ] + : projectConfiguration.targets[targetName].options; + + if (config.external && config.external.length > 0) { + config.external.forEach((value, index) => { + if (value === 'react/jsx-runtime') { + config.external.splice(index, 1, '@emotion/react/jsx-runtime'); + } + }); + config.external.forEach((value, index) => { + if (value === '@emotion/styled/base') { + config.external.splice(index, 1); + } + }); + } + updateProjectConfiguration(tree, projectName, projectConfiguration); + } + } + ); +} + +export default updateExternalEmotionJsxRuntime;