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

Set up experimental builds #17071

Merged
merged 2 commits into from Oct 14, 2019

Conversation

@acdlite
Copy link
Member

acdlite commented Oct 11, 2019

The experimental builds are packaged exactly like builds in the stable release channel: same file structure, entry points, and npm package names. The goal is to match what will eventually be released in stable as closely as possible, but with additional features turned on.

Versioning and Releasing

The experimental builds will be published to the same registry and package names as the stable ones. However, they will be versioned using a separate scheme. Instead of semver versions, experimental releases will receive arbitrary version strings based on their content hashes. The motivation is to thwart attempts to use a version range to match against future experimental releases. The only way to install or depend on an experimental release is to refer to the specific version number.

Building

I did not use the existing feature flag infra to configure the experimental builds. The reason is because feature flags are designed to configure a single package. They're not designed to generate multiple forks of the same package; for each set of feature flags, you must create a separate package configuration.

Instead, I've added a new build dimension called the release channel. By default, builds use the stable channel. There's also an experimental release channel. We have the option to add more in the future.

There are now two dimensions per artifact: build type (production, development, or profiling), and release channel (stable or experimental). These are separate dimensions because they are combinatorial: there are stable and experimental production builds, stable and experimental development builds, and so on.

You can add something to an experimental build by gating on __EXPERIMENTAL__, similar to how we use __DEV__. Anything inside these branches will be excluded from the stable builds. This gives us a low effort way to add experimental behavior in any package without setting up feature flags or configuring a new package.

@sizebot

This comment has been minimized.

Copy link

sizebot commented Oct 11, 2019

ReactDOM: size: 0.0%, gzip: -0.0%

Details of bundled changes.

Comparing: 75955bf...9977c2c

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-dom.profiling.min.js -0.0% -0.0% 119.46 KB 119.41 KB 37.72 KB 37.71 KB NODE_PROFILING
react-dom-server.browser.development.js 0.0% 0.0% 140.06 KB 140.06 KB 36.8 KB 36.8 KB UMD_DEV
ReactDOM-dev.js -0.1% -0.0% 968.85 KB 968.24 KB 215.29 KB 215.23 KB FB_WWW_DEV
react-dom-server.browser.production.min.js 0.0% -0.0% 19.84 KB 19.84 KB 7.37 KB 7.37 KB UMD_PROD
react-dom-unstable-fizz.browser.development.js 0.0% -0.1% 3.78 KB 3.78 KB 1.53 KB 1.53 KB UMD_DEV
react-dom-test-utils.production.min.js 0.0% 0.0% 11.17 KB 11.17 KB 4.14 KB 4.14 KB UMD_PROD
react-dom-unstable-fizz.browser.development.js 0.0% -0.1% 3.61 KB 3.61 KB 1.48 KB 1.48 KB NODE_DEV
react-dom-test-utils.production.min.js 0.0% 0.0% 10.94 KB 10.94 KB 4.08 KB 4.08 KB NODE_PROD
react-dom.development.js -0.0% -0.0% 946.68 KB 946.25 KB 214.41 KB 214.37 KB UMD_DEV
react-dom.production.min.js -0.0% -0.0% 115.69 KB 115.65 KB 37.24 KB 37.23 KB UMD_PROD
react-dom.profiling.min.js -0.0% -0.0% 119.22 KB 119.17 KB 38.35 KB 38.35 KB UMD_PROFILING
react-dom.development.js -0.0% -0.0% 940.75 KB 940.31 KB 212.84 KB 212.8 KB NODE_DEV
react-dom-server.node.development.js 0.0% -0.0% 137.1 KB 137.1 KB 36.02 KB 36.02 KB NODE_DEV
react-dom.production.min.js -0.0% -0.0% 115.81 KB 115.77 KB 36.7 KB 36.69 KB NODE_PROD
react-dom-server.node.production.min.js 0.0% -0.0% 20.17 KB 20.17 KB 7.5 KB 7.5 KB NODE_PROD
ReactDOM-prod.js -0.0% -0.0% 398.09 KB 398.04 KB 72.46 KB 72.45 KB FB_WWW_PROD
ReactDOM-profiling.js -0.0% -0.0% 398.88 KB 398.83 KB 72.97 KB 72.96 KB FB_WWW_PROFILING
react-dom-server.browser.development.js 0.0% -0.0% 135.99 KB 135.99 KB 35.8 KB 35.79 KB NODE_DEV
react-dom-server.browser.production.min.js 0.0% -0.0% 19.76 KB 19.76 KB 7.35 KB 7.35 KB NODE_PROD
ReactDOMServer-prod.js 0.0% 0.0% 48.5 KB 48.5 KB 11.08 KB 11.08 KB FB_WWW_PROD
react-dom-unstable-fizz.node.development.js 0.0% -0.1% 3.87 KB 3.87 KB 1.51 KB 1.51 KB NODE_DEV
react-dom-unstable-native-dependencies.production.min.js 0.0% -0.0% 10.46 KB 10.46 KB 3.57 KB 3.57 KB NODE_PROD
react-dom-unstable-fizz.node.production.min.js 0.0% -0.1% 1.1 KB 1.1 KB 668 B 667 B NODE_PROD

