From 54bfab5d6d9e0e313fbedbe76979c59470fbe140 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Mon, 10 Sep 2018 13:14:34 -0700 Subject: [PATCH 1/2] Release script updates private package dependencies also (#13612) --- .../build-commands/update-package-versions.js | 13 +++++++++++-- scripts/release/build.js | 11 +++++++++-- scripts/release/utils.js | 18 ++++++++++++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/scripts/release/build-commands/update-package-versions.js b/scripts/release/build-commands/update-package-versions.js index 60e98fbc2f282..467c20791b914 100644 --- a/scripts/release/build-commands/update-package-versions.js +++ b/scripts/release/build-commands/update-package-versions.js @@ -58,8 +58,11 @@ const update = async ({cwd, dry, packages, version}) => { const json = await readJson(path); const prerelease = semver.prerelease(version); - // Unstable package version. - json.version = getNextVersion(json.version, version); + // If this is a package we publish directly to NPM, update its version. + // Skip ones that we don't directly publish though (e.g. react-native-renderer). + if (json.private !== true) { + json.version = getNextVersion(json.version, version); + } if (project === 'react') { // Update inter-package dependencies as well. @@ -107,6 +110,12 @@ const update = async ({cwd, dry, packages, version}) => { Object.keys(json.dependencies).forEach(dependency => { if (packages.indexOf(dependency) >= 0) { const prevVersion = json.dependencies[dependency]; + + // Special case to handle e.g. react-noop-renderer + if (prevVersion === '*') { + return; + } + const nextVersion = getNextVersion( prevVersion.replace('^', ''), version diff --git a/scripts/release/build.js b/scripts/release/build.js index dedce1c267416..9288af14bf27d 100755 --- a/scripts/release/build.js +++ b/scripts/release/build.js @@ -8,7 +8,7 @@ const {exec} = require('child_process'); const run = async () => { const chalk = require('chalk'); const logUpdate = require('log-update'); - const {getPublicPackages} = require('./utils'); + const {getPublicPackages, getPackages} = require('./utils'); const addGitTag = require('./build-commands/add-git-tag'); const buildArtifacts = require('./build-commands/build-artifacts'); @@ -31,6 +31,7 @@ const run = async () => { try { const params = parseBuildParameters(); params.packages = getPublicPackages(); + await checkEnvironmentVariables(params); await validateVersion(params); await checkUncommittedChanges(params); @@ -41,7 +42,13 @@ const run = async () => { await checkPackageDependencies(params); await updateYarnDependencies(params); await runAutomatedTests(params); - await updatePackageVersions(params); + // Also update NPM dependencies for private packages (e.g. react-native-renderer) + // Even though we don't publish these to NPM, + // mismatching dependencies can cause `yarn install` to install duplicate packages. + await updatePackageVersions({ + ...params, + packages: getPackages(), + }); await updateNoopRendererDependencies(params); await buildArtifacts(params); await runAutomatedBundleTests(params); diff --git a/scripts/release/utils.js b/scripts/release/utils.js index d5be8b1a5a503..2a9ecff5e895c 100644 --- a/scripts/release/utils.js +++ b/scripts/release/utils.js @@ -23,6 +23,23 @@ const execUnlessDry = async (command, {cwd, dry}) => { } }; +const getPackages = () => { + const packagesRoot = join(__dirname, '..', '..', 'packages'); + + return readdirSync(packagesRoot).filter(dir => { + const packagePath = join(packagesRoot, dir, 'package.json'); + + if (dir.charAt(0) !== '.' && statSync(packagePath).isFile()) { + const packageJSON = JSON.parse(readFileSync(packagePath)); + + // Skip packages like "shared" and "events" that shouldn't be updated. + return packageJSON.version !== '0.0.0'; + } + + return false; + }); +}; + const getPublicPackages = () => { const packagesRoot = join(__dirname, '..', '..', 'packages'); @@ -99,6 +116,7 @@ const runYarnTask = async (cwd, task, errorMessage) => { module.exports = { execRead, execUnlessDry, + getPackages, getPublicPackages, getUnexecutedCommands, logPromise, From f6fb03edffcc5918ad2f37ed45bdc7c0c3b3d199 Mon Sep 17 00:00:00 2001 From: Nathan Hunzaker Date: Mon, 10 Sep 2018 14:04:14 -0700 Subject: [PATCH 2/2] Hydration DOM Fixture (#13521) * Add home component. Async load fixtures. This commit adds a homepage to the DOM fixtures that includes browser testing information and asynchronously loads fixtures. This should make it easier to find DOM testing information and keep the payload size in check as we add more components to the fixtures. * Adds experimental hydration fixture This commit adds a first pass at a fixture that makes it easier to debug the process of hydrating static markup. This is not complete: 1. It needs to be verified across multiple browsers 2. It needs to render with the current version of react Still, it at least demonstrates the idea. A fixture like this will also be helpful for debugging change events for hydrated inputs, which presently do not fire if the user changes an input's text before hydration. * Tweak select width * Manually join extra attributes in warning This prevents a bug where Chrome reports `Array(n)` where `n` is the size of the array. * Transform with buble * Eliminate dependencies * Pull in react-live for better editing * Handle encoding errors, pass react version * Load the correct version of React * Tweaks * Revert style change * Revert warning update * Properly handle script errors. Fix dom-server CDN loading * Fix 15.x releases * Use postMessage to reduce latency, support older browsers This commit makes a few tweaks to support older browsers and updates the code transition process to use window.postMessage. This avoids loading React on every single change. * Fix fixture renamespacing bug * Gracefully fallback to textarea in React 14 * Replace buble with babel, react-live with codemirror * Simplify layout to resolve production code-mirror issues * Tweak height rules for code-mirror * Update theme to paraiso * Format Code.js * Adjust viewport to fix CodeMirror resize issue in production build * Eliminate react-code-mirror * Improve error state. Make full stack collapsable * Add link to license in codemirror stylesheet * Make code example more concise * Replace "Hydrate" with "Auto-hydrate" for clarity * Remove border below hydration header * Rename query function in render.js * Use Function(code) to evaluate hydration fixture For clarity, and so that the Fixture component does not need to be assigned to the window, this commit changes the way code is executed such that it evaluates using a Function constructor. * Extend hydration fixture to fill width. Design adjustments This commit extends the hydration fixture such that it takes up the full screen view. To accomplish this, the container that wraps all fixtures has been moved to the FixtureSet component, utilized by all other fixtures. * Improve error scroll state * Lazy load CodeMirror together before executing This commit fixes an issue where CodeMirror wouldn't layout correctly in production builds because the editor executes before the stylesheet loaded. CodeMirror needs layout information, and was rendering off-screen without correct CSS layout measurements. * Fix indentation on error message * Do not highlight errors from Babel. Add setPrototypeOf polyfill This commit fixes an error in Safari 7.1 where Chalk highlighted Babel errors caused a crash when setPrototypeOf was called within the library. This is also an issue on IE9, however this fix does not resolve issues in that browser. * Increase resilience to bad errors in Hydration fixture - Reverts highlighting change. Polyfilling Safari 7.1 is sufficient - Do not render a details tag in IE9 --- fixtures/dom/.gitignore | 1 + fixtures/dom/package.json | 4 +- fixtures/dom/public/renderer.html | 86 +++++++++++ fixtures/dom/public/renderer.js | 141 ++++++++++++++++++ fixtures/dom/src/components/App.js | 4 +- fixtures/dom/src/components/FixtureSet.js | 2 +- fixtures/dom/src/components/Header.js | 3 +- fixtures/dom/src/components/fixtures/home.js | 2 +- .../src/components/fixtures/hydration/Code.js | 85 +++++++++++ .../fixtures/hydration/code-transformer.js | 18 +++ .../hydration/codemirror-paraiso-dark.css | 38 +++++ .../src/components/fixtures/hydration/data.js | 22 +++ .../fixtures/hydration/hydration.css | 68 +++++++++ .../components/fixtures/hydration/index.js | 109 ++++++++++++++ .../components/fixtures/range-inputs/index.js | 36 +++-- fixtures/dom/src/polyfills.js | 1 + fixtures/dom/src/react-loader.js | 31 ++-- fixtures/dom/src/style.css | 2 - fixtures/dom/yarn.lock | 8 + 19 files changed, 628 insertions(+), 33 deletions(-) create mode 100644 fixtures/dom/public/renderer.html create mode 100644 fixtures/dom/public/renderer.js create mode 100644 fixtures/dom/src/components/fixtures/hydration/Code.js create mode 100644 fixtures/dom/src/components/fixtures/hydration/code-transformer.js create mode 100644 fixtures/dom/src/components/fixtures/hydration/codemirror-paraiso-dark.css create mode 100644 fixtures/dom/src/components/fixtures/hydration/data.js create mode 100644 fixtures/dom/src/components/fixtures/hydration/hydration.css create mode 100644 fixtures/dom/src/components/fixtures/hydration/index.js diff --git a/fixtures/dom/.gitignore b/fixtures/dom/.gitignore index bcc245d36a251..bffad9e24b6de 100644 --- a/fixtures/dom/.gitignore +++ b/fixtures/dom/.gitignore @@ -10,6 +10,7 @@ coverage build public/react.development.js public/react-dom.development.js +public/react-dom-server.browser.development.js # misc .DS_Store diff --git a/fixtures/dom/package.json b/fixtures/dom/package.json index ef92dbfe50e4c..0f2959684a65b 100644 --- a/fixtures/dom/package.json +++ b/fixtures/dom/package.json @@ -6,7 +6,9 @@ "react-scripts": "^1.0.11" }, "dependencies": { + "@babel/standalone": "^7.0.0", "classnames": "^2.2.5", + "codemirror": "^5.40.0", "core-js": "^2.4.1", "prop-types": "^15.6.0", "query-string": "^4.2.3", @@ -16,7 +18,7 @@ }, "scripts": { "start": "react-scripts start", - "prestart": "cp ../../build/dist/react.development.js public/ && cp ../../build/dist/react-dom.development.js public/", + "prestart": "cp ../../build/dist/react.development.js ../../build/dist/react-dom.development.js ../../build/dist/react-dom-server.browser.development.js public/", "build": "react-scripts build && cp build/index.html build/200.html", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" diff --git a/fixtures/dom/public/renderer.html b/fixtures/dom/public/renderer.html new file mode 100644 index 0000000000000..3852dd952f2b9 --- /dev/null +++ b/fixtures/dom/public/renderer.html @@ -0,0 +1,86 @@ + + + + + + Renderer + + + +
+

Loading

+ + + + + +
+ +
+ + + + + diff --git a/fixtures/dom/public/renderer.js b/fixtures/dom/public/renderer.js new file mode 100644 index 0000000000000..542580a07318d --- /dev/null +++ b/fixtures/dom/public/renderer.js @@ -0,0 +1,141 @@ +/** + * Supports render.html, a piece of the hydration fixture. See /hydration + */ + +'use strict'; + +(function() { + var Fixture = null; + var output = document.getElementById('output'); + var status = document.getElementById('status'); + var hydrate = document.getElementById('hydrate'); + var reload = document.getElementById('reload'); + var renders = 0; + var failed = false; + + function getQueryParam(key) { + var pattern = new RegExp(key + '=([^&]+)(&|$)'); + var matches = window.location.search.match(pattern); + + if (matches) { + return decodeURIComponent(matches[1]); + } + + handleError(new Error('No key found for' + key)); + } + + function getBooleanQueryParam(key) { + return getQueryParam(key) === 'true'; + } + + function setStatus(label) { + status.innerHTML = label; + } + + function prerender() { + setStatus('Generating markup'); + + output.innerHTML = ReactDOMServer.renderToString( + React.createElement(Fixture) + ); + + setStatus('Markup only (No React)'); + } + + function render() { + setStatus('Hydrating'); + + if (ReactDOM.hydrate) { + ReactDOM.hydrate(React.createElement(Fixture), output); + } else { + ReactDOM.render(React.createElement(Fixture), output); + } + + setStatus(renders > 0 ? 'Re-rendered (' + renders + 'x)' : 'Hydrated'); + renders += 1; + hydrate.innerHTML = 'Re-render'; + } + + function handleError(error) { + console.log(error); + failed = true; + setStatus('Javascript Error'); + output.innerHTML = error; + } + + function loadScript(src) { + return new Promise(function(resolve, reject) { + var script = document.createElement('script'); + script.async = true; + script.src = src; + + script.onload = resolve; + script.onerror = function(error) { + reject(new Error('Unable to load ' + src)); + }; + + document.body.appendChild(script); + }); + } + + function injectFixture(src) { + Fixture = new Function(src + '\nreturn Fixture;')(); + + if (typeof Fixture === 'undefined') { + setStatus('Failed'); + output.innerHTML = 'Please name your root component "Fixture"'; + } else { + prerender(); + + if (getBooleanQueryParam('hydrate')) { + render(); + } + } + } + + function reloadFixture(code) { + renders = 0; + ReactDOM.unmountComponentAtNode(output); + injectFixture(code); + } + + window.onerror = handleError; + + reload.onclick = function() { + window.location.reload(); + }; + + hydrate.onclick = render; + + loadScript(getQueryParam('reactPath')) + .then(function() { + return getBooleanQueryParam('needsReactDOM') + ? loadScript(getQueryParam('reactDOMPath')) + : null; + }) + .then(function() { + return loadScript(getQueryParam('reactDOMServerPath')); + }) + .then(function() { + if (failed) { + return; + } + + window.addEventListener('message', function(event) { + var data = JSON.parse(event.data); + + switch (data.type) { + case 'code': + reloadFixture(data.payload); + break; + default: + throw new Error( + 'Renderer Error: Unrecognized message "' + data.type + '"' + ); + } + }); + + window.parent.postMessage(JSON.stringify({type: 'ready'}), '*'); + }) + .catch(handleError); +})(); diff --git a/fixtures/dom/src/components/App.js b/fixtures/dom/src/components/App.js index 084283733f8b0..5b0de92e074a0 100644 --- a/fixtures/dom/src/components/App.js +++ b/fixtures/dom/src/components/App.js @@ -8,9 +8,7 @@ function App() { return (
-
- -
+
); } diff --git a/fixtures/dom/src/components/FixtureSet.js b/fixtures/dom/src/components/FixtureSet.js index ee427043687ae..589b1c7bc3cb4 100644 --- a/fixtures/dom/src/components/FixtureSet.js +++ b/fixtures/dom/src/components/FixtureSet.js @@ -11,7 +11,7 @@ class FixtureSet extends React.Component { const {title, description, children} = this.props; return ( -
+

{title}

{description &&

{description}

} diff --git a/fixtures/dom/src/components/Header.js b/fixtures/dom/src/components/Header.js index de71a7dca606b..9671d2c1d9af7 100644 --- a/fixtures/dom/src/components/Header.js +++ b/fixtures/dom/src/components/Header.js @@ -48,7 +48,8 @@ class Header extends React.Component {