mirror of
https://github.com/zebrajr/react.git
synced 2026-01-15 12:15:22 +00:00
React version field should match package.json (#24445)
The `version` field exported by the React package currently corresponds to the `@next` release for that build. This updates the build script to output the same version that is used in the package.json file. It works by doing a find-and-replace of the React version after the build has completed. This is a bit weird but it saves us from having to build the `@next` and `@latest` releases separately; they are identical except for the version numbers.
This commit is contained in:
26
packages/react/src/__tests__/ReactVersion-test.js
Normal file
26
packages/react/src/__tests__/ReactVersion-test.js
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @emails react-core
|
||||
* @jest-environment node
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// NOTE: Intentionally using the dynamic version of the `gate` pragma to opt out
|
||||
// the negative test behavior. If this test happens to pass when running
|
||||
// against files source, that's fine. But all we care about is the behavior of
|
||||
// the build artifacts.
|
||||
// TODO: The experimental builds have a different version at runtime than
|
||||
// the package.json because DevTools uses it for feature detection. Consider
|
||||
// some other way of handling that.
|
||||
test('ReactVersion matches package.json', () => {
|
||||
if (gate(flags => flags.build && flags.stable && !flags.www)) {
|
||||
const React = require('react');
|
||||
const packageJSON = require('react/package.json');
|
||||
expect(React.version).toBe(packageJSON.version);
|
||||
}
|
||||
});
|
||||
@@ -38,6 +38,20 @@ if (dateString.startsWith("'")) {
|
||||
dateString = dateString.substr(1, 8);
|
||||
}
|
||||
|
||||
// Build the artifacts using a placeholder React version. We'll then do a string
|
||||
// replace to swap it with the correct version per release channel.
|
||||
//
|
||||
// The placeholder version is the same format that the "next" channel uses
|
||||
const PLACEHOLDER_REACT_VERSION =
|
||||
ReactVersion + '-' + nextChannelLabel + '-' + sha + '-' + dateString;
|
||||
|
||||
// TODO: We should inject the React version using a build-time parameter
|
||||
// instead of overwriting the source files.
|
||||
fs.writeFileSync(
|
||||
'./packages/shared/ReactVersion.js',
|
||||
`export default '${PLACEHOLDER_REACT_VERSION}';\n`
|
||||
);
|
||||
|
||||
if (process.env.CIRCLE_NODE_TOTAL) {
|
||||
// In CI, we use multiple concurrent processes. Allocate half the processes to
|
||||
// build the stable channel, and the other half for experimental. Override
|
||||
@@ -48,33 +62,21 @@ if (process.env.CIRCLE_NODE_TOTAL) {
|
||||
if (index < halfTotal) {
|
||||
const nodeTotal = halfTotal;
|
||||
const nodeIndex = index;
|
||||
updateTheReactVersionThatDevToolsReads(
|
||||
ReactVersion + '-' + sha + '-' + dateString
|
||||
);
|
||||
buildForChannel('stable', nodeTotal, nodeIndex);
|
||||
processStable('./build');
|
||||
} else {
|
||||
const nodeTotal = total - halfTotal;
|
||||
const nodeIndex = index - halfTotal;
|
||||
updateTheReactVersionThatDevToolsReads(
|
||||
ReactVersion + '-experimental-' + sha + '-' + dateString
|
||||
);
|
||||
buildForChannel('experimental', nodeTotal, nodeIndex);
|
||||
processExperimental('./build');
|
||||
}
|
||||
} else {
|
||||
// Running locally, no concurrency. Move each channel's build artifacts into
|
||||
// a temporary directory so that they don't conflict.
|
||||
updateTheReactVersionThatDevToolsReads(
|
||||
ReactVersion + '-' + sha + '-' + dateString
|
||||
);
|
||||
buildForChannel('stable', '', '');
|
||||
const stableDir = tmp.dirSync().name;
|
||||
crossDeviceRenameSync('./build', stableDir);
|
||||
processStable(stableDir);
|
||||
updateTheReactVersionThatDevToolsReads(
|
||||
ReactVersion + '-experimental-' + sha + '-' + dateString
|
||||
);
|
||||
buildForChannel('experimental', '', '');
|
||||
const experimentalDir = tmp.dirSync().name;
|
||||
crossDeviceRenameSync('./build', experimentalDir);
|
||||
@@ -129,6 +131,10 @@ function processStable(buildDir) {
|
||||
true
|
||||
);
|
||||
fs.renameSync(buildDir + '/node_modules', buildDir + '/oss-stable');
|
||||
updatePlaceholderReactVersionInCompiledArtifacts(
|
||||
buildDir + '/oss-stable',
|
||||
ReactVersion + '-' + nextChannelLabel + '-' + sha + '-' + dateString
|
||||
);
|
||||
|
||||
// Now do the semver ones
|
||||
const semverVersionsMap = new Map();
|
||||
@@ -142,6 +148,10 @@ function processStable(buildDir) {
|
||||
defaultVersionIfNotFound,
|
||||
false
|
||||
);
|
||||
updatePlaceholderReactVersionInCompiledArtifacts(
|
||||
buildDir + '/oss-stable-semver',
|
||||
ReactVersion
|
||||
);
|
||||
}
|
||||
|
||||
if (fs.existsSync(buildDir + '/facebook-www')) {
|
||||
@@ -152,6 +162,10 @@ function processStable(buildDir) {
|
||||
fs.renameSync(filePath, filePath.replace('.js', '.classic.js'));
|
||||
}
|
||||
}
|
||||
updatePlaceholderReactVersionInCompiledArtifacts(
|
||||
buildDir + '/facebook-www',
|
||||
ReactVersion + '-www-classic-' + sha + '-' + dateString
|
||||
);
|
||||
}
|
||||
|
||||
if (fs.existsSync(buildDir + '/sizes')) {
|
||||
@@ -162,7 +176,7 @@ function processStable(buildDir) {
|
||||
function processExperimental(buildDir, version) {
|
||||
if (fs.existsSync(buildDir + '/node_modules')) {
|
||||
const defaultVersionIfNotFound =
|
||||
'0.0.0' + '-' + 'experimental' + '-' + sha + '-' + dateString;
|
||||
'0.0.0' + '-experimental-' + sha + '-' + dateString;
|
||||
const versionsMap = new Map();
|
||||
for (const moduleName in stablePackages) {
|
||||
versionsMap.set(moduleName, defaultVersionIfNotFound);
|
||||
@@ -177,6 +191,13 @@ function processExperimental(buildDir, version) {
|
||||
true
|
||||
);
|
||||
fs.renameSync(buildDir + '/node_modules', buildDir + '/oss-experimental');
|
||||
updatePlaceholderReactVersionInCompiledArtifacts(
|
||||
buildDir + '/oss-experimental',
|
||||
// TODO: The npm version for experimental releases does not include the
|
||||
// React version, but the runtime version does so that DevTools can do
|
||||
// feature detection. Decide what to do about this later.
|
||||
ReactVersion + '-experimental-' + sha + '-' + dateString
|
||||
);
|
||||
}
|
||||
|
||||
if (fs.existsSync(buildDir + '/facebook-www')) {
|
||||
@@ -187,6 +208,10 @@ function processExperimental(buildDir, version) {
|
||||
fs.renameSync(filePath, filePath.replace('.js', '.modern.js'));
|
||||
}
|
||||
}
|
||||
updatePlaceholderReactVersionInCompiledArtifacts(
|
||||
buildDir + '/facebook-www',
|
||||
ReactVersion + '-www-modern-' + sha + '-' + dateString
|
||||
);
|
||||
}
|
||||
|
||||
if (fs.existsSync(buildDir + '/sizes')) {
|
||||
@@ -278,14 +303,32 @@ function updatePackageVersions(
|
||||
}
|
||||
}
|
||||
|
||||
function updateTheReactVersionThatDevToolsReads(version) {
|
||||
// Overwrite the ReactVersion module before the build script runs so that it
|
||||
// is included in the final bundles. This only runs in CI, so it's fine to
|
||||
// edit the source file.
|
||||
fs.writeFileSync(
|
||||
'./packages/shared/ReactVersion.js',
|
||||
`export default '${version}';\n`
|
||||
);
|
||||
function updatePlaceholderReactVersionInCompiledArtifacts(
|
||||
artifactsDirectory,
|
||||
newVersion
|
||||
) {
|
||||
// Update the version of React in the compiled artifacts by searching for
|
||||
// the placeholder string and replacing it with a new one.
|
||||
const artifactFilenames = String(
|
||||
spawnSync('grep', [
|
||||
'-lr',
|
||||
PLACEHOLDER_REACT_VERSION,
|
||||
'--',
|
||||
artifactsDirectory,
|
||||
]).stdout
|
||||
)
|
||||
.trim()
|
||||
.split('\n')
|
||||
.filter(filename => filename.endsWith('.js'));
|
||||
|
||||
for (const artifactFilename of artifactFilenames) {
|
||||
const originalText = fs.readFileSync(artifactFilename, 'utf8');
|
||||
const replacedText = originalText.replace(
|
||||
PLACEHOLDER_REACT_VERSION,
|
||||
newVersion
|
||||
);
|
||||
fs.writeFileSync(artifactFilename, replacedText);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user