Generated by 🚫 dangerJS against 9977c2c

The method names don't get stripped out of the production bundles
because they are passed as arguments to the error decoder.

Let's just always use the unprefixed APIs in the messages.
@acdlite acdlite force-pushed the acdlite:experimental-release-channel branch from 7687b9e to 8c4854d Oct 12, 2019
The experimental builds are packaged exactly like builds in the stable
release channel: same file structure, entry points, and npm package
names. The goal is to match what will eventually be released in stable
as closely as possible, but with additional features turned on.

Versioning and Releasing
------------------------

The experimental builds will be published to the same registry and
package names as the stable ones. However, they will be versioned using
a separate scheme. Instead of semver versions, experimental releases
will receive arbitrary version strings based on their content hashes.
The motivation is to thwart attempts to use a version range to match
against future experimental releases. The only way to install or depend
on an experimental release is to refer to the specific version number.

Building
--------

I did not use the existing feature flag infra to configure the
experimental builds. The reason is because feature flags are designed
to configure a single package. They're not designed to generate multiple
forks of the same package; for each set of feature flags, you must
create a separate package configuration.

Instead, I've added a new build dimension called the **release
channel**. By default, builds use the **stable** channel. There's
also an **experimental** release channel. We have the option to add more
in the future.

There are now two dimensions per artifact: build type (production,
development, or profiling), and release channel (stable or
experimental). These are separate dimensions because they are
combinatorial: there are stable and experimental production builds,
stable and experimental developmenet builds, and so on.

You can add something to an experimental build by gating on
`__EXPERIMENTAL__`, similar to how we use `__DEV__`. Anything inside
these branches will be excluded from the stable builds.
This gives us a low effort way to add experimental behavior in any
package without setting up feature flags or configuring a new package.
@acdlite acdlite force-pushed the acdlite:experimental-release-channel branch 8 times, most recently from b1b697e to f17702d Oct 12, 2019
@acdlite acdlite marked this pull request as ready for review Oct 13, 2019
@acdlite acdlite force-pushed the acdlite:experimental-release-channel branch from f17702d to 9977c2c Oct 13, 2019
Copy link
Contributor

bvaughn left a comment

No release script changes. Will those be follow up PRs?

@@ -74,6 +100,18 @@ jobs:
- *run_yarn
- run: yarn test --maxWorkers=2

test_source_experimental:

This comment has been minimized.

Copy link
@bvaughn

bvaughn Oct 14, 2019

Contributor

I assume that since we're using parallel containers, this won't actually increase the duration of every CI job? That would not be great.

This comment has been minimized.

Copy link
@acdlite

acdlite Oct 14, 2019

Author Member

The workflows run in parallel, yeah

@@ -682,9 +671,8 @@ function warnIfReactDOMContainerInDEV(container) {
if (__DEV__) {
warningWithoutStack(
!container._reactRootContainer,
'You are calling ReactDOM.%s() on a container that was previously ' +
'You are calling ReactDOM.createRoot() on a container that was previously ' +

This comment has been minimized.

Copy link
@bvaughn

bvaughn Oct 14, 2019

Contributor

I would not expect all fo these conditional names to change, given that we run this test against not-experimental builds as well. Why did they?

This comment has been minimized.

Copy link
@acdlite

acdlite Oct 14, 2019

Author Member

See the first commit.

The method names don't get stripped out of the production bundles
because they are passed as arguments to the error decoder.

Slightly unrelated but I did it this way instead of checking __EXPERIMENTAL__ in the tests. We're probably going to remove the prefixed versions from the stable releases, anyway.

@acdlite

This comment has been minimized.

Copy link
Member Author

acdlite commented Oct 14, 2019

@bvaughn I'll do release script changes in a follow-up. The existing publish script should actually work if you pass the build number in manually. The main thing I want to add is a check to the prepare-stable script that prevents you from publishing an experimental build as stable.

@acdlite acdlite merged commit d364d85 into facebook:master Oct 14, 2019
17 checks passed
17 checks passed
ci/circleci: build Your tests passed on CircleCI!
Details
ci/circleci: build_experimental Your tests passed on CircleCI!
Details
ci/circleci: flow Your tests passed on CircleCI!
Details
ci/circleci: lint Your tests passed on CircleCI!
Details
ci/circleci: lint_build Your tests passed on CircleCI!
Details
ci/circleci: process_artifacts Your tests passed on CircleCI!
Details
ci/circleci: process_artifacts_experimental Your tests passed on CircleCI!
Details
ci/circleci: setup Your tests passed on CircleCI!
Details
ci/circleci: sizebot Your tests passed on CircleCI!
Details
ci/circleci: test_build Your tests passed on CircleCI!
Details
ci/circleci: test_build_devtools Your tests passed on CircleCI!
Details
ci/circleci: test_build_prod Your tests passed on CircleCI!
Details
ci/circleci: test_dom_fixtures Your tests passed on CircleCI!
Details
ci/circleci: test_source Your tests passed on CircleCI!
Details
ci/circleci: test_source_experimental Your tests passed on CircleCI!
Details
ci/circleci: test_source_persistent Your tests passed on CircleCI!
Details
ci/circleci: test_source_prod Your tests passed on CircleCI!
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.