Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(react): update packages #9613

Merged
merged 1 commit into from Mar 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
36 changes: 14 additions & 22 deletions e2e/next/src/next.test.ts
Expand Up @@ -161,21 +161,12 @@ describe('Next.js Applications', () => {
updateFile(
`apps/${appName}/pages/index.tsx`,
`
import React, { useEffect, useState } from 'react';

export const Index = () => {
const [greeting, setGreeting] = useState('');

useEffect(() => {
fetch('/external-api/hello')
.then(r => r.text())
.then(setGreeting);
}, []);

return <>
<h1>{greeting}</h1>
<h2>{process.env.NX_CUSTOM_VAR}</h2>
</>;
import React from 'react';

export const Index = ({ greeting }: any) => {
return (
<p>{process.env.NX_CUSTOM_VAR}</p>
);
};
export default Index;
`
Expand All @@ -185,7 +176,7 @@ describe('Next.js Applications', () => {
`apps/${appName}/pages/api/hello.js`,
`
export default (_req, res) => {
res.status(200).send('Welcome to ${appName}');
res.status(200).send('Welcome');
};
`
);
Expand All @@ -198,9 +189,10 @@ describe('Next.js Applications', () => {
}
);

const data = await getData(port);
expect(data).toContain(`Welcome to ${appName}`);
expect(data).toContain(`test value from a file`);
const apiData = await getData(port, '/external-api/hello');
const pageData = await getData(port, '/');
expect(apiData).toContain(`Welcome`);
expect(pageData).toContain(`test value from a file`);

try {
await promisifiedTreeKill(p.pid, 'SIGKILL');
Expand Down Expand Up @@ -356,7 +348,7 @@ describe('Next.js Applications', () => {
);

const data = await getData(port);
expect(data).toContain(`Welcome to ${appName}`);
expect(data).toContain(`Welcome`);

try {
await promisifiedTreeKill(p.pid, 'SIGKILL');
Expand Down Expand Up @@ -419,9 +411,9 @@ describe('Next.js Applications', () => {
}, 300000);
});

function getData(port: number): Promise<any> {
function getData(port: number, path = ''): Promise<any> {
return new Promise((resolve) => {
http.get(`http://localhost:${port}`, (res) => {
http.get(`http://localhost:${port}${path}`, (res) => {
expect(res.statusCode).toEqual(200);
let data = '';
res.on('data', (chunk) => {
Expand Down
17 changes: 17 additions & 0 deletions packages/next/migrations.json
Expand Up @@ -220,6 +220,23 @@
"alwaysAddToPackageJson": false
}
}
},
"13.10.0": {
"version": "13.10.0-beta.1",
"packages": {
"next": {
"version": "12.1.2",
"alwaysAddToPackageJson": false
},
"eslint-config-next": {
"version": "12.1.2",
"alwaysAddToPackageJson": false
},
"sass": {
"version": "1.49.9",
"alwaysAddToPackageJson": false
}
}
}
}
}
4 changes: 2 additions & 2 deletions packages/next/src/utils/versions.ts
@@ -1,7 +1,7 @@
export const nxVersion = '*';

export const nextVersion = '12.1.0';
export const eslintConfigNextVersion = '12.1.1-canary.3';
export const nextVersion = '12.1.2';
export const eslintConfigNextVersion = '12.1.2';
export const sassVersion = '1.43.2';
export const lessLoader = '10.2.0';
export const stylusLoader = '6.2.0';
Expand Down
29 changes: 29 additions & 0 deletions packages/react-native/migrations.json
Expand Up @@ -440,6 +440,35 @@
"alwaysAddToPackageJson": false
}
}
},
"13.10.0": {
"version": "13.10.0-beta.1",
"packages": {
"react-native": {
"version": "0.67.4",
"alwaysAddToPackageJson": false
},
"metro": {
"version": "0.70.0",
"alwaysAddToPackageJson": false
},
"@types/react": {
"version": "17.0.43",
"alwaysAddToPackageJson": false
},
"metro-react-native-babel-preset": {
"version": "0.70.0",
"alwaysAddToPackageJson": false
},
"@testing-library/react-native": {
"version": "9.1.0",
"alwaysAddToPackageJson": false
},
"@babel/runtime": {
"version": "7.17.8",
"alwaysAddToPackageJson": false
}
}
}
}
}
26 changes: 26 additions & 0 deletions packages/react-native/src/generators/init/init.spec.ts
@@ -1,3 +1,4 @@
import { logger } from '@nrwl/devkit';
import { Tree, readJson, updateJson } from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { reactNativeInitGenerator } from './init';
Expand Down Expand Up @@ -34,6 +35,31 @@ describe('init', () => {
expect(content).toMatch(/# Nested node_modules/);
});

it.each`
version
${'18.0.0'}
${'~18.0.0'}
${'^18.0.0'}
`(
'should warn if React v18 is already installed in workspace',
async ({ version }) => {
const spy = jest.spyOn(logger, 'warn');
spy.mockImplementation(() => {});
updateJson(tree, 'package.json', (json) => {
json.dependencies = {
react: version,
};
return json;
});

await reactNativeInitGenerator(tree, { e2eTestRunner: 'none' });

expect(spy).toHaveBeenCalledWith(expect.stringContaining('incompatible'));

spy.mockRestore();
}
);

describe('defaultCollection', () => {
it('should be set if none was set before', async () => {
await reactNativeInitGenerator(tree, { e2eTestRunner: 'none' });
Expand Down
15 changes: 11 additions & 4 deletions packages/react-native/src/generators/init/init.ts
Expand Up @@ -4,17 +4,16 @@ import {
convertNxGenerator,
detectPackageManager,
formatFiles,
logger,
readJson,
removeDependenciesFromPackageJson,
Tree,
} from '@nrwl/devkit';
import { Schema } from './schema';
import { runTasksInSerial } from '@nrwl/workspace/src/utilities/run-tasks-in-serial';
import { jestInitGenerator } from '@nrwl/jest';
import { detoxInitGenerator } from '@nrwl/detox';
import {
reactVersion,
typesReactVersion,
} from '@nrwl/react/src/utils/versions';
import { typesReactVersion } from '@nrwl/react/src/utils/versions';

import {
babelRuntimeVersion,
Expand All @@ -31,6 +30,7 @@ import {
reactNativeSvgVersion,
reactNativeVersion,
reactTestRendererVersion,
reactVersion,
testingLibraryJestNativeVersion,
testingLibraryReactNativeVersion,
typesReactNativeVersion,
Expand Down Expand Up @@ -65,6 +65,13 @@ export async function reactNativeInitGenerator(host: Tree, schema: Schema) {

export function updateDependencies(host: Tree) {
const isPnpm = detectPackageManager(host.root) === 'pnpm';
const { dependencies = {} } = readJson(host, 'package.json');
// TODO(jack): Remove this once React Native 0.68.0 is out.
if (dependencies['react']?.match(/[\^~]?18/)) {
logger.warn(
`React version ${dependencies['react']} is incompatible with React Native version ${reactNativeVersion}. Nx will downgrade the version to ${reactVersion}.`
);
}
return addDependenciesToPackageJson(
host,
{
Expand Down
15 changes: 10 additions & 5 deletions packages/react-native/src/utils/versions.ts
@@ -1,9 +1,14 @@
export const nxVersion = '*';

export const reactNativeVersion = '0.67.3';
export const reactNativeVersion = '0.67.4';
export const typesReactNativeVersion = '0.67.3';

export const metroVersion = '0.69.1';
export const metroVersion = '0.70.0';

// TODO(jack): Remove this once react-native 0.68.0 is released.
// v18 is only supported on the New Architecture
// See: https://reactnative.dev/blog/2022/03/15/an-update-on-the-new-architecture-rollout
export const reactVersion = '17.0.2';

export const reactNativeCommunityCli = '7.0.1';
export const reactNativeCommunityCliIos = '7.0.1';
Expand All @@ -12,9 +17,9 @@ export const reactNativeCommunityCliAndroid = '7.0.1';
export const reactNativeConfigVersion = '1.4.5';
export const reactNativeAsyncStorageAsyncStorageVersion = '1.16.3';

export const metroReactNativeBabelPresetVersion = '0.69.1';
export const metroReactNativeBabelPresetVersion = '0.70.0';

export const testingLibraryReactNativeVersion = '9.0.0';
export const testingLibraryReactNativeVersion = '9.1.0';
export const testingLibraryJestNativeVersion = '4.0.4';

export const jestReactNativeVersion = '18.0.0';
Expand All @@ -24,4 +29,4 @@ export const reactTestRendererVersion = '17.0.2';
export const reactNativeSvgTransformerVersion = '1.0.0';
export const reactNativeSvgVersion = '12.3.0';

export const babelRuntimeVersion = '7.17.7';
export const babelRuntimeVersion = '7.17.8';
16 changes: 13 additions & 3 deletions packages/react/migrations.json
Expand Up @@ -29,6 +29,12 @@
"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-react-18-13.10.0": {
"cli": "nx",
"version": "13.10.0-beta.0",
"description": "Update to React 18",
"factory": "./src/migrations/update-13-10-0/update-13-10-0"
}
},
"packageJsonUpdates": {
Expand Down Expand Up @@ -268,12 +274,16 @@
"version": "5.3.5",
"alwaysAddToPackageJson": false
},
"eslint-plugin-react": {
"version": "7.29.4",
"alwaysAddToPackageJson": false
},
"styled-jsx": {
"version": "5.0.1",
"version": "5.0.2",
"alwaysAddToPackageJson": false
},
"eslint-plugin-react": {
"version": "7.29.4",
"eslint-plugin-react-hooks": {
"version": "4.4.0",
"alwaysAddToPackageJson": false
}
}
Expand Down
@@ -0,0 +1,50 @@
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { writeJson, readJson, Tree } from '@nrwl/devkit';
import migrate from './update-13-10-0';

describe('Update tsconfig for React apps', () => {
let tree: Tree;

beforeEach(() => {
tree = createTreeWithEmptyWorkspace();
});

it('should update to React 18 if React Native is not installed', async () => {
writeJson(tree, 'package.json', {
dependencies: {
react: '17.0.2',
},
});

const installTask = await migrate(tree);
expect(installTask).toBeDefined();
});

it('should update to React 18 if React Native 0.68.0-rc.4 is installed', async () => {
writeJson(tree, 'package.json', {
dependencies: {
react: '17.0.2',
'react-native': '0.68.0-rc.4',
},
});

await migrate(tree);

const installTask = await migrate(tree);
expect(installTask).toBeDefined();
});

it('should skip update to React 18 if React Native 0.67.0 is installed', async () => {
writeJson(tree, 'package.json', {
dependencies: {
react: '17.0.2',
'react-native': '0.67.0',
},
});

await migrate(tree);

const installTask = await migrate(tree);
expect(installTask).not.toBeDefined();
});
});
34 changes: 34 additions & 0 deletions packages/react/src/migrations/update-13-10-0/update-13-10-0.ts
@@ -0,0 +1,34 @@
import {
addDependenciesToPackageJson,
readJson,
logger,
Tree,
} from '@nrwl/devkit';

// Putting this here because React Native 0.67 is incompatible with React 18.
// Waiting for 0.68 to come out with support for React 18.
// TODO(jack): For Nx 14 let's add another migration for React 18 in migrations.json because by then React Native 0.68.0 should be released.
export async function updateToReact18(host: Tree) {
const { dependencies } = readJson(host, 'package.json');
if (
dependencies['react-native'] &&
!dependencies['react-native'].match(/[\^~]?0.68/)
) {
logger.info(
`React Native ${dependencies['react-native']} is incompatible with React 18. Skipping update until React Native 0.68.0 is released.`
);
} else {
return addDependenciesToPackageJson(
host,
{
react: '18.0.0',
'react-dom': '18.0.0',
'react-is': '18.0.0',
'react-test-renderer': '18.0.0',
},
{}
);
}
}

export default updateToReact18;