Compare commits
1 Commits
main
...
ty-selecti
| Author | SHA1 | Date |
|---|---|---|
|
|
c8a573b137 |
|
|
@ -7,11 +7,40 @@ aliases:
|
|||
- &environment
|
||||
TZ: /usr/share/zoneinfo/America/Los_Angeles
|
||||
|
||||
- &restore_yarn_cache
|
||||
restore_cache:
|
||||
name: Restore yarn cache
|
||||
keys:
|
||||
- v1-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}
|
||||
- v1-yarn_cache-{{ arch }}-
|
||||
- v1-yarn_cache-
|
||||
|
||||
- &yarn_install
|
||||
run:
|
||||
name: Install dependencies
|
||||
command: yarn install --frozen-lockfile --cache-folder ~/.cache/yarn
|
||||
|
||||
- &yarn_install_retry
|
||||
run:
|
||||
name: Install dependencies (retry)
|
||||
when: on_fail
|
||||
command: yarn install --frozen-lockfile --cache-folder ~/.cache/yarn
|
||||
|
||||
- &save_yarn_cache
|
||||
save_cache:
|
||||
name: Save yarn cache
|
||||
key: v1-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}
|
||||
paths:
|
||||
- ~/.cache/yarn
|
||||
|
||||
- &restore_yarn_cache_fixtures_dom
|
||||
restore_cache:
|
||||
name: Restore yarn cache for fixtures/dom
|
||||
keys:
|
||||
- v2-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}-fixtures/dom
|
||||
- v1-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}-fixtures/dom
|
||||
- v1-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}
|
||||
- v1-yarn_cache-{{ arch }}-
|
||||
- v1-yarn_cache-
|
||||
|
||||
- &yarn_install_fixtures_dom
|
||||
run:
|
||||
|
|
@ -29,36 +58,51 @@ aliases:
|
|||
- &save_yarn_cache_fixtures_dom
|
||||
save_cache:
|
||||
name: Save yarn cache for fixtures/dom
|
||||
key: v2-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}-fixtures/dom
|
||||
key: v1-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}-fixtures/dom
|
||||
paths:
|
||||
- ~/.cache/yarn
|
||||
|
||||
- &save_node_modules
|
||||
save_cache:
|
||||
name: Save node_modules cache
|
||||
# Cache only for the current revision to prevent cache injections from
|
||||
# malicious PRs.
|
||||
key: v1-node_modules-{{ arch }}-{{ .Revision }}
|
||||
paths:
|
||||
- node_modules
|
||||
- packages/eslint-plugin-react-hooks/node_modules
|
||||
- packages/react-art/node_modules
|
||||
- packages/react-client/node_modules
|
||||
- packages/react-devtools-core/node_modules
|
||||
- packages/react-devtools-extensions/node_modules
|
||||
- packages/react-devtools-inline/node_modules
|
||||
- packages/react-devtools-shared/node_modules
|
||||
- packages/react-devtools-shell/node_modules
|
||||
- packages/react-devtools-timeline/node_modules
|
||||
- packages/react-devtools/node_modules
|
||||
- packages/react-dom/node_modules
|
||||
- packages/react-interactions/node_modules
|
||||
- packages/react-native-renderer/node_modules
|
||||
- packages/react-reconciler/node_modules
|
||||
- packages/react-server-dom-relay/node_modules
|
||||
- packages/react-server-dom-webpack/node_modules
|
||||
- packages/react-server-native-relay/node_modules
|
||||
- packages/react-server/node_modules
|
||||
- packages/react-test-renderer/node_modules
|
||||
- packages/react/node_modules
|
||||
- packages/scheduler/node_modules
|
||||
|
||||
- &restore_node_modules
|
||||
restore_cache:
|
||||
name: Restore node_modules cache
|
||||
keys:
|
||||
- v1-node_modules-{{ arch }}-{{ .Revision }}
|
||||
|
||||
- &TEST_PARALLELISM 20
|
||||
|
||||
- &attach_workspace
|
||||
at: build
|
||||
|
||||
commands:
|
||||
setup_node_modules:
|
||||
description: "Restore node_modules"
|
||||
steps:
|
||||
- restore_cache:
|
||||
name: Restore yarn cache
|
||||
keys:
|
||||
- v2-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: |
|
||||
yarn install --frozen-lockfile --cache-folder ~/.cache/yarn
|
||||
if [ $? -ne 0 ]; then
|
||||
yarn install --frozen-lockfile --cache-folder ~/.cache/yarn
|
||||
fi
|
||||
- save_cache:
|
||||
name: Save yarn cache
|
||||
key: v2-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}
|
||||
paths:
|
||||
- ~/.cache/yarn
|
||||
|
||||
# The CircleCI API doesn't yet support triggering a specific workflow, but it
|
||||
# does support triggering a pipeline. So as a workaround you can triggger the
|
||||
# entire pipeline and use parameters to disable everything except the workflow
|
||||
|
|
@ -71,13 +115,28 @@ parameters:
|
|||
default: ''
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
docker: *docker
|
||||
environment: *environment
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: NodeJS Version
|
||||
command: node --version
|
||||
- *restore_yarn_cache
|
||||
- *restore_node_modules
|
||||
- *yarn_install
|
||||
- *yarn_install_retry
|
||||
- *save_yarn_cache
|
||||
- *save_node_modules
|
||||
|
||||
yarn_lint:
|
||||
docker: *docker
|
||||
environment: *environment
|
||||
|
||||
steps:
|
||||
- checkout
|
||||
- setup_node_modules
|
||||
- *restore_node_modules
|
||||
- run: node ./scripts/prettier/index
|
||||
- run: node ./scripts/tasks/eslint
|
||||
- run: ./scripts/circleci/check_license.sh
|
||||
|
|
@ -91,7 +150,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- checkout
|
||||
- setup_node_modules
|
||||
- *restore_node_modules
|
||||
- run: node ./scripts/tasks/flow-ci
|
||||
|
||||
scrape_warning_messages:
|
||||
|
|
@ -100,7 +159,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- checkout
|
||||
- setup_node_modules
|
||||
- *restore_node_modules
|
||||
- run:
|
||||
command: |
|
||||
mkdir -p ./build
|
||||
|
|
@ -110,14 +169,14 @@ jobs:
|
|||
paths:
|
||||
- build
|
||||
|
||||
yarn_build:
|
||||
yarn_build_combined:
|
||||
docker: *docker
|
||||
environment: *environment
|
||||
parallelism: 40
|
||||
steps:
|
||||
- checkout
|
||||
- setup_node_modules
|
||||
- run: yarn build
|
||||
- *restore_node_modules
|
||||
- run: yarn build-combined
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths:
|
||||
|
|
@ -131,7 +190,7 @@ jobs:
|
|||
type: string
|
||||
steps:
|
||||
- checkout
|
||||
- setup_node_modules
|
||||
- *restore_node_modules
|
||||
- run:
|
||||
name: Download artifacts for revision
|
||||
command: |
|
||||
|
|
@ -148,36 +207,14 @@ jobs:
|
|||
environment: *environment
|
||||
steps:
|
||||
- checkout
|
||||
- setup_node_modules
|
||||
- *restore_node_modules
|
||||
- run:
|
||||
name: Download artifacts for base revision
|
||||
# TODO: The download-experimental-build.js script works by fetching
|
||||
# artifacts from CI. CircleCI recently updated this endpoint to
|
||||
# require an auth token. This is a problem for PR branches, where
|
||||
# sizebot needs to run, because we don't want to leak the token to
|
||||
# arbitrary code written by an outside contributor.
|
||||
#
|
||||
# This only affects PR branches. CI workflows that run on the main
|
||||
# branch are allowed to access environment variables, because only those
|
||||
# with push access can land code in main.
|
||||
#
|
||||
# As a temporary workaround, we'll fetch the assets from a mirror.
|
||||
# Need to figure out a longer term solution for this.
|
||||
#
|
||||
# Original code
|
||||
#
|
||||
# command: |
|
||||
# git fetch origin main
|
||||
# cd ./scripts/release && yarn && cd ../../
|
||||
# scripts/release/download-experimental-build.js --commit=$(git merge-base HEAD origin/main) --allowBrokenCI
|
||||
# mv ./build ./base-build
|
||||
#
|
||||
# Workaround. Fetch the artifacts from react-builds.vercel.app. This
|
||||
# is the same app that hosts the sizebot diff previews.
|
||||
command: |
|
||||
curl -L --retry 60 --retry-delay 10 --retry-max-time 600 https://react-builds.vercel.app/api/commits/$(git merge-base HEAD origin/main)/artifacts/build.tgz | tar -xz
|
||||
git fetch origin main
|
||||
cd ./scripts/release && yarn && cd ../../
|
||||
scripts/release/download-experimental-build.js --commit=$(git merge-base HEAD origin/main) --allowBrokenCI
|
||||
mv ./build ./base-build
|
||||
|
||||
- run:
|
||||
# TODO: The `download-experimental-build` script copies the npm
|
||||
# packages into the `node_modules` directory. This is a historical
|
||||
|
|
@ -198,7 +235,7 @@ jobs:
|
|||
- checkout
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- setup_node_modules
|
||||
- *restore_node_modules
|
||||
- run: echo "<< pipeline.git.revision >>" >> build/COMMIT_SHA
|
||||
# Compress build directory into a single tarball for easy download
|
||||
- run: tar -zcvf ./build.tgz ./build
|
||||
|
|
@ -217,7 +254,7 @@ jobs:
|
|||
- attach_workspace:
|
||||
at: .
|
||||
- run: echo "<< pipeline.git.revision >>" >> build/COMMIT_SHA
|
||||
- setup_node_modules
|
||||
- *restore_node_modules
|
||||
- run:
|
||||
command: node ./scripts/tasks/danger
|
||||
|
||||
|
|
@ -228,7 +265,7 @@ jobs:
|
|||
- checkout
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- setup_node_modules
|
||||
- *restore_node_modules
|
||||
- run:
|
||||
environment:
|
||||
RELEASE_CHANNEL: experimental
|
||||
|
|
@ -243,7 +280,7 @@ jobs:
|
|||
- checkout
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- setup_node_modules
|
||||
- *restore_node_modules
|
||||
- run:
|
||||
name: Playwright install deps
|
||||
command: |
|
||||
|
|
@ -265,7 +302,7 @@ jobs:
|
|||
- checkout
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- setup_node_modules
|
||||
- *restore_node_modules
|
||||
- run: ./scripts/circleci/download_devtools_regression_build.js << parameters.version >> --replaceBuild
|
||||
- run: node ./scripts/jest/jest-cli.js --build --project devtools --release-channel=experimental --reactVersion << parameters.version >> --ci
|
||||
|
||||
|
|
@ -280,7 +317,7 @@ jobs:
|
|||
- checkout
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- setup_node_modules
|
||||
- *restore_node_modules
|
||||
- run:
|
||||
name: Playwright install deps
|
||||
command: |
|
||||
|
|
@ -304,7 +341,7 @@ jobs:
|
|||
- checkout
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- setup_node_modules
|
||||
- *restore_node_modules
|
||||
- run: yarn lint-build
|
||||
|
||||
yarn_check_release_dependencies:
|
||||
|
|
@ -314,7 +351,7 @@ jobs:
|
|||
- checkout
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- setup_node_modules
|
||||
- *restore_node_modules
|
||||
- run: yarn check-release-dependencies
|
||||
|
||||
|
||||
|
|
@ -324,7 +361,7 @@ jobs:
|
|||
steps:
|
||||
- checkout
|
||||
- attach_workspace: *attach_workspace
|
||||
- setup_node_modules
|
||||
- *restore_node_modules
|
||||
- run:
|
||||
name: Search build artifacts for unminified errors
|
||||
command: |
|
||||
|
|
@ -337,7 +374,7 @@ jobs:
|
|||
steps:
|
||||
- checkout
|
||||
- attach_workspace: *attach_workspace
|
||||
- setup_node_modules
|
||||
- *restore_node_modules
|
||||
- run:
|
||||
name: Confirm generated inline Fizz runtime is up to date
|
||||
command: |
|
||||
|
|
@ -353,7 +390,7 @@ jobs:
|
|||
type: string
|
||||
steps:
|
||||
- checkout
|
||||
- setup_node_modules
|
||||
- *restore_node_modules
|
||||
- run: yarn test <<parameters.args>> --ci
|
||||
|
||||
yarn_test_build:
|
||||
|
|
@ -367,7 +404,7 @@ jobs:
|
|||
- checkout
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- setup_node_modules
|
||||
- *restore_node_modules
|
||||
- run: yarn test --build <<parameters.args>> --ci
|
||||
|
||||
RELEASE_CHANNEL_stable_yarn_test_dom_fixtures:
|
||||
|
|
@ -377,7 +414,7 @@ jobs:
|
|||
- checkout
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- setup_node_modules
|
||||
- *restore_node_modules
|
||||
- *restore_yarn_cache_fixtures_dom
|
||||
- *yarn_install_fixtures_dom
|
||||
- *yarn_install_fixtures_dom_retry
|
||||
|
|
@ -388,7 +425,7 @@ jobs:
|
|||
RELEASE_CHANNEL: stable
|
||||
working_directory: fixtures/dom
|
||||
command: |
|
||||
yarn predev
|
||||
yarn prestart
|
||||
yarn test --maxWorkers=2
|
||||
|
||||
test_fuzz:
|
||||
|
|
@ -396,7 +433,7 @@ jobs:
|
|||
environment: *environment
|
||||
steps:
|
||||
- checkout
|
||||
- setup_node_modules
|
||||
- *restore_node_modules
|
||||
- run:
|
||||
name: Run fuzz tests
|
||||
command: |
|
||||
|
|
@ -415,7 +452,7 @@ jobs:
|
|||
environment: *environment
|
||||
steps:
|
||||
- checkout
|
||||
- setup_node_modules
|
||||
- *restore_node_modules
|
||||
- run:
|
||||
name: Run publish script
|
||||
command: |
|
||||
|
|
@ -426,30 +463,29 @@ jobs:
|
|||
scripts/release/publish.js --ci --tags << parameters.dist_tag >>
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
|
||||
# New workflow that will replace "stable" and "experimental"
|
||||
build_and_test:
|
||||
unless: << pipeline.parameters.prerelease_commit_sha >>
|
||||
jobs:
|
||||
- setup:
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- builds/facebook-www
|
||||
- yarn_flow:
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- builds/facebook-www
|
||||
requires:
|
||||
- setup
|
||||
- check_generated_fizz_runtime:
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- builds/facebook-www
|
||||
requires:
|
||||
- setup
|
||||
- yarn_lint:
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- builds/facebook-www
|
||||
requires:
|
||||
- setup
|
||||
- yarn_test:
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- builds/facebook-www
|
||||
requires:
|
||||
- setup
|
||||
matrix:
|
||||
parameters:
|
||||
args:
|
||||
|
|
@ -472,23 +508,19 @@ workflows:
|
|||
# TODO: Test more persistent configurations?
|
||||
- '-r=stable --env=development --persistent'
|
||||
- '-r=experimental --env=development --persistent'
|
||||
- yarn_build:
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- builds/facebook-www
|
||||
- yarn_build_combined:
|
||||
requires:
|
||||
- setup
|
||||
- scrape_warning_messages:
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- builds/facebook-www
|
||||
requires:
|
||||
- setup
|
||||
- process_artifacts_combined:
|
||||
requires:
|
||||
- scrape_warning_messages
|
||||
- yarn_build
|
||||
- yarn_build_combined
|
||||
- yarn_test_build:
|
||||
requires:
|
||||
- yarn_build
|
||||
- yarn_build_combined
|
||||
matrix:
|
||||
parameters:
|
||||
args:
|
||||
|
|
@ -519,7 +551,8 @@ workflows:
|
|||
branches:
|
||||
ignore:
|
||||
- main
|
||||
- builds/facebook-www
|
||||
requires:
|
||||
- setup
|
||||
- sizebot:
|
||||
filters:
|
||||
branches:
|
||||
|
|
@ -527,22 +560,22 @@ workflows:
|
|||
- main
|
||||
requires:
|
||||
- download_base_build_for_sizebot
|
||||
- yarn_build
|
||||
- yarn_build_combined
|
||||
- yarn_lint_build:
|
||||
requires:
|
||||
- yarn_build
|
||||
- yarn_build_combined
|
||||
- yarn_check_release_dependencies:
|
||||
requires:
|
||||
- yarn_build
|
||||
- yarn_build_combined
|
||||
- check_error_codes:
|
||||
requires:
|
||||
- yarn_build
|
||||
- yarn_build_combined
|
||||
- RELEASE_CHANNEL_stable_yarn_test_dom_fixtures:
|
||||
requires:
|
||||
- yarn_build
|
||||
- yarn_build_combined
|
||||
- build_devtools_and_process_artifacts:
|
||||
requires:
|
||||
- yarn_build
|
||||
- yarn_build_combined
|
||||
- run_devtools_e2e_tests:
|
||||
requires:
|
||||
- build_devtools_and_process_artifacts
|
||||
|
|
@ -558,7 +591,10 @@ workflows:
|
|||
only:
|
||||
- main
|
||||
jobs:
|
||||
- test_fuzz
|
||||
- setup
|
||||
- test_fuzz:
|
||||
requires:
|
||||
- setup
|
||||
|
||||
devtools_regression_tests:
|
||||
unless: << pipeline.parameters.prerelease_commit_sha >>
|
||||
|
|
@ -571,7 +607,10 @@ workflows:
|
|||
only:
|
||||
- main
|
||||
jobs:
|
||||
- setup
|
||||
- download_build:
|
||||
requires:
|
||||
- setup
|
||||
revision: << pipeline.git.revision >>
|
||||
- build_devtools_and_process_artifacts:
|
||||
requires:
|
||||
|
|
@ -603,21 +642,14 @@ workflows:
|
|||
publish_preleases:
|
||||
when: << pipeline.parameters.prerelease_commit_sha >>
|
||||
jobs:
|
||||
- setup
|
||||
- publish_prerelease:
|
||||
name: Publish to Canary channel
|
||||
name: Publish to Next channel
|
||||
requires:
|
||||
- setup
|
||||
commit_sha: << pipeline.parameters.prerelease_commit_sha >>
|
||||
release_channel: stable
|
||||
# The tags to use when publishing canaries. The main one we should
|
||||
# always include is "canary" but we can use multiple (e.g. alpha,
|
||||
# beta, rc). To declare multiple, use a comma-separated string, like
|
||||
# this:
|
||||
# dist_tag: "canary,alpha,beta,rc"
|
||||
#
|
||||
# TODO: We currently tag canaries with "next" in addition to "canary"
|
||||
# because this used to be called the "next" channel and some
|
||||
# downstream consumers might still expect that tag. We can remove this
|
||||
# after some time has elapsed and the change has been communicated.
|
||||
dist_tag: "canary,next"
|
||||
dist_tag: "next"
|
||||
- publish_prerelease:
|
||||
name: Publish to Experimental channel
|
||||
requires:
|
||||
|
|
@ -625,7 +657,7 @@ workflows:
|
|||
# will sometimes fail if you try to concurrently publish two
|
||||
# different versions of the same package, even if they use different
|
||||
# dist tags.
|
||||
- Publish to Canary channel
|
||||
- Publish to Next channel
|
||||
commit_sha: << pipeline.parameters.prerelease_commit_sha >>
|
||||
release_channel: experimental
|
||||
dist_tag: experimental
|
||||
|
|
@ -642,11 +674,14 @@ workflows:
|
|||
only:
|
||||
- main
|
||||
jobs:
|
||||
- setup
|
||||
- publish_prerelease:
|
||||
name: Publish to Canary channel
|
||||
name: Publish to Next channel
|
||||
requires:
|
||||
- setup
|
||||
commit_sha: << pipeline.git.revision >>
|
||||
release_channel: stable
|
||||
dist_tag: "canary,next"
|
||||
dist_tag: "next"
|
||||
- publish_prerelease:
|
||||
name: Publish to Experimental channel
|
||||
requires:
|
||||
|
|
@ -654,7 +689,7 @@ workflows:
|
|||
# will sometimes fail if you try to concurrently publish two
|
||||
# different versions of the same package, even if they use different
|
||||
# dist tags.
|
||||
- Publish to Canary channel
|
||||
- Publish to Next channel
|
||||
commit_sha: << pipeline.git.revision >>
|
||||
release_channel: experimental
|
||||
dist_tag: experimental
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"packages": ["packages/react", "packages/react-dom", "packages/scheduler"],
|
||||
"buildCommand": "download-build-in-codesandbox-ci",
|
||||
"node": "18",
|
||||
"node": "14",
|
||||
"publishDirectory": {
|
||||
"react": "build/oss-experimental/react",
|
||||
"react-dom": "build/oss-experimental/react-dom",
|
||||
|
|
|
|||
276
.eslintrc.js
276
.eslintrc.js
|
|
@ -8,18 +8,15 @@ const {
|
|||
const restrictedGlobals = require('confusing-browser-globals');
|
||||
|
||||
const OFF = 0;
|
||||
const WARNING = 1;
|
||||
const ERROR = 2;
|
||||
|
||||
module.exports = {
|
||||
extends: ['prettier'],
|
||||
extends: ['fbjs', 'prettier'],
|
||||
|
||||
// Stop ESLint from looking for a configuration file in parent folders
|
||||
root: true,
|
||||
|
||||
plugins: [
|
||||
'babel',
|
||||
'ft-flow',
|
||||
'jest',
|
||||
'no-for-of-loops',
|
||||
'no-function-declare-after-return',
|
||||
|
|
@ -27,7 +24,7 @@ module.exports = {
|
|||
'react-internal',
|
||||
],
|
||||
|
||||
parser: 'hermes-eslint',
|
||||
parser: 'babel-eslint',
|
||||
parserOptions: {
|
||||
ecmaVersion: 9,
|
||||
sourceType: 'script',
|
||||
|
|
@ -36,190 +33,6 @@ module.exports = {
|
|||
// We're stricter than the default config, mostly. We'll override a few rules
|
||||
// and then enable some React specific ones.
|
||||
rules: {
|
||||
'ft-flow/array-style-complex-type': [OFF, 'verbose'],
|
||||
'ft-flow/array-style-simple-type': [OFF, 'verbose'], // TODO should be WARNING
|
||||
'ft-flow/boolean-style': ERROR,
|
||||
'ft-flow/no-dupe-keys': ERROR,
|
||||
'ft-flow/no-primitive-constructor-types': ERROR,
|
||||
'ft-flow/no-types-missing-file-annotation': OFF, // TODO should be ERROR
|
||||
'ft-flow/no-unused-expressions': ERROR,
|
||||
// 'ft-flow/no-weak-types': WARNING,
|
||||
// 'ft-flow/require-valid-file-annotation': ERROR,
|
||||
|
||||
'no-cond-assign': OFF,
|
||||
'no-constant-condition': OFF,
|
||||
'no-control-regex': OFF,
|
||||
'no-debugger': ERROR,
|
||||
'no-dupe-args': ERROR,
|
||||
'no-dupe-keys': ERROR,
|
||||
'no-duplicate-case': WARNING,
|
||||
'no-empty-character-class': WARNING,
|
||||
'no-empty': OFF,
|
||||
'no-ex-assign': WARNING,
|
||||
'no-extra-boolean-cast': WARNING,
|
||||
'no-func-assign': ERROR,
|
||||
'no-invalid-regexp': WARNING,
|
||||
'no-irregular-whitespace': WARNING,
|
||||
'no-negated-in-lhs': ERROR,
|
||||
'no-obj-calls': ERROR,
|
||||
'no-regex-spaces': WARNING,
|
||||
'no-sparse-arrays': ERROR,
|
||||
'no-unreachable': ERROR,
|
||||
'use-isnan': ERROR,
|
||||
'valid-jsdoc': OFF,
|
||||
'block-scoped-var': OFF,
|
||||
complexity: OFF,
|
||||
'default-case': OFF,
|
||||
'guard-for-in': OFF,
|
||||
'no-alert': OFF,
|
||||
'no-caller': ERROR,
|
||||
'no-case-declarations': OFF,
|
||||
'no-div-regex': OFF,
|
||||
'no-else-return': OFF,
|
||||
'no-empty-pattern': WARNING,
|
||||
'no-eq-null': OFF,
|
||||
'no-eval': ERROR,
|
||||
'no-extend-native': WARNING,
|
||||
'no-extra-bind': WARNING,
|
||||
'no-fallthrough': WARNING,
|
||||
'no-implicit-coercion': OFF,
|
||||
'no-implied-eval': ERROR,
|
||||
'no-invalid-this': OFF,
|
||||
'no-iterator': OFF,
|
||||
'no-labels': [ERROR, {allowLoop: true, allowSwitch: true}],
|
||||
'no-lone-blocks': WARNING,
|
||||
'no-loop-func': OFF,
|
||||
'no-magic-numbers': OFF,
|
||||
'no-multi-str': ERROR,
|
||||
'no-native-reassign': [ERROR, {exceptions: ['Map', 'Set']}],
|
||||
'no-new-func': ERROR,
|
||||
'no-new': WARNING,
|
||||
'no-new-wrappers': WARNING,
|
||||
'no-octal-escape': WARNING,
|
||||
'no-octal': WARNING,
|
||||
'no-param-reassign': OFF,
|
||||
'no-process-env': OFF,
|
||||
'no-proto': ERROR,
|
||||
'no-redeclare': OFF, // TODO should be WARNING?
|
||||
'no-return-assign': OFF,
|
||||
'no-script-url': ERROR,
|
||||
'no-self-compare': WARNING,
|
||||
'no-sequences': WARNING,
|
||||
'no-throw-literal': ERROR,
|
||||
'no-useless-call': WARNING,
|
||||
'no-void': OFF,
|
||||
'no-warning-comments': OFF,
|
||||
'no-with': OFF,
|
||||
radix: WARNING,
|
||||
'vars-on-top': OFF,
|
||||
yoda: OFF,
|
||||
'init-declarations': OFF,
|
||||
'no-catch-shadow': ERROR,
|
||||
'no-delete-var': ERROR,
|
||||
'no-label-var': WARNING,
|
||||
'no-shadow-restricted-names': WARNING,
|
||||
'no-undef-init': OFF,
|
||||
'no-undef': ERROR,
|
||||
'no-undefined': OFF,
|
||||
'callback-return': OFF,
|
||||
'global-require': OFF,
|
||||
'handle-callback-err': OFF,
|
||||
'no-mixed-requires': OFF,
|
||||
'no-new-require': OFF,
|
||||
'no-path-concat': OFF,
|
||||
'no-process-exit': OFF,
|
||||
'no-restricted-modules': OFF,
|
||||
'no-sync': OFF,
|
||||
camelcase: [OFF, {properties: 'always'}],
|
||||
'consistent-this': [OFF, 'self'],
|
||||
'func-names': OFF,
|
||||
'func-style': [OFF, 'declaration'],
|
||||
'id-length': OFF,
|
||||
'id-match': OFF,
|
||||
'max-depth': OFF,
|
||||
'max-nested-callbacks': OFF,
|
||||
'max-params': OFF,
|
||||
'max-statements': OFF,
|
||||
'new-cap': OFF,
|
||||
'newline-after-var': OFF,
|
||||
'no-array-constructor': ERROR,
|
||||
'no-continue': OFF,
|
||||
'no-inline-comments': OFF,
|
||||
'no-lonely-if': OFF,
|
||||
'no-negated-condition': OFF,
|
||||
'no-nested-ternary': OFF,
|
||||
'no-new-object': WARNING,
|
||||
'no-plusplus': OFF,
|
||||
'no-ternary': OFF,
|
||||
'no-underscore-dangle': OFF,
|
||||
'no-unneeded-ternary': WARNING,
|
||||
'one-var': [WARNING, {initialized: 'never'}],
|
||||
'operator-assignment': [WARNING, 'always'],
|
||||
'require-jsdoc': OFF,
|
||||
'sort-vars': OFF,
|
||||
'spaced-comment': [
|
||||
OFF,
|
||||
'always',
|
||||
{exceptions: ['jshint', 'jslint', 'eslint', 'global']},
|
||||
],
|
||||
'constructor-super': ERROR,
|
||||
'no-class-assign': WARNING,
|
||||
'no-const-assign': ERROR,
|
||||
'no-dupe-class-members': ERROR,
|
||||
'no-this-before-super': ERROR,
|
||||
'object-shorthand': OFF,
|
||||
'prefer-const': OFF,
|
||||
'prefer-spread': OFF,
|
||||
'prefer-reflect': OFF,
|
||||
'prefer-template': OFF,
|
||||
'require-yield': OFF,
|
||||
'babel/generator-star-spacing': OFF,
|
||||
'babel/new-cap': OFF,
|
||||
'babel/array-bracket-spacing': OFF,
|
||||
'babel/object-curly-spacing': OFF,
|
||||
'babel/object-shorthand': OFF,
|
||||
'babel/arrow-parens': OFF,
|
||||
'babel/no-await-in-loop': OFF,
|
||||
'babel/flow-object-type': OFF,
|
||||
'react/display-name': OFF,
|
||||
'react/forbid-prop-types': OFF,
|
||||
'react/jsx-closing-bracket-location': OFF,
|
||||
'react/jsx-curly-spacing': OFF,
|
||||
'react/jsx-equals-spacing': WARNING,
|
||||
'react/jsx-filename-extension': OFF,
|
||||
'react/jsx-first-prop-new-line': OFF,
|
||||
'react/jsx-handler-names': OFF,
|
||||
'react/jsx-indent': OFF,
|
||||
'react/jsx-indent-props': OFF,
|
||||
'react/jsx-key': OFF,
|
||||
'react/jsx-max-props-per-line': OFF,
|
||||
'react/jsx-no-bind': OFF,
|
||||
'react/jsx-no-duplicate-props': ERROR,
|
||||
'react/jsx-no-literals': OFF,
|
||||
'react/jsx-no-target-blank': OFF,
|
||||
'react/jsx-pascal-case': OFF,
|
||||
'react/jsx-sort-props': OFF,
|
||||
'react/jsx-uses-vars': ERROR,
|
||||
'react/no-comment-textnodes': OFF,
|
||||
'react/no-danger': OFF,
|
||||
'react/no-deprecated': OFF,
|
||||
'react/no-did-mount-set-state': OFF,
|
||||
'react/no-did-update-set-state': OFF,
|
||||
'react/no-direct-mutation-state': OFF,
|
||||
'react/no-multi-comp': OFF,
|
||||
'react/no-render-return-value': OFF,
|
||||
'react/no-set-state': OFF,
|
||||
'react/no-string-refs': OFF,
|
||||
'react/no-unknown-property': OFF,
|
||||
'react/prefer-es6-class': OFF,
|
||||
'react/prefer-stateless-function': OFF,
|
||||
'react/prop-types': OFF,
|
||||
'react/require-extension': OFF,
|
||||
'react/require-optimization': OFF,
|
||||
'react/require-render-return': OFF,
|
||||
'react/sort-comp': OFF,
|
||||
'react/sort-prop-types': OFF,
|
||||
|
||||
'accessor-pairs': OFF,
|
||||
'brace-style': [ERROR, '1tbs'],
|
||||
'consistent-return': OFF,
|
||||
|
|
@ -236,15 +49,9 @@ module.exports = {
|
|||
'no-inner-declarations': [ERROR, 'functions'],
|
||||
'no-multi-spaces': ERROR,
|
||||
'no-restricted-globals': [ERROR].concat(restrictedGlobals),
|
||||
'no-restricted-syntax': [
|
||||
ERROR,
|
||||
'WithStatement',
|
||||
{
|
||||
selector: 'MemberExpression[property.name=/^(?:substring|substr)$/]',
|
||||
message: 'Prefer string.slice() over .substring() and .substr().',
|
||||
},
|
||||
],
|
||||
'no-restricted-syntax': [ERROR, 'WithStatement'],
|
||||
'no-shadow': ERROR,
|
||||
'no-unused-expressions': ERROR,
|
||||
'no-unused-vars': [ERROR, {args: 'none'}],
|
||||
'no-use-before-define': OFF,
|
||||
'no-useless-concat': OFF,
|
||||
|
|
@ -267,6 +74,8 @@ module.exports = {
|
|||
// deal. But I turned it off because loading the plugin causes some obscure
|
||||
// syntax error and it didn't seem worth investigating.
|
||||
'max-len': OFF,
|
||||
// Prettier forces semicolons in a few places
|
||||
'flowtype/object-type-delimiter': OFF,
|
||||
|
||||
// React & JSX
|
||||
// Our transforms set this automatically
|
||||
|
|
@ -332,7 +141,6 @@ module.exports = {
|
|||
'packages/react-native-renderer/**/*.js',
|
||||
'packages/eslint-plugin-react-hooks/**/*.js',
|
||||
'packages/jest-react/**/*.js',
|
||||
'packages/internal-test-utils/**/*.js',
|
||||
'packages/**/__tests__/*.js',
|
||||
'packages/**/npm/*.js',
|
||||
],
|
||||
|
|
@ -358,7 +166,7 @@ module.exports = {
|
|||
// We apply these settings to the source files that get compiled.
|
||||
// They can use all features including JSX (but shouldn't use `var`).
|
||||
files: esNextPaths,
|
||||
parser: 'hermes-eslint',
|
||||
parser: 'babel-eslint',
|
||||
parserOptions: {
|
||||
ecmaVersion: 8,
|
||||
sourceType: 'module',
|
||||
|
|
@ -396,6 +204,14 @@ module.exports = {
|
|||
ERROR,
|
||||
{isProductionUserAppCode: false},
|
||||
],
|
||||
|
||||
// Disable accessibility checks
|
||||
'jsx-a11y/aria-role': OFF,
|
||||
'jsx-a11y/no-noninteractive-element-interactions': OFF,
|
||||
'jsx-a11y/no-static-element-interactions': OFF,
|
||||
'jsx-a11y/role-has-required-aria-props': OFF,
|
||||
'jsx-a11y/no-noninteractive-tabindex': OFF,
|
||||
'jsx-a11y/tabindex-no-positive': OFF,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -416,6 +232,7 @@ module.exports = {
|
|||
{
|
||||
files: [
|
||||
'packages/react-native-renderer/**/*.js',
|
||||
'packages/react-server-native-relay/**/*.js',
|
||||
],
|
||||
globals: {
|
||||
nativeFabricUIManager: 'readonly',
|
||||
|
|
@ -436,71 +253,10 @@ module.exports = {
|
|||
},
|
||||
],
|
||||
|
||||
env: {
|
||||
browser: true,
|
||||
es6: true,
|
||||
node: true,
|
||||
jest: true,
|
||||
},
|
||||
|
||||
globals: {
|
||||
$Call: 'readonly',
|
||||
$ElementType: 'readonly',
|
||||
$Flow$ModuleRef: 'readonly',
|
||||
$FlowFixMe: 'readonly',
|
||||
$Keys: 'readonly',
|
||||
$NonMaybeType: 'readonly',
|
||||
$PropertyType: 'readonly',
|
||||
$ReadOnly: 'readonly',
|
||||
$ReadOnlyArray: 'readonly',
|
||||
$Shape: 'readonly',
|
||||
AnimationFrameID: 'readonly',
|
||||
// For Flow type annotation. Only `BigInt` is valid at runtime.
|
||||
bigint: 'readonly',
|
||||
BigInt: 'readonly',
|
||||
Class: 'readonly',
|
||||
ClientRect: 'readonly',
|
||||
CopyInspectedElementPath: 'readonly',
|
||||
DOMHighResTimeStamp: 'readonly',
|
||||
EventListener: 'readonly',
|
||||
Iterable: 'readonly',
|
||||
Iterator: 'readonly',
|
||||
JSONValue: 'readonly',
|
||||
JSResourceReference: 'readonly',
|
||||
MouseEventHandler: 'readonly',
|
||||
PropagationPhases: 'readonly',
|
||||
PropertyDescriptor: 'readonly',
|
||||
React$AbstractComponent: 'readonly',
|
||||
React$Component: 'readonly',
|
||||
React$ComponentType: 'readonly',
|
||||
React$Config: 'readonly',
|
||||
React$Context: 'readonly',
|
||||
React$Element: 'readonly',
|
||||
React$ElementConfig: 'readonly',
|
||||
React$ElementProps: 'readonly',
|
||||
React$ElementRef: 'readonly',
|
||||
React$ElementType: 'readonly',
|
||||
React$Key: 'readonly',
|
||||
React$Node: 'readonly',
|
||||
React$Portal: 'readonly',
|
||||
React$Ref: 'readonly',
|
||||
React$StatelessFunctionalComponent: 'readonly',
|
||||
ReadableStreamController: 'readonly',
|
||||
RequestInfo: 'readonly',
|
||||
RequestOptions: 'readonly',
|
||||
ResponseState: 'readonly',
|
||||
StoreAsGlobal: 'readonly',
|
||||
symbol: 'readonly',
|
||||
SyntheticEvent: 'readonly',
|
||||
SyntheticMouseEvent: 'readonly',
|
||||
Thenable: 'readonly',
|
||||
TimeoutID: 'readonly',
|
||||
WheelEventHandler: 'readonly',
|
||||
|
||||
spyOnDev: 'readonly',
|
||||
spyOnDevAndProd: 'readonly',
|
||||
spyOnProd: 'readonly',
|
||||
__DEV__: 'readonly',
|
||||
__EXPERIMENTAL__: 'readonly',
|
||||
__EXTENSION__: 'readonly',
|
||||
__PROFILE__: 'readonly',
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
3. If you've fixed a bug or added code that should be tested, add tests!
|
||||
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch TestName` is helpful in development.
|
||||
5. Run `yarn test --prod` to test in the production environment. It supports the same options as `yarn test`.
|
||||
6. If you need a debugger, run `yarn test --debug --watch TestName`, open `chrome://inspect`, and press "Inspect".
|
||||
6. If you need a debugger, run `yarn debug-test --watch TestName`, open `chrome://inspect`, and press "Inspect".
|
||||
7. Format your code with [prettier](https://github.com/prettier/prettier) (`yarn prettier`).
|
||||
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only check changed files.
|
||||
9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
|
||||
|
|
|
|||
|
|
@ -1,29 +1,24 @@
|
|||
name: Commit Artifacts for Meta WWW and fbsource
|
||||
name: Commit Artifacts for Facebook WWW
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, meta-www, meta-fbsource]
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
download_artifacts:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
www_branch_count: ${{ steps.check_branches.outputs.www_branch_count }}
|
||||
fbsource_branch_count: ${{ steps.check_branches.outputs.fbsource_branch_count }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: "Check branches"
|
||||
id: check_branches
|
||||
run: |
|
||||
echo "www_branch_count=$(git ls-remote --heads origin "refs/heads/meta-www" | wc -l)" >> "$GITHUB_OUTPUT"
|
||||
echo "fbsource_branch_count=$(git ls-remote --heads origin "refs/heads/meta-fbsource" | wc -l)" >> "$GITHUB_OUTPUT"
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
- run: npm init -y
|
||||
- run: npm install node-fetch@2
|
||||
- name: Download and unzip artifacts
|
||||
uses: actions/github-script@v6
|
||||
env:
|
||||
CIRCLECI_TOKEN: ${{secrets.CIRCLECI_TOKEN_DIFFTRAIN}}
|
||||
with:
|
||||
script: |
|
||||
const cp = require('child_process');
|
||||
const fetch = require('node-fetch');
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
|
@ -69,10 +64,10 @@ jobs:
|
|||
const ciBuildId = /\/facebook\/react\/([0-9]+)/.exec(
|
||||
status.target_url,
|
||||
)[1];
|
||||
console.log(`CircleCI build id found: ${ciBuildId}`);
|
||||
if (Number.parseInt(ciBuildId, 10) + '' === ciBuildId) {
|
||||
artifactsUrl =
|
||||
`https://circleci.com/api/v1.1/project/github/facebook/react/${ciBuildId}/artifacts`;
|
||||
console.log(`Found artifactsUrl: ${artifactsUrl}`);
|
||||
break spinloop;
|
||||
} else {
|
||||
throw new Error(`${ciBuildId} isn't a number`);
|
||||
|
|
@ -91,33 +86,20 @@ jobs:
|
|||
await sleep(60_000);
|
||||
}
|
||||
if (artifactsUrl != null) {
|
||||
const {CIRCLECI_TOKEN} = process.env;
|
||||
const res = await fetch(artifactsUrl, {
|
||||
headers: {
|
||||
'Circle-Token': CIRCLECI_TOKEN
|
||||
}
|
||||
});
|
||||
const res = await fetch(artifactsUrl);
|
||||
const data = await res.json();
|
||||
if (!Array.isArray(data) && data.message != null) {
|
||||
throw `CircleCI returned: ${data.message}`;
|
||||
}
|
||||
for (const artifact of data) {
|
||||
if (artifact.path === 'build.tgz') {
|
||||
console.log(`Downloading and unzipping ${artifact.url}`);
|
||||
await execHelper(
|
||||
`curl -L ${artifact.url} -H "Circle-Token: ${CIRCLECI_TOKEN}" | tar -xvz`
|
||||
`curl -L ${artifact.url} | tar -xvz`
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
process.exitCode = 1;
|
||||
}
|
||||
- name: Strip @license from eslint plugin and react-refresh
|
||||
run: |
|
||||
sed -i -e 's/ @license React*//' \
|
||||
build/oss-experimental/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js \
|
||||
build/oss-experimental/react-refresh/cjs/react-refresh-babel.development.js
|
||||
- name: Move relevant files for React in www into compiled
|
||||
- name: Move relevant files into compiled
|
||||
run: |
|
||||
mkdir -p ./compiled
|
||||
mkdir -p ./compiled/facebook-www
|
||||
|
|
@ -130,7 +112,7 @@ jobs:
|
|||
mv build/WARNINGS ./compiled/facebook-www/WARNINGS
|
||||
|
||||
# Copy eslint-plugin-react-hooks into facebook-www
|
||||
mv build/oss-experimental/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js \
|
||||
mv build/oss-stable/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js \
|
||||
./compiled/facebook-www/eslint-plugin-react-hooks.js
|
||||
|
||||
# Copy unstable_server-external-runtime.js into facebook-www
|
||||
|
|
@ -138,46 +120,17 @@ jobs:
|
|||
./compiled/facebook-www/unstable_server-external-runtime.js
|
||||
|
||||
# Copy react-refresh-babel.development.js into babel-plugin-react-refresh
|
||||
mv build/oss-experimental/react-refresh/cjs/react-refresh-babel.development.js \
|
||||
mv build/oss-stable/react-refresh/cjs/react-refresh-babel.development.js \
|
||||
./compiled/babel-plugin-react-refresh/index.js
|
||||
|
||||
ls -R ./compiled
|
||||
- name: Move relevant files for React in fbsource into compiled-rn
|
||||
run: |
|
||||
BASE_FOLDER='compiled-rn/facebook-fbsource/xplat/js'
|
||||
mkdir -p ${BASE_FOLDER}/react-native-github/Libraries/Renderer/
|
||||
mkdir -p ${BASE_FOLDER}/RKJSModules/vendor/{scheduler,react,react-is,react-test-renderer}/
|
||||
|
||||
# Move React Native renderer
|
||||
mv build/react-native/implementations/ $BASE_FOLDER/react-native-github/Libraries/Renderer/
|
||||
mv build/react-native/shims/ $BASE_FOLDER/react-native-github/Libraries/Renderer/
|
||||
mv build/facebook-react-native/scheduler/cjs/ $BASE_FOLDER/RKJSModules/vendor/scheduler/
|
||||
mv build/facebook-react-native/react/cjs/ $BASE_FOLDER/RKJSModules/vendor/react/
|
||||
mv build/facebook-react-native/react-is/cjs/ $BASE_FOLDER/RKJSModules/vendor/react-is/
|
||||
mv build/facebook-react-native/react-test-renderer/cjs/ $BASE_FOLDER/RKJSModules/vendor/react-test-renderer/
|
||||
|
||||
# Delete OSS renderer. OSS renderer is synced through internal script.
|
||||
RENDERER_FOLDER=$BASE_FOLDER/react-native-github/Libraries/Renderer/implementations/
|
||||
rm $RENDERER_FOLDER/ReactFabric-{dev,prod,profiling}.js
|
||||
rm $RENDERER_FOLDER/ReactNativeRenderer-{dev,prod,profiling}.js
|
||||
|
||||
ls -R ./compiled
|
||||
- name: Add REVISION file
|
||||
run: |
|
||||
echo ${{ github.sha }} >> ./compiled/facebook-www/REVISION
|
||||
echo ${{ github.sha }} >> ./compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/REVISION
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: compiled
|
||||
path: compiled/
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: compiled-rn
|
||||
path: compiled-rn/
|
||||
|
||||
commit_www_artifacts:
|
||||
commit_artifacts:
|
||||
needs: download_artifacts
|
||||
if: ${{ (github.ref == 'refs/heads/main' && needs.download_artifacts.outputs.www_branch_count == '0') || github.ref == 'refs/heads/meta-www' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
|
@ -190,59 +143,11 @@ jobs:
|
|||
name: compiled
|
||||
path: compiled/
|
||||
- run: git status -u
|
||||
- name: Check if only the REVISION file has changed
|
||||
id: check_should_commit
|
||||
run: |
|
||||
if git status --porcelain | grep -qv '/REVISION$'; then
|
||||
echo "should_commit=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "should_commit=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
- name: Commit changes to branch
|
||||
if: steps.check_should_commit.outputs.should_commit == 'true'
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: |
|
||||
${{ github.event.head_commit.message }}
|
||||
|
||||
DiffTrain build for [${{ github.sha }}](https://github.com/facebook/react/commit/${{ github.sha }})
|
||||
commit_message: Build for ${{ github.sha }}
|
||||
branch: builds/facebook-www
|
||||
commit_user_name: ${{ github.actor }}
|
||||
commit_user_email: ${{ github.actor }}@users.noreply.github.com
|
||||
create_branch: true
|
||||
|
||||
commit_fbsource_artifacts:
|
||||
needs: download_artifacts
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ (github.ref == 'refs/heads/main' && needs.download_artifacts.outputs.fbsource_branch_count == '0') || github.ref == 'refs/heads/meta-fbsource' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: main
|
||||
repository: facebook/react-fbsource-import
|
||||
token: ${{secrets.FBSOURCE_SYNC_PUSH_TOKEN}}
|
||||
- name: Ensure clean directory
|
||||
run: rm -rf compiled-rn
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: compiled-rn
|
||||
path: compiled-rn/
|
||||
- run: git status -u
|
||||
- name: Check if only the REVISION file has changed
|
||||
id: check_should_commit
|
||||
run: |
|
||||
if git status --porcelain | grep -qv '/REVISION$'; then
|
||||
echo "should_commit=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "should_commit=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
- name: Commit changes to branch
|
||||
if: steps.check_should_commit.outputs.should_commit == 'true'
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: |
|
||||
${{ github.event.head_commit.message }}
|
||||
|
||||
DiffTrain build for commit https://github.com/facebook/react/commit/${{ github.sha }}.
|
||||
commit_user_name: ${{ github.actor }}
|
||||
commit_user_email: ${{ github.actor }}@users.noreply.github.com
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ module.exports = {
|
|||
jsxBracketSameLine: true,
|
||||
trailingComma: 'es5',
|
||||
printWidth: 80,
|
||||
parser: 'flow',
|
||||
arrowParens: 'avoid',
|
||||
parser: 'babel',
|
||||
|
||||
overrides: [
|
||||
{
|
||||
files: esNextPaths,
|
||||
|
|
|
|||
10
CHANGELOG.md
10
CHANGELOG.md
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
### Server Components (Experimental)
|
||||
|
||||
* Add support for `useId()` inside Server Components. ([@gnoff](https://github.com/gnoff) in [#24172](https://github.com/facebook/react/pull/24172))
|
||||
* Add support for `useId()` inside Server Components. ([@gnoff](https://github.com/gnoff)) in [#24172](https://github.com/facebook/react/pull/24172)
|
||||
|
||||
## 18.1.0 (April 26, 2022)
|
||||
|
||||
|
|
@ -102,10 +102,6 @@ The existing `renderToString` method keeps working but is discouraged.
|
|||
* **Layout Effects with Suspense**: When a tree re-suspends and reverts to a fallback, React will now clean up layout effects, and then re-create them when the content inside the boundary is shown again. This fixes an issue which prevented component libraries from correctly measuring layout when used with Suspense.
|
||||
* **New JS Environment Requirements**: React now depends on modern browsers features including `Promise`, `Symbol`, and `Object.assign`. If you support older browsers and devices such as Internet Explorer which do not provide modern browser features natively or have non-compliant implementations, consider including a global polyfill in your bundled application.
|
||||
|
||||
### Scheduler (Experimental)
|
||||
|
||||
* Remove unstable `scheduler/tracing` API
|
||||
|
||||
## Notable Changes
|
||||
|
||||
### React
|
||||
|
|
@ -197,10 +193,6 @@ The existing `renderToString` method keeps working but is discouraged.
|
|||
* Fix a mistake in the Node loader. ([#22537](https://github.com/facebook/react/pull/22537) by [@btea](https://github.com/btea))
|
||||
* Use `globalThis` instead of `window` for edge environments. ([#22777](https://github.com/facebook/react/pull/22777) by [@huozhi](https://github.com/huozhi))
|
||||
|
||||
### Scheduler (Experimental)
|
||||
|
||||
* Remove unstable `scheduler/tracing` API ([#20037](https://github.com/facebook/react/pull/20037) by [@bvaughn](https://github.com/bvaughn))
|
||||
|
||||
## 17.0.2 (March 22, 2021)
|
||||
|
||||
### React DOM
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# [React](https://reactjs.org/) · [](https://github.com/facebook/react/blob/main/LICENSE) [](https://www.npmjs.com/package/react) [](https://circleci.com/gh/facebook/react) [](https://reactjs.org/docs/how-to-contribute.html#your-first-pull-request)
|
||||
# [React](https://reactjs.org/) · [](https://github.com/facebook/react/blob/main/LICENSE) [](https://www.npmjs.com/package/react) [](https://circleci.com/gh/facebook/react) [](https://reactjs.org/docs/how-to-contribute.html#your-first-pull-request)
|
||||
|
||||
React is a JavaScript library for building user interfaces.
|
||||
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@
|
|||
//
|
||||
// The @latest channel uses the version as-is, e.g.:
|
||||
//
|
||||
// 18.3.0
|
||||
// 18.0.0
|
||||
//
|
||||
// The @canary channel appends additional information, with the scheme
|
||||
// The @next channel appends additional information, with the scheme
|
||||
// <version>-<label>-<commit_sha>, e.g.:
|
||||
//
|
||||
// 18.3.0-canary-a1c2d3e4
|
||||
// 18.0.0-alpha-a1c2d3e4
|
||||
//
|
||||
// The @experimental channel doesn't include a version, only a date and a sha, e.g.:
|
||||
//
|
||||
|
|
@ -20,13 +20,9 @@
|
|||
|
||||
const ReactVersion = '18.3.0';
|
||||
|
||||
// The label used by the @canary channel. Represents the upcoming release's
|
||||
// stability. Most of the time, this will be "canary", but we may temporarily
|
||||
// choose to change it to "alpha", "beta", "rc", etc.
|
||||
//
|
||||
// It only affects the label used in the version string. To customize the
|
||||
// npm dist tags used during publish, refer to .circleci/config.yml.
|
||||
const canaryChannelLabel = 'canary';
|
||||
// The label used by the @next channel. Represents the upcoming release's
|
||||
// stability. Could be "alpha", "beta", "rc", etc.
|
||||
const nextChannelLabel = 'next';
|
||||
|
||||
const stablePackages = {
|
||||
'eslint-plugin-react-hooks': '5.0.0',
|
||||
|
|
@ -44,14 +40,14 @@ const stablePackages = {
|
|||
scheduler: '0.24.0',
|
||||
};
|
||||
|
||||
// These packages do not exist in the @canary or @latest channel, only
|
||||
// These packages do not exist in the @next or @latest channel, only
|
||||
// @experimental. We don't use semver, just the commit sha, so this is just a
|
||||
// list of package names instead of a map.
|
||||
const experimentalPackages = [];
|
||||
|
||||
module.exports = {
|
||||
ReactVersion,
|
||||
canaryChannelLabel,
|
||||
nextChannelLabel,
|
||||
stablePackages,
|
||||
experimentalPackages,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ const CRITICAL_ARTIFACT_PATHS = new Set([
|
|||
'oss-experimental/react-dom/cjs/react-dom.production.min.js',
|
||||
'facebook-www/ReactDOM-prod.classic.js',
|
||||
'facebook-www/ReactDOM-prod.modern.js',
|
||||
'facebook-www/ReactDOMForked-prod.classic.js',
|
||||
]);
|
||||
|
||||
const kilobyteFormatter = new Intl.NumberFormat('en', {
|
||||
|
|
@ -97,7 +98,7 @@ function row(result, baseSha, headSha) {
|
|||
return rowArr.join(' | ');
|
||||
}
|
||||
|
||||
(async function () {
|
||||
(async function() {
|
||||
// Use git locally to grab the commit which represents the place
|
||||
// where the branches differ
|
||||
|
||||
|
|
@ -241,9 +242,8 @@ Comparing: ${baseSha}...${headSha}
|
|||
|
||||
## Critical size changes
|
||||
|
||||
Includes critical production bundles, as well as any change greater than ${
|
||||
CRITICAL_THRESHOLD * 100
|
||||
}%:
|
||||
Includes critical production bundles, as well as any change greater than ${CRITICAL_THRESHOLD *
|
||||
100}%:
|
||||
|
||||
${header}
|
||||
${criticalResults.join('\n')}
|
||||
|
|
|
|||
|
|
@ -5,13 +5,12 @@
|
|||
"@babel/preset-env": "^7.10.4",
|
||||
"@babel/preset-react": "^7.10.4",
|
||||
"babel-loader": "^8.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-art": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react": "link:../../build/node_modules/react",
|
||||
"react-art": "link:../../build/node_modules/react-art/",
|
||||
"react-dom": "link:../../build/node_modules/react-dom",
|
||||
"webpack": "^1.14.0"
|
||||
},
|
||||
"scripts": {
|
||||
"prebuild": "cp -r ../../build/oss-experimental/* ./node_modules/",
|
||||
"build": "webpack app.js bundle.js"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1007,11 +1007,6 @@ arrify@^1.0.0:
|
|||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
|
||||
|
||||
art@^0.10.1:
|
||||
version "0.10.3"
|
||||
resolved "https://registry.yarnpkg.com/art/-/art-0.10.3.tgz#b01d84a968ccce6208df55a733838c96caeeaea2"
|
||||
integrity sha512-HXwbdofRTiJT6qZX/FnchtldzJjS3vkLJxQilc3Xj+ma2MXjY4UAyQ0ls1XZYVnDvVIBiFZbC6QsvtW86TD6tQ==
|
||||
|
||||
asn1@~0.2.3:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86"
|
||||
|
|
@ -1291,14 +1286,6 @@ core-util-is@~1.0.0:
|
|||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
|
||||
create-react-class@^15.6.2:
|
||||
version "15.7.0"
|
||||
resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.7.0.tgz#7499d7ca2e69bb51d13faf59bd04f0c65a1d6c1e"
|
||||
integrity sha512-QZv4sFWG9S5RUvkTYWbflxeZX+JG7Cz0Tn33rQBJ+WFQTqTfUTjMjiv9tnfXazjsO5r0KhPs+AqCjyrQX6h2ng==
|
||||
dependencies:
|
||||
loose-envify "^1.3.1"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
cryptiles@2.x.x:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
|
||||
|
|
@ -1774,7 +1761,7 @@ js-tokens@^3.0.0:
|
|||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
|
||||
|
||||
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
|
||||
js-tokens@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||
|
|
@ -1910,13 +1897,6 @@ loose-envify@^1.0.0:
|
|||
dependencies:
|
||||
js-tokens "^3.0.0"
|
||||
|
||||
loose-envify@^1.1.0, loose-envify@^1.3.1:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||
dependencies:
|
||||
js-tokens "^3.0.0 || ^4.0.0"
|
||||
|
||||
make-dir@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
|
||||
|
|
@ -2086,10 +2066,9 @@ oauth-sign@~0.8.1:
|
|||
version "0.8.2"
|
||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
|
||||
|
||||
object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
object-assign@^4.0.1, object-assign@^4.1.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
|
||||
|
||||
object-keys@^1.0.11, object-keys@^1.0.12:
|
||||
version "1.1.1"
|
||||
|
|
@ -2272,30 +2251,17 @@ rc@^1.1.7:
|
|||
minimist "^1.2.0"
|
||||
strip-json-comments "~2.0.1"
|
||||
|
||||
react-art@^18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-art/-/react-art-18.2.0.tgz#73b3929b1a0ce781b088bce76186d3793f0106c5"
|
||||
integrity sha512-HfSK9OBtPIpkdI4QZAyWSxCIbM/I7+nqjybxp2FLmiFS7RN+eCEvOY0KdPw+6//B1oIU31t2o35s5EEhe0Fodw==
|
||||
dependencies:
|
||||
art "^0.10.1"
|
||||
create-react-class "^15.6.2"
|
||||
loose-envify "^1.1.0"
|
||||
scheduler "^0.23.0"
|
||||
"react-art@link:../../build/node_modules/react-art":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
react-dom@^18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
|
||||
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
scheduler "^0.23.0"
|
||||
"react-dom@link:../../build/node_modules/react-dom":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
react@^18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
|
||||
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
"react@link:../../build/node_modules/react":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.4, readable-stream@^2.2.6:
|
||||
version "2.2.6"
|
||||
|
|
@ -2475,13 +2441,6 @@ safe-buffer@~5.1.1:
|
|||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||
|
||||
scheduler@^0.23.0:
|
||||
version "0.23.0"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
|
||||
integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
|
||||
schema-utils@^2.6.5:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7"
|
||||
|
|
|
|||
|
|
@ -1998,7 +1998,7 @@
|
|||
| `colSpan=(null)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |
|
||||
| `colSpan=(undefined)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |
|
||||
|
||||
## `content` (on `<meta>` inside `<head>`)
|
||||
## `content` (on `<meta>` inside `<div>`)
|
||||
| Test Case | Flags | Result |
|
||||
| --- | --- | --- |
|
||||
| `content=(string)`| (changed)| `"a string"` |
|
||||
|
|
@ -3348,81 +3348,6 @@
|
|||
| `externalResourcesRequired=(null)`| (initial)| `<null>` |
|
||||
| `externalResourcesRequired=(undefined)`| (initial)| `<null>` |
|
||||
|
||||
## `fetchPriority` (on `<img>` inside `<div>`)
|
||||
| Test Case | Flags | Result |
|
||||
| --- | --- | --- |
|
||||
| `fetchPriority=(string)`| (changed)| `"high"` |
|
||||
| `fetchPriority=(empty string)`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(array with string)`| (changed)| `"high"` |
|
||||
| `fetchPriority=(empty array)`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(object)`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(numeric string)`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(-1)`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(0)`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(integer)`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(NaN)`| (initial, warning)| `"auto"` |
|
||||
| `fetchPriority=(float)`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(true)`| (initial, warning)| `"auto"` |
|
||||
| `fetchPriority=(false)`| (initial, warning)| `"auto"` |
|
||||
| `fetchPriority=(string 'true')`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(string 'false')`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(string 'on')`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(string 'off')`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(symbol)`| (initial, warning)| `"auto"` |
|
||||
| `fetchPriority=(function)`| (initial, warning)| `"auto"` |
|
||||
| `fetchPriority=(null)`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(undefined)`| (initial)| `"auto"` |
|
||||
|
||||
## `fetchpriority` (on `<img>` inside `<div>`)
|
||||
| Test Case | Flags | Result |
|
||||
| --- | --- | --- |
|
||||
| `fetchpriority=(string)`| (changed, warning)| `"high"` |
|
||||
| `fetchpriority=(empty string)`| (initial, warning)| `"auto"` |
|
||||
| `fetchpriority=(array with string)`| (changed, warning)| `"high"` |
|
||||
| `fetchpriority=(empty array)`| (initial, warning)| `"auto"` |
|
||||
| `fetchpriority=(object)`| (initial, warning)| `"auto"` |
|
||||
| `fetchpriority=(numeric string)`| (initial, warning)| `"auto"` |
|
||||
| `fetchpriority=(-1)`| (initial, warning)| `"auto"` |
|
||||
| `fetchpriority=(0)`| (initial, warning)| `"auto"` |
|
||||
| `fetchpriority=(integer)`| (initial, warning)| `"auto"` |
|
||||
| `fetchpriority=(NaN)`| (initial, warning)| `"auto"` |
|
||||
| `fetchpriority=(float)`| (initial, warning)| `"auto"` |
|
||||
| `fetchpriority=(true)`| (initial, warning)| `"auto"` |
|
||||
| `fetchpriority=(false)`| (initial, warning)| `"auto"` |
|
||||
| `fetchpriority=(string 'true')`| (initial, warning)| `"auto"` |
|
||||
| `fetchpriority=(string 'false')`| (initial, warning)| `"auto"` |
|
||||
| `fetchpriority=(string 'on')`| (initial, warning)| `"auto"` |
|
||||
| `fetchpriority=(string 'off')`| (initial, warning)| `"auto"` |
|
||||
| `fetchpriority=(symbol)`| (initial, warning)| `"auto"` |
|
||||
| `fetchpriority=(function)`| (initial, warning)| `"auto"` |
|
||||
| `fetchpriority=(null)`| (initial, warning)| `"auto"` |
|
||||
| `fetchpriority=(undefined)`| (initial, warning)| `"auto"` |
|
||||
|
||||
## `fetchPriority` (on `<link>` inside `<div>`)
|
||||
| Test Case | Flags | Result |
|
||||
| --- | --- | --- |
|
||||
| `fetchPriority=(string)`| (changed)| `"high"` |
|
||||
| `fetchPriority=(empty string)`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(array with string)`| (changed)| `"high"` |
|
||||
| `fetchPriority=(empty array)`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(object)`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(numeric string)`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(-1)`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(0)`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(integer)`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(NaN)`| (initial, warning)| `"auto"` |
|
||||
| `fetchPriority=(float)`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(true)`| (initial, warning)| `"auto"` |
|
||||
| `fetchPriority=(false)`| (initial, warning)| `"auto"` |
|
||||
| `fetchPriority=(string 'true')`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(string 'false')`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(string 'on')`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(string 'off')`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(symbol)`| (initial, warning)| `"auto"` |
|
||||
| `fetchPriority=(function)`| (initial, warning)| `"auto"` |
|
||||
| `fetchPriority=(null)`| (initial)| `"auto"` |
|
||||
| `fetchPriority=(undefined)`| (initial)| `"auto"` |
|
||||
|
||||
## `fill` (on `<path>` inside `<svg>`)
|
||||
| Test Case | Flags | Result |
|
||||
| --- | --- | --- |
|
||||
|
|
@ -5123,7 +5048,7 @@
|
|||
| `htmlFor=(null)`| (initial)| `<empty string>` |
|
||||
| `htmlFor=(undefined)`| (initial)| `<empty string>` |
|
||||
|
||||
## `http-equiv` (on `<meta>` inside `<head>`)
|
||||
## `http-equiv` (on `<meta>` inside `<div>`)
|
||||
| Test Case | Flags | Result |
|
||||
| --- | --- | --- |
|
||||
| `http-equiv=(string)`| (changed, warning)| `"a string"` |
|
||||
|
|
@ -5148,7 +5073,7 @@
|
|||
| `http-equiv=(null)`| (initial, warning)| `<empty string>` |
|
||||
| `http-equiv=(undefined)`| (initial, warning)| `<empty string>` |
|
||||
|
||||
## `httpEquiv` (on `<meta>` inside `<head>`)
|
||||
## `httpEquiv` (on `<meta>` inside `<div>`)
|
||||
| Test Case | Flags | Result |
|
||||
| --- | --- | --- |
|
||||
| `httpEquiv=(string)`| (changed)| `"a string"` |
|
||||
|
|
@ -6198,31 +6123,6 @@
|
|||
| `lang=(null)`| (initial)| `<empty string>` |
|
||||
| `lang=(undefined)`| (initial)| `<empty string>` |
|
||||
|
||||
## `lang` (on `<html>` inside `<document>`)
|
||||
| Test Case | Flags | Result |
|
||||
| --- | --- | --- |
|
||||
| `lang=(string)`| (changed, ssr mismatch)| `"a string"` |
|
||||
| `lang=(empty string)`| (initial)| `<empty string>` |
|
||||
| `lang=(array with string)`| (changed, ssr mismatch)| `"string"` |
|
||||
| `lang=(empty array)`| (initial)| `<empty string>` |
|
||||
| `lang=(object)`| (changed, ssr mismatch)| `"result of toString()"` |
|
||||
| `lang=(numeric string)`| (changed, ssr mismatch)| `"42"` |
|
||||
| `lang=(-1)`| (changed, ssr mismatch)| `"-1"` |
|
||||
| `lang=(0)`| (changed, ssr mismatch)| `"0"` |
|
||||
| `lang=(integer)`| (changed, ssr mismatch)| `"1"` |
|
||||
| `lang=(NaN)`| (changed, warning, ssr mismatch)| `"NaN"` |
|
||||
| `lang=(float)`| (changed, ssr mismatch)| `"99.99"` |
|
||||
| `lang=(true)`| (initial, warning)| `<empty string>` |
|
||||
| `lang=(false)`| (initial, warning)| `<empty string>` |
|
||||
| `lang=(string 'true')`| (changed, ssr mismatch)| `"true"` |
|
||||
| `lang=(string 'false')`| (changed, ssr mismatch)| `"false"` |
|
||||
| `lang=(string 'on')`| (changed, ssr mismatch)| `"on"` |
|
||||
| `lang=(string 'off')`| (changed, ssr mismatch)| `"off"` |
|
||||
| `lang=(symbol)`| (initial, warning)| `<empty string>` |
|
||||
| `lang=(function)`| (initial, warning)| `<empty string>` |
|
||||
| `lang=(null)`| (initial)| `<empty string>` |
|
||||
| `lang=(undefined)`| (initial)| `<empty string>` |
|
||||
|
||||
## `length` (on `<div>` inside `<div>`)
|
||||
| Test Case | Flags | Result |
|
||||
| --- | --- | --- |
|
||||
|
|
@ -11398,56 +11298,6 @@
|
|||
| `transform=(null)`| (initial)| `[]` |
|
||||
| `transform=(undefined)`| (initial)| `[]` |
|
||||
|
||||
## `transform-origin` (on `<svg>` inside `<div>`)
|
||||
| Test Case | Flags | Result |
|
||||
| --- | --- | --- |
|
||||
| `transform-origin=(string)`| (changed, warning)| `"a string"` |
|
||||
| `transform-origin=(empty string)`| (changed, warning)| `<empty string>` |
|
||||
| `transform-origin=(array with string)`| (changed, warning)| `"string"` |
|
||||
| `transform-origin=(empty array)`| (changed, warning)| `<empty string>` |
|
||||
| `transform-origin=(object)`| (changed, warning)| `"result of toString()"` |
|
||||
| `transform-origin=(numeric string)`| (changed, warning)| `"42"` |
|
||||
| `transform-origin=(-1)`| (changed, warning)| `"-1"` |
|
||||
| `transform-origin=(0)`| (changed, warning)| `"0"` |
|
||||
| `transform-origin=(integer)`| (changed, warning)| `"1"` |
|
||||
| `transform-origin=(NaN)`| (changed, warning)| `"NaN"` |
|
||||
| `transform-origin=(float)`| (changed, warning)| `"99.99"` |
|
||||
| `transform-origin=(true)`| (initial, warning)| `<null>` |
|
||||
| `transform-origin=(false)`| (initial, warning)| `<null>` |
|
||||
| `transform-origin=(string 'true')`| (changed, warning)| `"true"` |
|
||||
| `transform-origin=(string 'false')`| (changed, warning)| `"false"` |
|
||||
| `transform-origin=(string 'on')`| (changed, warning)| `"on"` |
|
||||
| `transform-origin=(string 'off')`| (changed, warning)| `"off"` |
|
||||
| `transform-origin=(symbol)`| (initial, warning)| `<null>` |
|
||||
| `transform-origin=(function)`| (initial, warning)| `<null>` |
|
||||
| `transform-origin=(null)`| (initial, warning)| `<null>` |
|
||||
| `transform-origin=(undefined)`| (initial, warning)| `<null>` |
|
||||
|
||||
## `transformOrigin` (on `<svg>` inside `<div>`)
|
||||
| Test Case | Flags | Result |
|
||||
| --- | --- | --- |
|
||||
| `transformOrigin=(string)`| (changed)| `"a string"` |
|
||||
| `transformOrigin=(empty string)`| (changed)| `<empty string>` |
|
||||
| `transformOrigin=(array with string)`| (changed)| `"string"` |
|
||||
| `transformOrigin=(empty array)`| (changed)| `<empty string>` |
|
||||
| `transformOrigin=(object)`| (changed)| `"result of toString()"` |
|
||||
| `transformOrigin=(numeric string)`| (changed)| `"42"` |
|
||||
| `transformOrigin=(-1)`| (changed)| `"-1"` |
|
||||
| `transformOrigin=(0)`| (changed)| `"0"` |
|
||||
| `transformOrigin=(integer)`| (changed)| `"1"` |
|
||||
| `transformOrigin=(NaN)`| (changed, warning)| `"NaN"` |
|
||||
| `transformOrigin=(float)`| (changed)| `"99.99"` |
|
||||
| `transformOrigin=(true)`| (initial, warning)| `<null>` |
|
||||
| `transformOrigin=(false)`| (initial, warning)| `<null>` |
|
||||
| `transformOrigin=(string 'true')`| (changed)| `"true"` |
|
||||
| `transformOrigin=(string 'false')`| (changed)| `"false"` |
|
||||
| `transformOrigin=(string 'on')`| (changed)| `"on"` |
|
||||
| `transformOrigin=(string 'off')`| (changed)| `"off"` |
|
||||
| `transformOrigin=(symbol)`| (initial, warning)| `<null>` |
|
||||
| `transformOrigin=(function)`| (initial, warning)| `<null>` |
|
||||
| `transformOrigin=(null)`| (initial)| `<null>` |
|
||||
| `transformOrigin=(undefined)`| (initial)| `<null>` |
|
||||
|
||||
## `type` (on `<button>` inside `<div>`)
|
||||
| Test Case | Flags | Result |
|
||||
| --- | --- | --- |
|
||||
|
|
@ -12551,23 +12401,23 @@
|
|||
## `viewTarget` (on `<view>` inside `<svg>`)
|
||||
| Test Case | Flags | Result |
|
||||
| --- | --- | --- |
|
||||
| `viewTarget=(string)`| (changed)| `"a string"` |
|
||||
| `viewTarget=(empty string)`| (changed)| `<empty string>` |
|
||||
| `viewTarget=(array with string)`| (changed)| `"string"` |
|
||||
| `viewTarget=(empty array)`| (changed)| `<empty string>` |
|
||||
| `viewTarget=(object)`| (changed)| `"result of toString()"` |
|
||||
| `viewTarget=(numeric string)`| (changed)| `"42"` |
|
||||
| `viewTarget=(-1)`| (changed)| `"-1"` |
|
||||
| `viewTarget=(0)`| (changed)| `"0"` |
|
||||
| `viewTarget=(integer)`| (changed)| `"1"` |
|
||||
| `viewTarget=(NaN)`| (changed, warning)| `"NaN"` |
|
||||
| `viewTarget=(float)`| (changed)| `"99.99"` |
|
||||
| `viewTarget=(string)`| (changed, ssr mismatch)| `"a string"` |
|
||||
| `viewTarget=(empty string)`| (changed, ssr mismatch)| `<empty string>` |
|
||||
| `viewTarget=(array with string)`| (changed, ssr mismatch)| `"string"` |
|
||||
| `viewTarget=(empty array)`| (changed, ssr mismatch)| `<empty string>` |
|
||||
| `viewTarget=(object)`| (changed, ssr mismatch)| `"result of toString()"` |
|
||||
| `viewTarget=(numeric string)`| (changed, ssr mismatch)| `"42"` |
|
||||
| `viewTarget=(-1)`| (changed, ssr mismatch)| `"-1"` |
|
||||
| `viewTarget=(0)`| (changed, ssr mismatch)| `"0"` |
|
||||
| `viewTarget=(integer)`| (changed, ssr mismatch)| `"1"` |
|
||||
| `viewTarget=(NaN)`| (changed, warning, ssr mismatch)| `"NaN"` |
|
||||
| `viewTarget=(float)`| (changed, ssr mismatch)| `"99.99"` |
|
||||
| `viewTarget=(true)`| (initial, warning)| `<null>` |
|
||||
| `viewTarget=(false)`| (initial, warning)| `<null>` |
|
||||
| `viewTarget=(string 'true')`| (changed)| `"true"` |
|
||||
| `viewTarget=(string 'false')`| (changed)| `"false"` |
|
||||
| `viewTarget=(string 'on')`| (changed)| `"on"` |
|
||||
| `viewTarget=(string 'off')`| (changed)| `"off"` |
|
||||
| `viewTarget=(string 'true')`| (changed, ssr mismatch)| `"true"` |
|
||||
| `viewTarget=(string 'false')`| (changed, ssr mismatch)| `"false"` |
|
||||
| `viewTarget=(string 'on')`| (changed, ssr mismatch)| `"on"` |
|
||||
| `viewTarget=(string 'off')`| (changed, ssr mismatch)| `"off"` |
|
||||
| `viewTarget=(symbol)`| (initial, warning)| `<null>` |
|
||||
| `viewTarget=(function)`| (initial, warning)| `<null>` |
|
||||
| `viewTarget=(null)`| (initial)| `<null>` |
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
## Instructions
|
||||
|
||||
`yarn build --type=UMD_DEV react/index,react-dom && cd fixtures/attribute-behavior && yarn install && yarn dev`
|
||||
`yarn build --type=UMD_DEV react/index,react-dom && cd fixtures/attribute-behavior && yarn install && yarn start`
|
||||
|
||||
## Interpretation
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@
|
|||
"react-virtualized": "^9.9.0"
|
||||
},
|
||||
"scripts": {
|
||||
"predev":
|
||||
"cp ../../build/oss-experimental/react/umd/react.development.js public/ && cp ../../build/oss-experimental/react-dom/umd/react-dom.development.js public/ && cp ../../build/oss-experimental/react-dom/umd/react-dom-server-legacy.browser.development.js public/",
|
||||
"dev": "react-scripts start",
|
||||
"prestart":
|
||||
"cp ../../build/node_modules/react/umd/react.development.js public/ && cp ../../build/node_modules/react-dom/umd/react-dom.development.js public/ && cp ../../build/node_modules/react-dom/umd/react-dom-server-legacy.browser.development.js public/",
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test --env=jsdom",
|
||||
"eject": "react-scripts eject"
|
||||
|
|
|
|||
|
|
@ -237,8 +237,6 @@ function getRenderedAttributeValue(
|
|||
return document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
||||
} else if (containerTagName === 'document') {
|
||||
return document.implementation.createHTMLDocument('');
|
||||
} else if (containerTagName === 'head') {
|
||||
return document.implementation.createHTMLDocument('').head;
|
||||
} else {
|
||||
return document.createElement(containerTagName);
|
||||
}
|
||||
|
|
@ -284,12 +282,12 @@ function getRenderedAttributeValue(
|
|||
try {
|
||||
let container = createContainer();
|
||||
renderer.render(react.createElement(tagName, baseProps), container);
|
||||
defaultValue = read(container.lastChild);
|
||||
defaultValue = read(container.firstChild);
|
||||
canonicalDefaultValue = getCanonicalizedValue(defaultValue);
|
||||
|
||||
container = createContainer();
|
||||
renderer.render(react.createElement(tagName, props), container);
|
||||
result = read(container.lastChild);
|
||||
result = read(container.firstChild);
|
||||
canonicalResult = getCanonicalizedValue(result);
|
||||
didWarn = _didWarn;
|
||||
didError = false;
|
||||
|
|
@ -310,12 +308,6 @@ function getRenderedAttributeValue(
|
|||
);
|
||||
container = createContainer();
|
||||
container.innerHTML = html;
|
||||
} else if (containerTagName === 'head') {
|
||||
const html = serverRenderer.renderToString(
|
||||
react.createElement(tagName, props)
|
||||
);
|
||||
container = createContainer();
|
||||
container.innerHTML = html;
|
||||
} else {
|
||||
const html = serverRenderer.renderToString(
|
||||
react.createElement(
|
||||
|
|
@ -772,7 +764,7 @@ class App extends React.Component {
|
|||
ReactDOMStable:
|
||||
'https://unpkg.com/react-dom@latest/umd/react-dom.development.js',
|
||||
ReactDOMServerStable:
|
||||
'https://unpkg.com/react-dom@latest/umd/react-dom-server-legacy.browser.development.js',
|
||||
'https://unpkg.com/react-dom@latest/umd/react-dom-server.browser.development.js',
|
||||
ReactNext: '/react.development.js',
|
||||
ReactDOMNext: '/react-dom.development.js',
|
||||
ReactDOMServerNext: '/react-dom-server-legacy.browser.development.js',
|
||||
|
|
@ -910,9 +902,8 @@ class App extends React.Component {
|
|||
|
||||
let log = '';
|
||||
for (let attribute of attributes) {
|
||||
log += `## \`${attribute.name}\` (on \`<${
|
||||
attribute.tagName || 'div'
|
||||
}>\` inside \`<${attribute.containerTagName || 'div'}>\`)\n`;
|
||||
log += `## \`${attribute.name}\` (on \`<${attribute.tagName ||
|
||||
'div'}>\` inside \`<${attribute.containerTagName || 'div'}>\`)\n`;
|
||||
log += '| Test Case | Flags | Result |\n';
|
||||
log += '| --- | --- | --- |\n';
|
||||
|
||||
|
|
|
|||
|
|
@ -356,7 +356,7 @@ const attributes = [
|
|||
},
|
||||
{name: 'cols', tagName: 'textarea'},
|
||||
{name: 'colSpan', containerTagName: 'tr', tagName: 'td'},
|
||||
{name: 'content', containerTagName: 'head', tagName: 'meta'},
|
||||
{name: 'content', tagName: 'meta'},
|
||||
{name: 'contentEditable'},
|
||||
{
|
||||
name: 'contentScriptType',
|
||||
|
|
@ -573,24 +573,6 @@ const attributes = [
|
|||
tagName: 'path',
|
||||
read: getSVGAttribute('externalResourcesRequired'),
|
||||
},
|
||||
{
|
||||
name: 'fetchPriority',
|
||||
overrideStringValue: 'high',
|
||||
tagName: 'img',
|
||||
read: getProperty('fetchPriority'),
|
||||
},
|
||||
{
|
||||
name: 'fetchpriority',
|
||||
overrideStringValue: 'high',
|
||||
tagName: 'img',
|
||||
read: getProperty('fetchPriority'),
|
||||
},
|
||||
{
|
||||
name: 'fetchPriority',
|
||||
overrideStringValue: 'high',
|
||||
tagName: 'link',
|
||||
read: getProperty('fetchPriority'),
|
||||
},
|
||||
{
|
||||
name: 'fill',
|
||||
containerTagName: 'svg',
|
||||
|
|
@ -934,13 +916,8 @@ const attributes = [
|
|||
{name: 'href', tagName: 'a', overrideStringValue: 'https://reactjs.com'},
|
||||
{name: 'hrefLang', read: getAttribute('hreflang')},
|
||||
{name: 'htmlFor', tagName: 'label'},
|
||||
{
|
||||
name: 'http-equiv',
|
||||
containerTagName: 'head',
|
||||
tagName: 'meta',
|
||||
read: getProperty('httpEquiv'),
|
||||
},
|
||||
{name: 'httpEquiv', containerTagName: 'head', tagName: 'meta'},
|
||||
{name: 'http-equiv', tagName: 'meta', read: getProperty('httpEquiv')},
|
||||
{name: 'httpEquiv', tagName: 'meta'},
|
||||
{name: 'icon', tagName: 'command', read: getAttribute('icon')},
|
||||
{name: 'id'},
|
||||
{name: 'ID', read: getProperty('id')},
|
||||
|
|
@ -1081,7 +1058,6 @@ const attributes = [
|
|||
{name: 'label', tagName: 'track'},
|
||||
{name: 'LANG', read: getProperty('lang')},
|
||||
{name: 'lang'},
|
||||
{name: 'lang', containerTagName: 'document', tagName: 'html'},
|
||||
{name: 'length', read: getAttribute('length')},
|
||||
{
|
||||
name: 'lengthAdjust',
|
||||
|
|
@ -1987,16 +1963,6 @@ const attributes = [
|
|||
overrideStringValue:
|
||||
'translate(-10,-20) scale(2) rotate(45) translate(5,10)',
|
||||
},
|
||||
{
|
||||
name: 'transform-origin',
|
||||
tagName: 'svg',
|
||||
read: getSVGAttribute('transform-origin'),
|
||||
},
|
||||
{
|
||||
name: 'transformOrigin',
|
||||
tagName: 'svg',
|
||||
read: getSVGAttribute('transform-origin'),
|
||||
},
|
||||
{name: 'type', tagName: 'button', overrideStringValue: 'reset'},
|
||||
{
|
||||
name: 'type',
|
||||
|
|
|
|||
|
|
@ -5026,8 +5026,8 @@ qs@6.5.0:
|
|||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.0.tgz#8d04954d364def3efc55b5a0793e1e2c8b1e6e49"
|
||||
|
||||
qs@~6.4.0:
|
||||
version "6.4.1"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.1.tgz#2bad97710a5b661c366b378b1e3a44a592ff45e6"
|
||||
version "6.4.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
|
||||
|
||||
query-string@^4.1.0:
|
||||
version "4.3.4"
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
SKIP_PREFLIGHT_CHECK=true
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
{
|
||||
"posts": [
|
||||
{
|
||||
"id": 1,
|
||||
"userId": 2,
|
||||
"title": "Welcome",
|
||||
"body": "Hello, world!"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"userId": 3,
|
||||
"title": "A Guide to useEffect",
|
||||
"body": "Let me tell you everything about useEffect"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"userId": 1,
|
||||
"title": "Here and There",
|
||||
"body": "Browsers are smart"
|
||||
}
|
||||
],
|
||||
"comments": [
|
||||
{
|
||||
"id": 1,
|
||||
"body": "Hey there",
|
||||
"postId": 1,
|
||||
"userId": 1
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"body": "Welcome to the chat",
|
||||
"postId": 1,
|
||||
"userId": 2
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"body": "What editor/font are you using?",
|
||||
"postId": 2,
|
||||
"userId": 2
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"body": "It's always been hard",
|
||||
"postId": 3,
|
||||
"userId": 1
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"body": "It's still easy",
|
||||
"postId": 3,
|
||||
"userId": 2
|
||||
}
|
||||
],
|
||||
"users": [{
|
||||
"id": 1,
|
||||
"name": "Sebastian",
|
||||
"bioId": 10
|
||||
}, {
|
||||
"id": 2,
|
||||
"name": "Sophie",
|
||||
"bioId": 20
|
||||
}, {
|
||||
"id": 3,
|
||||
"name": "Dan",
|
||||
"bioId": 30
|
||||
}],
|
||||
"bios": [{
|
||||
"id": 10,
|
||||
"text": "I like European movies"
|
||||
}, {
|
||||
"id": 20,
|
||||
"text": "I like math puzzles"
|
||||
}, {
|
||||
"id": 30,
|
||||
"text": "I like reading twitter"
|
||||
}]
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
module.exports = (req, res, next) => {
|
||||
if (req.query.delay) {
|
||||
setTimeout(next, Number(req.query.delay));
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"name": "blocks",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"proxy": "http://localhost:3001/",
|
||||
"dependencies": {
|
||||
"concurrently": "^5.2.0",
|
||||
"json-server": "^0.16.1",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-scripts": "3.4.1"
|
||||
},
|
||||
"scripts": {
|
||||
"prestart": "cp -r ../../build/node_modules/* ./node_modules/",
|
||||
"prebuild": "cp -r ../../build/node_modules/* ./node_modules/",
|
||||
"start": "concurrently \"npm run start:client\" \"npm run start:api\"",
|
||||
"start:api": "json-server --watch db.json --port 3001 --delay 1000 --middlewares delay.js",
|
||||
"start:client": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Blocks Fixture</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React, {
|
||||
useReducer,
|
||||
useEffect,
|
||||
unstable_useTransition as useTransition,
|
||||
useCallback,
|
||||
useMemo,
|
||||
Suspense,
|
||||
} from 'react';
|
||||
import {createCache, CacheProvider} from 'react/unstable-cache';
|
||||
import {RouterProvider} from './client/RouterContext';
|
||||
// TODO: can't really import a server component on the client.
|
||||
import App from './server/App';
|
||||
|
||||
const initialUrl = window.location.pathname;
|
||||
const initialState = {
|
||||
// TODO: use this for invalidation.
|
||||
cache: createCache(),
|
||||
url: initialUrl,
|
||||
pendingUrl: initialUrl,
|
||||
root: <App route={initialUrl} />,
|
||||
};
|
||||
|
||||
function reducer(state, action) {
|
||||
switch (action.type) {
|
||||
case 'startNavigation':
|
||||
return {
|
||||
...state,
|
||||
pendingUrl: action.url,
|
||||
};
|
||||
case 'completeNavigation':
|
||||
// TODO: cancel previous fetch?
|
||||
return {
|
||||
...state,
|
||||
url: action.url,
|
||||
pendingUrl: action.url,
|
||||
root: action.root,
|
||||
};
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
|
||||
function Router() {
|
||||
const [state, dispatch] = useReducer(reducer, initialState);
|
||||
const [startTransition, isPending] = useTransition({
|
||||
timeoutMs: 1500,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
document.body.style.cursor = isPending ? 'wait' : '';
|
||||
}, [isPending]);
|
||||
|
||||
const navigate = useCallback(
|
||||
url => {
|
||||
startTransition(() => {
|
||||
// TODO: Here, There, and Everywhere.
|
||||
// TODO: Instant Transitions, somehow.
|
||||
dispatch({
|
||||
type: 'completeNavigation',
|
||||
root: <App route={url} />,
|
||||
url,
|
||||
});
|
||||
});
|
||||
dispatch({
|
||||
type: 'startNavigation',
|
||||
url,
|
||||
});
|
||||
},
|
||||
[startTransition]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const listener = () => {
|
||||
navigate(window.location.pathname);
|
||||
};
|
||||
window.addEventListener('popstate', listener);
|
||||
return () => window.removeEventListener('popstate', listener);
|
||||
}, [navigate]);
|
||||
|
||||
const routeContext = useMemo(
|
||||
() => ({
|
||||
pendingUrl: state.pendingUrl,
|
||||
url: state.url,
|
||||
navigate,
|
||||
}),
|
||||
[state.url, state.pendingUrl, navigate]
|
||||
);
|
||||
|
||||
return (
|
||||
<Suspense fallback={<h2>Loading...</h2>}>
|
||||
<CacheProvider value={state.cache}>
|
||||
<RouterProvider value={routeContext}>{state.root}</RouterProvider>
|
||||
</CacheProvider>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
export default Router;
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
import {useRouter} from './RouterContext';
|
||||
|
||||
export default function Link({to, children, ...rest}) {
|
||||
const {navigate} = useRouter();
|
||||
return (
|
||||
<a
|
||||
href={to}
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
window.history.pushState(null, null, to);
|
||||
navigate(to);
|
||||
}}
|
||||
{...rest}>
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
/* eslint-disable import/first */
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
import {TabBar, TabLink} from '../client/TabNav';
|
||||
|
||||
export default function ProfileNav({userId}) {
|
||||
// TODO: Don't hardcode ID.
|
||||
return (
|
||||
<TabBar>
|
||||
<TabLink to={`/profile/${userId}`}>Timeline</TabLink>
|
||||
<TabLink to={`/profile/${userId}/bio`}>Bio</TabLink>
|
||||
</TabBar>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import {createContext, useContext} from 'react';
|
||||
|
||||
const RouterContext = createContext(null);
|
||||
|
||||
export const RouterProvider = RouterContext.Provider;
|
||||
|
||||
export function useRouter() {
|
||||
return useContext(RouterContext);
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
import {TabBar, TabLink} from './TabNav';
|
||||
|
||||
// TODO: Error Boundaries.
|
||||
|
||||
function MainTabNav() {
|
||||
return (
|
||||
<TabBar>
|
||||
<TabLink to="/">Home</TabLink>
|
||||
<TabLink to="/profile/3" partial={true}>
|
||||
Profile
|
||||
</TabLink>
|
||||
</TabBar>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Shell({children}) {
|
||||
return (
|
||||
<>
|
||||
<MainTabNav />
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
import Link from './Link';
|
||||
import {useRouter} from './RouterContext';
|
||||
|
||||
export function TabBar({children}) {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
border: '1px solid #aaa',
|
||||
padding: 20,
|
||||
marginBottom: 20,
|
||||
width: 500,
|
||||
}}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function TabLink({to, partial, children}) {
|
||||
const {pendingUrl: activeUrl} = useRouter();
|
||||
const active = partial ? activeUrl.startsWith(to) : activeUrl === to;
|
||||
if (active) {
|
||||
return (
|
||||
<b
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
marginRight: 20,
|
||||
}}>
|
||||
{children}
|
||||
</b>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Link
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
marginRight: 20,
|
||||
}}
|
||||
to={to}>
|
||||
{children}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
body {
|
||||
font-family: Helvetica;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {createRoot} from 'react-dom/client';
|
||||
import './index.css';
|
||||
import Router from './Router';
|
||||
|
||||
createRoot(document.getElementById('root')).render(<Router />);
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
/* eslint-disable import/first */
|
||||
|
||||
import * as React from 'react';
|
||||
import {matchRoute} from './ServerRouter';
|
||||
import FeedPage from './FeedPage';
|
||||
import ProfilePage from './ProfilePage';
|
||||
|
||||
// TODO: Replace with asset reference.
|
||||
import Shell from '../client/Shell';
|
||||
|
||||
// TODO: Router component?
|
||||
const AppRoutes = {
|
||||
'/': props => <FeedPage {...props} key="home" />,
|
||||
'/profile/:userId/*': props => (
|
||||
<ProfilePage {...props} key={`profile-${props.userId}`} />
|
||||
),
|
||||
};
|
||||
|
||||
export default function App(props) {
|
||||
const match = matchRoute(props, AppRoutes);
|
||||
return <Shell>{match}</Shell>;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
/* eslint-disable import/first */
|
||||
|
||||
import * as React from 'react';
|
||||
import {fetch} from 'react-fetch';
|
||||
|
||||
// TODO: Replace with asset reference.
|
||||
import Link from '../client/Link';
|
||||
|
||||
export default function Comments({postId}) {
|
||||
const comments = fetch(`/comments?postId=${postId}&_expand=user`).json();
|
||||
return (
|
||||
<>
|
||||
<h5>Comments</h5>
|
||||
<ul>
|
||||
{comments.slice(0, 5).map(comment => (
|
||||
<li key={comment.id}>
|
||||
{comment.body}
|
||||
{' • '}
|
||||
<Link to={`/profile/${comment.user.id}`}>{comment.user.name}</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
/* eslint-disable import/first */
|
||||
|
||||
import * as React from 'react';
|
||||
import {fetch} from 'react-fetch';
|
||||
import PostList from './PostList';
|
||||
|
||||
export default function Feed() {
|
||||
const posts = fetch('/posts?_expand=user').json();
|
||||
return (
|
||||
<>
|
||||
<h2>Feed</h2>
|
||||
<PostList posts={posts} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
/* eslint-disable import/first */
|
||||
|
||||
import * as React from 'react';
|
||||
import {Suspense} from 'react';
|
||||
import PostGlimmer from './PostGlimmer';
|
||||
import Feed from './Feed';
|
||||
|
||||
export default function FeedPage() {
|
||||
return (
|
||||
<Suspense fallback={<PostGlimmer />}>
|
||||
<Feed />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
/* eslint-disable import/first */
|
||||
|
||||
import * as React from 'react';
|
||||
import {Suspense} from 'react';
|
||||
import Comments from './Comments';
|
||||
|
||||
// TODO: Replace with asset reference.
|
||||
import Link from '../client/Link';
|
||||
|
||||
export default function Post({post}) {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
border: '1px solid #aaa',
|
||||
borderRadius: 10,
|
||||
marginBottom: 20,
|
||||
padding: 20,
|
||||
maxWidth: 500,
|
||||
}}>
|
||||
<h4 style={{marginTop: 0}}>
|
||||
{post.title}
|
||||
{' by '}
|
||||
<Link to={`/profile/${post.user.id}`}>{post.user.name}</Link>
|
||||
</h4>
|
||||
<p>{post.body}</p>
|
||||
<Suspense
|
||||
fallback={<h5>Loading comments...</h5>}
|
||||
unstable_avoidThisFallback={true}>
|
||||
<Comments postId={post.id} />
|
||||
</Suspense>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
/* eslint-disable import/first */
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
export default function PostGlimmer() {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
border: '1px solid #aaa',
|
||||
borderRadius: 10,
|
||||
marginBottom: 20,
|
||||
padding: 20,
|
||||
maxWidth: 500,
|
||||
height: 180,
|
||||
}}>
|
||||
<div
|
||||
style={{
|
||||
marginBottom: 20,
|
||||
width: '50%',
|
||||
height: 20,
|
||||
background: '#ddd',
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
marginBottom: 20,
|
||||
width: '60%',
|
||||
height: 20,
|
||||
background: '#eee',
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
marginBottom: 20,
|
||||
width: '50%',
|
||||
height: 20,
|
||||
background: '#eee',
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
marginBottom: 20,
|
||||
width: '60%',
|
||||
height: 20,
|
||||
background: '#eee',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
/* eslint-disable import/first */
|
||||
|
||||
import * as React from 'react';
|
||||
import {Suspense, unstable_SuspenseList as SuspenseList} from 'react';
|
||||
import {preload} from 'react-fetch';
|
||||
import PostGlimmer from './PostGlimmer';
|
||||
import Post from './Post';
|
||||
|
||||
export default function PostList({posts}) {
|
||||
return (
|
||||
<SuspenseList revealOrder="forwards" tail="collapsed">
|
||||
{posts.map(post => {
|
||||
preload(`/comments?postId=${post.id}&_expand=user`);
|
||||
return (
|
||||
<Suspense key={post.id} fallback={<PostGlimmer />}>
|
||||
<Post post={post} />
|
||||
</Suspense>
|
||||
);
|
||||
})}
|
||||
</SuspenseList>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
/* eslint-disable import/first */
|
||||
|
||||
import * as React from 'react';
|
||||
import {fetch} from 'react-fetch';
|
||||
|
||||
export default function ProfileBio({userId}) {
|
||||
const user = fetch(`/users/${userId}`).json();
|
||||
const bio = fetch(`/bios/${user.bioId}`).json().text;
|
||||
return (
|
||||
<>
|
||||
<h3>{user.name}'s Bio</h3>
|
||||
<p>{bio}</p>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
import {Suspense} from 'react';
|
||||
import {fetch} from 'react-fetch';
|
||||
import {matchRoute} from './ServerRouter';
|
||||
import ProfileTimeline from './ProfileTimeline';
|
||||
import ProfileBio from './ProfileBio';
|
||||
|
||||
// TODO: Replace with asset reference.
|
||||
import ProfileNav from '../client/ProfileNav';
|
||||
|
||||
// TODO: Router component?
|
||||
const ProfileRoutes = {
|
||||
'/': props => <ProfileTimeline {...props} key="timeline" />,
|
||||
'/bio': props => <ProfileBio {...props} key="bio" />,
|
||||
};
|
||||
|
||||
export default function ProfilePage(props) {
|
||||
const user = fetch(`/users/${props.userId}`).json();
|
||||
const match = matchRoute(props, ProfileRoutes);
|
||||
return (
|
||||
<>
|
||||
<h2>{user.name}</h2>
|
||||
<ProfileNav userId={user.id} />
|
||||
<Suspense fallback={<h3>Loading...</h3>}>{match}</Suspense>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
/* eslint-disable import/first */
|
||||
|
||||
import * as React from 'react';
|
||||
import {fetch} from 'react-fetch';
|
||||
import PostList from './PostList';
|
||||
|
||||
export default function ProfileTimeline({userId}) {
|
||||
const posts = fetch(`/posts?userId=${userId}&_expand=user`).json();
|
||||
return <PostList posts={posts} />;
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
/* eslint-disable import/first */
|
||||
|
||||
function tryMatch(props, def) {
|
||||
const defSegments = def.split('/').filter(Boolean);
|
||||
const routeSegments = props.route.split('/').filter(Boolean);
|
||||
let innerProps = {...props};
|
||||
while (routeSegments.length > 0) {
|
||||
if (defSegments.length === 0) {
|
||||
return null;
|
||||
}
|
||||
const urlSegment = routeSegments.shift();
|
||||
const defSegment = defSegments.shift();
|
||||
if (urlSegment === defSegment) {
|
||||
continue;
|
||||
}
|
||||
if (defSegment[0] === ':') {
|
||||
innerProps[defSegment.slice(1)] = urlSegment;
|
||||
continue;
|
||||
}
|
||||
if (defSegment === '*') {
|
||||
innerProps.route = '/' + urlSegment + routeSegments.join('/');
|
||||
return innerProps;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (defSegments.length === 0) {
|
||||
return innerProps;
|
||||
}
|
||||
if (defSegments.length === 1 && defSegments[0] === '*') {
|
||||
innerProps.route = '/';
|
||||
return innerProps;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function matchRoute(props, defs) {
|
||||
for (let def in defs) {
|
||||
if (!defs.hasOwnProperty(def)) {
|
||||
continue;
|
||||
}
|
||||
const innerProps = tryMatch(props, def);
|
||||
if (innerProps) {
|
||||
const match = defs[def](innerProps);
|
||||
return match;
|
||||
}
|
||||
}
|
||||
throw Error('Not found.');
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -11,8 +11,8 @@
|
|||
"victory": "^0.25.6"
|
||||
},
|
||||
"scripts": {
|
||||
"copy-source": "cp -r ../../../build/oss-experimental/* ./node_modules/",
|
||||
"dev": "react-scripts start",
|
||||
"copy-source": "cp -r ../../../build/node_modules/* ./node_modules/",
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test --env=jsdom",
|
||||
"eject": "react-scripts eject"
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class App extends PureComponent {
|
|||
}
|
||||
const multiplier = input.length !== 0 ? input.length : 1;
|
||||
const complexity =
|
||||
(parseInt(window.location.search.slice(1), 10) / 100) * 25 || 25;
|
||||
(parseInt(window.location.search.substring(1), 10) / 100) * 25 || 25;
|
||||
const data = _.range(5).map(t =>
|
||||
_.range(complexity * multiplier).map((j, i) => {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -6536,9 +6536,9 @@ qs@6.7.0:
|
|||
integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
|
||||
|
||||
qs@~6.5.2:
|
||||
version "6.5.3"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad"
|
||||
integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==
|
||||
version "6.5.2"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
|
||||
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
|
||||
|
||||
query-string@^4.1.0:
|
||||
version "4.3.4"
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@
|
|||
<script src="https://unpkg.com/scheduler@canary/umd/scheduler-tracing.development.js"></script>
|
||||
<script src="https://unpkg.com/react@canary/umd/react.development.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@canary/umd/react-dom.development.js"></script>
|
||||
<script src="https://unpkg.com/react-cache@canary/umd/react-cache.development.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/react-cache@next/umd/react-cache.development.js"></script>
|
||||
|
||||
<!-- Don't use this in production: -->
|
||||
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
|
||||
</head>
|
||||
|
|
@ -38,4 +38,4 @@
|
|||
Learn more at https://reactjs.org/docs/getting-started.html
|
||||
-->
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
@ -11,12 +11,12 @@
|
|||
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
||||
</script>
|
||||
|
||||
<script src="https://unpkg.com/scheduler@canary/umd/scheduler.development.js"></script>
|
||||
<script src="https://unpkg.com/scheduler@canary/umd/scheduler-tracing.development.js"></script>
|
||||
<script src="https://unpkg.com/react@canary/umd/react.development.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@canary/umd/react-dom.development.js"></script>
|
||||
<script src="https://unpkg.com/react-cache@canary/umd/react-cache.development.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/scheduler@next/umd/scheduler.development.js"></script>
|
||||
<script src="https://unpkg.com/scheduler@next/umd/scheduler-tracing.development.js"></script>
|
||||
<script src="https://unpkg.com/react@next/umd/react.development.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@next/umd/react-dom.development.js"></script>
|
||||
<script src="https://unpkg.com/react-cache@next/umd/react-cache.development.js"></script>
|
||||
|
||||
<!-- Don't use this in production: -->
|
||||
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
|
||||
</head>
|
||||
|
|
@ -38,4 +38,4 @@
|
|||
Learn more at https://reactjs.org/docs/getting-started.html
|
||||
-->
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
/* eslint-disable react/react-in-jsx-scope, react/jsx-no-undef */
|
||||
/* eslint-disable no-fallthrough, react/react-in-jsx-scope, react/jsx-no-undef */
|
||||
/* global React ReactCache ReactDOM SchedulerTracing ScheduleTracing */
|
||||
|
||||
const apps = [];
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ const DEPENDENCIES = [
|
|||
['react-dom/umd/react-dom.development.js', 'react-dom.js'],
|
||||
];
|
||||
|
||||
const BUILD_DIRECTORY = '../../../build/oss-experimental/';
|
||||
const BUILD_DIRECTORY = '../../../build/node_modules/';
|
||||
const DEPENDENCIES_DIRECTORY = 'dependencies';
|
||||
|
||||
function initDependencies() {
|
||||
|
|
@ -39,7 +39,7 @@ function initServer() {
|
|||
const host = 'localhost';
|
||||
const port = 8000;
|
||||
|
||||
const requestListener = function (request, response) {
|
||||
const requestListener = function(request, response) {
|
||||
let contents;
|
||||
switch (request.url) {
|
||||
case '/react.js':
|
||||
|
|
|
|||
|
|
@ -334,11 +334,6 @@
|
|||
},
|
||||
});
|
||||
|
||||
class Foo {
|
||||
flag = false;
|
||||
object = {a: {b: {c: {d: 1}}}}
|
||||
}
|
||||
|
||||
function UnserializableProps() {
|
||||
return (
|
||||
<ChildComponent
|
||||
|
|
@ -348,7 +343,6 @@
|
|||
setOfSets={setOfSets}
|
||||
typedArray={typedArray}
|
||||
immutable={immutable}
|
||||
classInstance={new Foo()}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
"classnames": "^2.2.5",
|
||||
"codemirror": "^5.40.0",
|
||||
"core-js": "^2.4.1",
|
||||
"jest-diff": "^29.4.1",
|
||||
"jest-diff": "^25.1.0",
|
||||
"prop-types": "^15.6.0",
|
||||
"query-string": "^4.2.3",
|
||||
"react": "^15.4.1",
|
||||
|
|
@ -19,8 +19,8 @@
|
|||
"semver": "^5.5.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "react-scripts start",
|
||||
"predev": "cp ../../build/oss-stable/scheduler/umd/scheduler-unstable_mock.development.js ../../build/oss-stable/scheduler/umd/scheduler-unstable_mock.production.min.js ../../build/oss-stable/react/umd/react.development.js ../../build/oss-stable/react-dom/umd/react-dom.development.js ../../build/oss-stable/react/umd/react.production.min.js ../../build/oss-stable/react-dom/umd/react-dom.production.min.js ../../build/oss-stable/react-dom/umd/react-dom-server.browser.development.js ../../build/oss-stable/react-dom/umd/react-dom-server.browser.production.min.js ../../build/oss-stable/react-dom/umd/react-dom-test-utils.development.js ../../build/oss-stable/react-dom/umd/react-dom-test-utils.production.min.js public/ && cp -a ../../build/oss-stable/. node_modules",
|
||||
"start": "react-scripts start",
|
||||
"prestart": "cp ../../build/oss-stable/scheduler/umd/scheduler-unstable_mock.development.js ../../build/oss-stable/scheduler/umd/scheduler-unstable_mock.production.min.js ../../build/oss-stable/react/umd/react.development.js ../../build/oss-stable/react-dom/umd/react-dom.development.js ../../build/oss-stable/react/umd/react.production.min.js ../../build/oss-stable/react-dom/umd/react-dom.production.min.js ../../build/oss-stable/react-dom/umd/react-dom-server.browser.development.js ../../build/oss-stable/react-dom/umd/react-dom-server.browser.production.min.js ../../build/oss-stable/react-dom/umd/react-dom-test-utils.development.js ../../build/oss-stable/react-dom/umd/react-dom-test-utils.production.min.js public/ && cp -a ../../build/oss-stable/. node_modules",
|
||||
"build": "react-scripts build && cp build/index.html build/200.html",
|
||||
"test": "react-scripts test --env=jsdom",
|
||||
"eject": "react-scripts eject"
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
(function() {
|
||||
var Fixture = null;
|
||||
var output = document.getElementById('output');
|
||||
var status = document.getElementById('status');
|
||||
|
|
@ -60,7 +60,7 @@
|
|||
setStatus('Generating markup');
|
||||
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
.then(function() {
|
||||
const element = createElement(Fixture);
|
||||
|
||||
// Server rendering moved to a separate package along with ReactDOM
|
||||
|
|
@ -80,11 +80,11 @@
|
|||
}
|
||||
|
||||
// Finally, React 0.4 and lower emits markup in a callback
|
||||
return new Promise(function (resolve) {
|
||||
return new Promise(function(resolve) {
|
||||
React.renderComponentToString(element, resolve);
|
||||
});
|
||||
})
|
||||
.then(function (string) {
|
||||
.then(function(string) {
|
||||
output.innerHTML = string;
|
||||
setStatus('Markup only (No React)');
|
||||
})
|
||||
|
|
@ -124,13 +124,13 @@
|
|||
}
|
||||
|
||||
function loadScript(src) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var script = document.createElement('script');
|
||||
script.async = true;
|
||||
script.src = src;
|
||||
|
||||
script.onload = resolve;
|
||||
script.onerror = function (error) {
|
||||
script.onerror = function(error) {
|
||||
reject(new Error('Unable to load ' + src));
|
||||
};
|
||||
|
||||
|
|
@ -145,7 +145,7 @@
|
|||
setStatus('Failed');
|
||||
output.innerHTML = 'Please name your root component "Fixture"';
|
||||
} else {
|
||||
prerender().then(function () {
|
||||
prerender().then(function() {
|
||||
if (getBooleanQueryParam('hydrate')) {
|
||||
render();
|
||||
}
|
||||
|
|
@ -161,14 +161,14 @@
|
|||
|
||||
window.onerror = handleError;
|
||||
|
||||
reload.onclick = function () {
|
||||
reload.onclick = function() {
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
hydrate.onclick = render;
|
||||
|
||||
loadScript(getQueryParam('reactPath'))
|
||||
.then(function () {
|
||||
.then(function() {
|
||||
if (needsReactDOM) {
|
||||
return Promise.all([
|
||||
loadScript(getQueryParam('reactDOMPath')),
|
||||
|
|
@ -176,12 +176,12 @@
|
|||
]);
|
||||
}
|
||||
})
|
||||
.then(function () {
|
||||
.then(function() {
|
||||
if (failed) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener('message', function (event) {
|
||||
window.addEventListener('message', function(event) {
|
||||
var data = JSON.parse(event.data);
|
||||
|
||||
switch (data.type) {
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ class TrySilenceFatalError extends React.Component {
|
|||
|
||||
function naiveMemoize(fn) {
|
||||
let memoizedEntry;
|
||||
return function () {
|
||||
return function() {
|
||||
if (!memoizedEntry) {
|
||||
memoizedEntry = {result: null};
|
||||
memoizedEntry.result = fn();
|
||||
|
|
@ -251,7 +251,7 @@ function naiveMemoize(fn) {
|
|||
return memoizedEntry.result;
|
||||
};
|
||||
}
|
||||
let memoizedFunction = naiveMemoize(function () {
|
||||
let memoizedFunction = naiveMemoize(function() {
|
||||
throw new Error('Passed');
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export class CodeEditor extends React.Component {
|
|||
lineNumbers: true,
|
||||
});
|
||||
|
||||
this.editor.on('change', function (doc) {
|
||||
this.editor.on('change', function(doc) {
|
||||
onChange(doc.getValue());
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ const ReactDOM = window.ReactDOM;
|
|||
const MouseEnter = () => {
|
||||
const containerRef = React.useRef();
|
||||
|
||||
React.useEffect(function () {
|
||||
React.useEffect(function() {
|
||||
const hostEl = containerRef.current;
|
||||
ReactDOM.render(<MouseEnterDetect />, hostEl, () => {
|
||||
ReactDOM.render(<MouseEnterDetect />, hostEl.childNodes[1]);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import 'core-js/es6/map';
|
|||
|
||||
// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
|
||||
// MIT license
|
||||
(function () {
|
||||
(function() {
|
||||
var lastTime = 0;
|
||||
var vendors = ['ms', 'moz', 'webkit', 'o'];
|
||||
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
|
||||
|
|
@ -19,10 +19,10 @@ import 'core-js/es6/map';
|
|||
}
|
||||
|
||||
if (!window.requestAnimationFrame)
|
||||
window.requestAnimationFrame = function (callback, element) {
|
||||
window.requestAnimationFrame = function(callback, element) {
|
||||
var currTime = new Date().getTime();
|
||||
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
|
||||
var id = window.setTimeout(function () {
|
||||
var id = window.setTimeout(function() {
|
||||
callback(currTime + timeToCall);
|
||||
}, timeToCall);
|
||||
lastTime = currTime + timeToCall;
|
||||
|
|
@ -30,7 +30,7 @@ import 'core-js/es6/map';
|
|||
};
|
||||
|
||||
if (!window.cancelAnimationFrame)
|
||||
window.cancelAnimationFrame = function (id) {
|
||||
window.cancelAnimationFrame = function(id) {
|
||||
clearTimeout(id);
|
||||
};
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import semver from 'semver';
|
|||
|
||||
function parseQuery(qstr) {
|
||||
var query = {};
|
||||
var a = qstr.slice(1).split('&');
|
||||
var a = qstr.substr(1).split('&');
|
||||
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
var b = a[i].split('=');
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// copied from scripts/jest/matchers/toWarnDev.js
|
||||
'use strict';
|
||||
|
||||
const {diff: jestDiff} = require('jest-diff');
|
||||
const jestDiff = require('jest-diff').default;
|
||||
const util = require('util');
|
||||
|
||||
function shouldIgnoreConsoleError(format, args) {
|
||||
|
|
|
|||
|
|
@ -7,17 +7,47 @@
|
|||
resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.12.10.tgz#f77f6750d0ab88c7c23234dd2d2f3800f170a573"
|
||||
integrity sha512-e3sJ7uwwjiGWv7qeATKrP+Mjltr6JEurPh3yR0dBb9ie2YDnKl52lO82f+Ha+HAtyxTHfsPIXwgFmWKsCT2zOQ==
|
||||
|
||||
"@jest/schemas@^29.4.0":
|
||||
version "29.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.4.0.tgz#0d6ad358f295cc1deca0b643e6b4c86ebd539f17"
|
||||
integrity sha512-0E01f/gOZeNTG76i5eWWSupvSHaIINrTie7vCyjiYFKgzNdyEGd12BUv4oNBFHOqlHDbtoJi3HrQ38KCC90NsQ==
|
||||
"@jest/types@^25.5.0":
|
||||
version "25.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@jest/types/-/types-25.5.0.tgz#4d6a4793f7b9599fc3680877b856a97dbccf2a9d"
|
||||
integrity sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw==
|
||||
dependencies:
|
||||
"@sinclair/typebox" "^0.25.16"
|
||||
"@types/istanbul-lib-coverage" "^2.0.0"
|
||||
"@types/istanbul-reports" "^1.1.1"
|
||||
"@types/yargs" "^15.0.0"
|
||||
chalk "^3.0.0"
|
||||
|
||||
"@sinclair/typebox@^0.25.16":
|
||||
version "0.25.21"
|
||||
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.21.tgz#763b05a4b472c93a8db29b2c3e359d55b29ce272"
|
||||
integrity sha512-gFukHN4t8K4+wVC+ECqeqwzBDeFeTzBXroBTqE6vcWrQGbEUpHO7LYdG0f4xnvYq4VOEwITSlHlp0JBAIFMS/g==
|
||||
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762"
|
||||
integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==
|
||||
|
||||
"@types/istanbul-lib-report@*":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686"
|
||||
integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==
|
||||
dependencies:
|
||||
"@types/istanbul-lib-coverage" "*"
|
||||
|
||||
"@types/istanbul-reports@^1.1.1":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz#e875cc689e47bce549ec81f3df5e6f6f11cfaeb2"
|
||||
integrity sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==
|
||||
dependencies:
|
||||
"@types/istanbul-lib-coverage" "*"
|
||||
"@types/istanbul-lib-report" "*"
|
||||
|
||||
"@types/yargs-parser@*":
|
||||
version "15.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d"
|
||||
integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==
|
||||
|
||||
"@types/yargs@^15.0.0":
|
||||
version "15.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.11.tgz#361d7579ecdac1527687bcebf9946621c12ab78c"
|
||||
integrity sha512-jfcNBxHFYJ4nPIacsi3woz1+kvUO6s1CyeEhtnDHBjHUMNj5UlW2GynmnSgiJJEdNg9yW5C8lfoNRZrHGv5EqA==
|
||||
dependencies:
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
abab@^1.0.3:
|
||||
version "1.0.4"
|
||||
|
|
@ -154,6 +184,11 @@ ansi-regex@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
|
||||
integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
|
||||
|
||||
ansi-regex@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
|
||||
integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
|
||||
|
||||
ansi-styles@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
|
||||
|
|
@ -166,18 +201,13 @@ ansi-styles@^3.0.0, ansi-styles@^3.2.1:
|
|||
dependencies:
|
||||
color-convert "^1.9.0"
|
||||
|
||||
ansi-styles@^4.1.0:
|
||||
ansi-styles@^4.0.0, ansi-styles@^4.1.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
|
||||
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
|
||||
dependencies:
|
||||
color-convert "^2.0.1"
|
||||
|
||||
ansi-styles@^5.0.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b"
|
||||
integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==
|
||||
|
||||
anymatch@^1.3.0:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a"
|
||||
|
|
@ -1625,10 +1655,10 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1:
|
|||
escape-string-regexp "^1.0.5"
|
||||
supports-color "^5.3.0"
|
||||
|
||||
chalk@^4.0.0:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
|
||||
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
|
||||
chalk@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
|
||||
integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==
|
||||
dependencies:
|
||||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
|
@ -2379,10 +2409,10 @@ detect-port-alt@1.1.6:
|
|||
address "^1.0.1"
|
||||
debug "^2.6.0"
|
||||
|
||||
diff-sequences@^29.3.1:
|
||||
version "29.3.1"
|
||||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.3.1.tgz#104b5b95fe725932421a9c6e5b4bef84c3f2249e"
|
||||
integrity sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==
|
||||
diff-sequences@^25.2.6:
|
||||
version "25.2.6"
|
||||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd"
|
||||
integrity sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg==
|
||||
|
||||
diff@^3.2.0:
|
||||
version "3.5.0"
|
||||
|
|
@ -4569,15 +4599,15 @@ jest-diff@^20.0.3:
|
|||
jest-matcher-utils "^20.0.3"
|
||||
pretty-format "^20.0.3"
|
||||
|
||||
jest-diff@^29.4.1:
|
||||
version "29.4.1"
|
||||
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.4.1.tgz#9a6dc715037e1fa7a8a44554e7d272088c4029bd"
|
||||
integrity sha512-uazdl2g331iY56CEyfbNA0Ut7Mn2ulAG5vUaEHXycf1L6IPyuImIxSz4F0VYBKi7LYIuxOwTZzK3wh5jHzASMw==
|
||||
jest-diff@^25.1.0:
|
||||
version "25.5.0"
|
||||
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.5.0.tgz#1dd26ed64f96667c068cef026b677dfa01afcfa9"
|
||||
integrity sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A==
|
||||
dependencies:
|
||||
chalk "^4.0.0"
|
||||
diff-sequences "^29.3.1"
|
||||
jest-get-type "^29.2.0"
|
||||
pretty-format "^29.4.1"
|
||||
chalk "^3.0.0"
|
||||
diff-sequences "^25.2.6"
|
||||
jest-get-type "^25.2.6"
|
||||
pretty-format "^25.5.0"
|
||||
|
||||
jest-docblock@^20.0.3:
|
||||
version "20.0.3"
|
||||
|
|
@ -4601,10 +4631,10 @@ jest-environment-node@^20.0.3:
|
|||
jest-mock "^20.0.3"
|
||||
jest-util "^20.0.3"
|
||||
|
||||
jest-get-type@^29.2.0:
|
||||
version "29.2.0"
|
||||
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.2.0.tgz#726646f927ef61d583a3b3adb1ab13f3a5036408"
|
||||
integrity sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==
|
||||
jest-get-type@^25.2.6:
|
||||
version "25.2.6"
|
||||
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.2.6.tgz#0b0a32fab8908b44d508be81681487dbabb8d877"
|
||||
integrity sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==
|
||||
|
||||
jest-haste-map@^20.0.4:
|
||||
version "20.0.5"
|
||||
|
|
@ -6329,14 +6359,15 @@ pretty-format@^20.0.3:
|
|||
ansi-regex "^2.1.1"
|
||||
ansi-styles "^3.0.0"
|
||||
|
||||
pretty-format@^29.4.1:
|
||||
version "29.4.1"
|
||||
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.4.1.tgz#0da99b532559097b8254298da7c75a0785b1751c"
|
||||
integrity sha512-dt/Z761JUVsrIKaY215o1xQJBGlSmTx/h4cSqXqjHLnU1+Kt+mavVE7UgqJJO5ukx5HjSswHfmXz4LjS2oIJfg==
|
||||
pretty-format@^25.5.0:
|
||||
version "25.5.0"
|
||||
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.5.0.tgz#7873c1d774f682c34b8d48b6743a2bf2ac55791a"
|
||||
integrity sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ==
|
||||
dependencies:
|
||||
"@jest/schemas" "^29.4.0"
|
||||
ansi-styles "^5.0.0"
|
||||
react-is "^18.0.0"
|
||||
"@jest/types" "^25.5.0"
|
||||
ansi-regex "^5.0.0"
|
||||
ansi-styles "^4.0.0"
|
||||
react-is "^16.12.0"
|
||||
|
||||
private@^0.1.6, private@^0.1.7, private@^0.1.8:
|
||||
version "0.1.8"
|
||||
|
|
@ -6564,16 +6595,11 @@ react-error-overlay@^4.0.1:
|
|||
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-4.0.1.tgz#417addb0814a90f3a7082eacba7cee588d00da89"
|
||||
integrity sha512-xXUbDAZkU08aAkjtUvldqbvI04ogv+a1XdHxvYuHPYKIVk/42BIOD0zSKTHAWV4+gDy3yGm283z2072rA2gdtw==
|
||||
|
||||
react-is@^16.8.1:
|
||||
react-is@^16.12.0, react-is@^16.8.1:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||
|
||||
react-is@^18.0.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
|
||||
integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
|
||||
|
||||
react-scripts@^1.0.11:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-1.1.5.tgz#3041610ab0826736b52197711a4c4e3756e97768"
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ function reload() {
|
|||
}
|
||||
}
|
||||
// Point to the built version.
|
||||
build = require('../../../build/oss-experimental/eslint-plugin-react-hooks');
|
||||
build = require('../../../build/node_modules/eslint-plugin-react-hooks');
|
||||
}
|
||||
|
||||
let rules = {};
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
"react-scripts": "1.0.17"
|
||||
},
|
||||
"scripts": {
|
||||
"predev":
|
||||
"cp ../../build/oss-experimental/react/umd/react.development.js public/ && cp ../../build/oss-experimental/react-dom/umd/react-dom.development.js public/",
|
||||
"dev": "react-scripts start",
|
||||
"prestart":
|
||||
"cp ../../build/node_modules/react/umd/react.development.js public/ && cp ../../build/node_modules/react-dom/umd/react-dom.development.js public/",
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test --env=jsdom",
|
||||
"eject": "react-scripts eject"
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
"react-motion": "^0.5.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "react-scripts start",
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ function Graph(props) {
|
|||
});
|
||||
|
||||
var edgeLabels = {};
|
||||
React.Children.forEach(props.children, function (child) {
|
||||
React.Children.forEach(props.children, function(child) {
|
||||
if (!child) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
If you checked out the source from GitHub make sure to run <code>npm run build</code>.
|
||||
</p>
|
||||
</div>
|
||||
<script src="../../build/oss-experimental/react/umd/react.development.js"></script>
|
||||
<script src="../../build/oss-experimental/react-dom/umd/react-dom.development.js"></script>
|
||||
<script src="../../build/node_modules/react/umd/react.development.js"></script>
|
||||
<script src="../../build/node_modules/react-dom/umd/react-dom.development.js"></script>
|
||||
<script src="https://unpkg.com/babel-standalone@6/babel.js"></script>
|
||||
<script type="text/babel">
|
||||
var dotStyle = {
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@
|
|||
If you checked out the source from GitHub make sure to run <code>npm run build</code>.
|
||||
</p>
|
||||
</div>
|
||||
<script src="../../build/oss-experimental/react/umd/react.development.js"></script>
|
||||
<script src="../../build/oss-experimental/react-dom/umd/react-dom.development.js"></script>
|
||||
<script src="../../build/oss-experimental/react-dom/umd/react-dom-server.browser.development.js"></script>
|
||||
<script src="../../build/node_modules/react/umd/react.development.js"></script>
|
||||
<script src="../../build/node_modules/react-dom/umd/react-dom.development.js"></script>
|
||||
<script src="../../build/node_modules/react-dom/umd/react-dom-server.browser.development.js"></script>
|
||||
<script src="https://unpkg.com/babel-standalone@6/babel.js"></script>
|
||||
<script type="text/babel">
|
||||
async function render() {
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@
|
|||
"concurrently": "^5.3.0",
|
||||
"express": "^4.17.1",
|
||||
"nodemon": "^2.0.6",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react": "link:../../build/node_modules/react",
|
||||
"react-dom": "link:../../build/node_modules/react-dom",
|
||||
"react-error-boundary": "^3.1.3",
|
||||
"resolve": "1.12.0",
|
||||
"rimraf": "^3.0.2",
|
||||
|
|
@ -28,14 +28,12 @@
|
|||
"prettier": "1.19.1"
|
||||
},
|
||||
"scripts": {
|
||||
"predev": "cp -r ../../build/oss-experimental/* ./node_modules/",
|
||||
"prestart": "cp -r ../../build/oss-experimental/* ./node_modules/",
|
||||
"dev": "concurrently \"npm run dev:server\" \"npm run dev:bundler\"",
|
||||
"start": "concurrently \"npm run start:server\" \"npm run start:bundler\"",
|
||||
"dev:server": "cross-env NODE_ENV=development nodemon -- --inspect server/server.js",
|
||||
"start:server": "cross-env NODE_ENV=production nodemon -- server/server.js",
|
||||
"dev:bundler": "cross-env NODE_ENV=development nodemon -- scripts/build.js",
|
||||
"start:bundler": "cross-env NODE_ENV=production nodemon -- scripts/build.js"
|
||||
"start": "concurrently \"npm run server:dev\" \"npm run bundler:dev\"",
|
||||
"start:prod": "concurrently \"npm run server:prod\" \"npm run bundler:prod\"",
|
||||
"server:dev": "cross-env NODE_ENV=development nodemon -- --inspect server/server.js",
|
||||
"server:prod": "cross-env NODE_ENV=production nodemon -- server/server.js",
|
||||
"bundler:dev": "cross-env NODE_ENV=development nodemon -- scripts/build.js",
|
||||
"bundler:prod": "cross-env NODE_ENV=production nodemon -- scripts/build.js"
|
||||
},
|
||||
"babel": {
|
||||
"presets": [
|
||||
|
|
|
|||
|
|
@ -30,28 +30,28 @@ const app = express();
|
|||
app.use(compress());
|
||||
app.get(
|
||||
'/',
|
||||
handleErrors(async function (req, res) {
|
||||
handleErrors(async function(req, res) {
|
||||
await waitForWebpack();
|
||||
renderToStream(req.url, res);
|
||||
})
|
||||
);
|
||||
app.get(
|
||||
'/string',
|
||||
handleErrors(async function (req, res) {
|
||||
handleErrors(async function(req, res) {
|
||||
await waitForWebpack();
|
||||
renderToString(req.url, res);
|
||||
})
|
||||
);
|
||||
app.get(
|
||||
'/stream',
|
||||
handleErrors(async function (req, res) {
|
||||
handleErrors(async function(req, res) {
|
||||
await waitForWebpack();
|
||||
renderToStream(req.url, res);
|
||||
})
|
||||
);
|
||||
app.get(
|
||||
'/buffer',
|
||||
handleErrors(async function (req, res) {
|
||||
handleErrors(async function(req, res) {
|
||||
await waitForWebpack();
|
||||
renderToBuffer(req.url, res);
|
||||
})
|
||||
|
|
@ -63,7 +63,7 @@ app
|
|||
.listen(PORT, () => {
|
||||
console.log(`Listening at ${PORT}...`);
|
||||
})
|
||||
.on('error', function (error) {
|
||||
.on('error', function(error) {
|
||||
if (error.syscall !== 'listen') {
|
||||
throw error;
|
||||
}
|
||||
|
|
@ -84,7 +84,7 @@ app
|
|||
});
|
||||
|
||||
function handleErrors(fn) {
|
||||
return async function (req, res, next) {
|
||||
return async function(req, res, next) {
|
||||
try {
|
||||
return await fn(req, res);
|
||||
} catch (x) {
|
||||
|
|
|
|||
|
|
@ -3171,7 +3171,7 @@ isobject@^3.0.0, isobject@^3.0.1:
|
|||
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
|
||||
integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
|
||||
|
||||
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
|
||||
js-tokens@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||
|
|
@ -3295,13 +3295,6 @@ lodash@^4.17.15, lodash@^4.17.19:
|
|||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
||||
loose-envify@^1.1.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||
dependencies:
|
||||
js-tokens "^3.0.0 || ^4.0.0"
|
||||
|
||||
lowercase-keys@^1.0.0, lowercase-keys@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
|
||||
|
|
@ -4090,13 +4083,8 @@ rc@^1.2.8:
|
|||
minimist "^1.2.0"
|
||||
strip-json-comments "~2.0.1"
|
||||
|
||||
react-dom@^18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
|
||||
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
scheduler "^0.23.0"
|
||||
"react-dom@link:../../build/node_modules/react-dom":
|
||||
version "0.0.0"
|
||||
|
||||
react-error-boundary@^3.1.3:
|
||||
version "3.1.4"
|
||||
|
|
@ -4105,12 +4093,8 @@ react-error-boundary@^3.1.3:
|
|||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
|
||||
react@^18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
|
||||
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
"react@link:../../build/node_modules/react":
|
||||
version "0.0.0"
|
||||
|
||||
read-pkg@^4.0.1:
|
||||
version "4.0.1"
|
||||
|
|
@ -4369,13 +4353,6 @@ safe-regex@^1.1.0:
|
|||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||
|
||||
scheduler@^0.23.0:
|
||||
version "0.23.0"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
|
||||
integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
|
||||
schema-utils@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770"
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@
|
|||
If you checked out the source from GitHub make sure to run <code>npm run build</code>.
|
||||
</p>
|
||||
</div>
|
||||
<script src="../../build/oss-experimental/react/umd/react.development.js"></script>
|
||||
<script src="../../build/oss-experimental/react-dom/umd/react-dom.development.js"></script>
|
||||
<script src="../../build/oss-experimental/react-dom/umd/react-dom-server.browser.development.js"></script>
|
||||
<script src="../../build/oss-experimental/react-server-dom-webpack/umd/react-server-dom-webpack-server.browser.development.js"></script>
|
||||
<script src="../../build/oss-experimental/react-server-dom-webpack/umd/react-server-dom-webpack-client.browser.development.js"></script>
|
||||
<script src="../../build/node_modules/react/umd/react.development.js"></script>
|
||||
<script src="../../build/node_modules/react-dom/umd/react-dom.development.js"></script>
|
||||
<script src="../../build/node_modules/react-dom/umd/react-dom-server.browser.development.js"></script>
|
||||
<script src="../../build/node_modules/react-server-dom-webpack/umd/react-server-dom-webpack-server.browser.development.js"></script>
|
||||
<script src="../../build/node_modules/react-server-dom-webpack/umd/react-server-dom-webpack.development.js"></script>
|
||||
<script src="https://unpkg.com/babel-standalone@6/babel.js"></script>
|
||||
<script type="text/babel">
|
||||
let Suspense = React.Suspense;
|
||||
|
|
@ -60,7 +60,7 @@
|
|||
content: <HTML />,
|
||||
};
|
||||
|
||||
let stream = ReactServerDOMServer.renderToReadableStream(model);
|
||||
let stream = ReactServerDOMWriter.renderToReadableStream(model);
|
||||
let response = new Response(stream, {
|
||||
headers: {'Content-Type': 'text/html'},
|
||||
});
|
||||
|
|
@ -70,13 +70,13 @@
|
|||
let blob = await responseToDisplay.blob();
|
||||
let url = URL.createObjectURL(blob);
|
||||
|
||||
let data = ReactServerDOMClient.createFromFetch(
|
||||
let data = ReactServerDOMReader.createFromFetch(
|
||||
fetch(url)
|
||||
);
|
||||
// The client also supports XHR streaming.
|
||||
// var xhr = new XMLHttpRequest();
|
||||
// xhr.open('GET', url);
|
||||
// let data = ReactServerDOMClient.createFromXHR(xhr);
|
||||
// let data = ReactServerDOMReader.createFromXHR(xhr);
|
||||
// xhr.send();
|
||||
|
||||
renderResult(data);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
# production
|
||||
/build
|
||||
/dist
|
||||
.eslintcache
|
||||
|
||||
# misc
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const crypto = require('crypto');
|
||||
const chalk = require('react-dev-utils/chalk');
|
||||
const paths = require('./paths');
|
||||
|
||||
// Ensure the certificate and key provided are valid and if not
|
||||
// throw an easy to debug error
|
||||
function validateKeyAndCerts({cert, key, keyFile, crtFile}) {
|
||||
let encrypted;
|
||||
try {
|
||||
// publicEncrypt will throw an error with an invalid cert
|
||||
encrypted = crypto.publicEncrypt(cert, Buffer.from('test'));
|
||||
} catch (err) {
|
||||
throw new Error(
|
||||
`The certificate "${chalk.yellow(crtFile)}" is invalid.\n${err.message}`
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
// privateDecrypt will throw an error with an invalid key
|
||||
crypto.privateDecrypt(key, encrypted);
|
||||
} catch (err) {
|
||||
throw new Error(
|
||||
`The certificate key "${chalk.yellow(keyFile)}" is invalid.\n${
|
||||
err.message
|
||||
}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Read file and throw an error if it doesn't exist
|
||||
function readEnvFile(file, type) {
|
||||
if (!fs.existsSync(file)) {
|
||||
throw new Error(
|
||||
`You specified ${chalk.cyan(
|
||||
type
|
||||
)} in your env, but the file "${chalk.yellow(file)}" can't be found.`
|
||||
);
|
||||
}
|
||||
return fs.readFileSync(file);
|
||||
}
|
||||
|
||||
// Get the https config
|
||||
// Return cert files if provided in env, otherwise just true or false
|
||||
function getHttpsConfig() {
|
||||
const {SSL_CRT_FILE, SSL_KEY_FILE, HTTPS} = process.env;
|
||||
const isHttps = HTTPS === 'true';
|
||||
|
||||
if (isHttps && SSL_CRT_FILE && SSL_KEY_FILE) {
|
||||
const crtFile = path.resolve(paths.appPath, SSL_CRT_FILE);
|
||||
const keyFile = path.resolve(paths.appPath, SSL_KEY_FILE);
|
||||
const config = {
|
||||
cert: readEnvFile(crtFile, 'SSL_CRT_FILE'),
|
||||
key: readEnvFile(keyFile, 'SSL_KEY_FILE'),
|
||||
};
|
||||
|
||||
validateKeyAndCerts({...config, keyFile, crtFile});
|
||||
return config;
|
||||
}
|
||||
return isHttps;
|
||||
}
|
||||
|
||||
module.exports = getHttpsConfig;
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const paths = require('./paths');
|
||||
const chalk = require('chalk');
|
||||
const chalk = require('react-dev-utils/chalk');
|
||||
const resolve = require('resolve');
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ module.exports = {
|
|||
appPath: resolveApp('.'),
|
||||
appBuild: resolveApp(buildPath),
|
||||
appPublic: resolveApp('public'),
|
||||
appHtml: resolveApp('public/index.html'),
|
||||
appIndexJs: resolveModule(resolveApp, 'src/index'),
|
||||
appPackageJson: resolveApp('package.json'),
|
||||
appSrc: resolveApp('src'),
|
||||
|
|
@ -63,6 +64,7 @@ module.exports = {
|
|||
appJsConfig: resolveApp('jsconfig.json'),
|
||||
yarnLockFile: resolveApp('yarn.lock'),
|
||||
testsSetup: resolveModule(resolveApp, 'src/setupTests'),
|
||||
proxySetup: resolveApp('src/setupProxy.js'),
|
||||
appNodeModules: resolveApp('node_modules'),
|
||||
appWebpackCache: resolveApp('node_modules/.cache'),
|
||||
appTsBuildInfoFile: resolveApp('node_modules/.cache/tsconfig.tsbuildinfo'),
|
||||
|
|
|
|||
|
|
@ -5,14 +5,18 @@ const ReactFlightWebpackPlugin = require('react-server-dom-webpack/plugin');
|
|||
// Fork End
|
||||
|
||||
const fs = require('fs');
|
||||
const {createHash} = require('crypto');
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const resolve = require('resolve');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
|
||||
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
|
||||
const {WebpackManifestPlugin} = require('webpack-manifest-plugin');
|
||||
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
|
||||
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
|
||||
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
|
||||
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
|
||||
const ESLintPlugin = require('eslint-webpack-plugin');
|
||||
|
|
@ -25,14 +29,8 @@ const ForkTsCheckerWebpackPlugin =
|
|||
? require('react-dev-utils/ForkTsCheckerWarningWebpackPlugin')
|
||||
: require('react-dev-utils/ForkTsCheckerWebpackPlugin');
|
||||
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
|
||||
const {WebpackManifestPlugin} = require('webpack-manifest-plugin');
|
||||
|
||||
function createEnvironmentHash(env) {
|
||||
const hash = createHash('md5');
|
||||
hash.update(JSON.stringify(env));
|
||||
|
||||
return hash.digest('hex');
|
||||
}
|
||||
const createEnvironmentHash = require('./webpack/persistentCache/createEnvironmentHash');
|
||||
|
||||
// Source maps are resource heavy and can cause out of memory issue for large source files.
|
||||
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
|
||||
|
|
@ -93,7 +91,7 @@ const hasJsxRuntime = (() => {
|
|||
|
||||
// This is the production and development configuration.
|
||||
// It is focused on developer experience, fast rebuilds, and a minimal bundle.
|
||||
module.exports = function (webpackEnv) {
|
||||
module.exports = function(webpackEnv) {
|
||||
const isEnvDevelopment = webpackEnv === 'development';
|
||||
const isEnvProduction = webpackEnv === 'production';
|
||||
|
||||
|
|
@ -114,7 +112,7 @@ module.exports = function (webpackEnv) {
|
|||
const getStyleLoaders = (cssOptions, preProcessor) => {
|
||||
const loaders = [
|
||||
isEnvDevelopment && require.resolve('style-loader'),
|
||||
{
|
||||
isEnvProduction && {
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
// css is located in `static/css`, use '../../' to locate index.html folder
|
||||
// in production `paths.publicUrlOrPath` can be a relative path
|
||||
|
|
@ -206,13 +204,7 @@ module.exports = function (webpackEnv) {
|
|||
: isEnvDevelopment && 'cheap-module-source-map',
|
||||
// These are the "entry points" to our application.
|
||||
// This means they will be the "root" imports that are included in JS bundle.
|
||||
entry: isEnvProduction
|
||||
? [paths.appIndexJs]
|
||||
: [
|
||||
paths.appIndexJs,
|
||||
// HMR client
|
||||
'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000',
|
||||
],
|
||||
entry: paths.appIndexJs,
|
||||
output: {
|
||||
// The build folder.
|
||||
path: paths.appBuild,
|
||||
|
|
@ -575,7 +567,44 @@ module.exports = function (webpackEnv) {
|
|||
].filter(Boolean),
|
||||
},
|
||||
plugins: [
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
// Generates an `index.html` file with the <script> injected.
|
||||
new HtmlWebpackPlugin(
|
||||
Object.assign(
|
||||
{},
|
||||
{
|
||||
inject: true,
|
||||
template: paths.appHtml,
|
||||
},
|
||||
isEnvProduction
|
||||
? {
|
||||
minify: {
|
||||
removeComments: true,
|
||||
collapseWhitespace: true,
|
||||
removeRedundantAttributes: true,
|
||||
useShortDoctype: true,
|
||||
removeEmptyAttributes: true,
|
||||
removeStyleLinkTypeAttributes: true,
|
||||
keepClosingSlash: true,
|
||||
minifyJS: true,
|
||||
minifyCSS: true,
|
||||
minifyURLs: true,
|
||||
},
|
||||
}
|
||||
: undefined
|
||||
)
|
||||
),
|
||||
// Inlines the webpack runtime script. This script is too small to warrant
|
||||
// a network request.
|
||||
// https://github.com/facebook/create-react-app/issues/5358
|
||||
isEnvProduction &&
|
||||
shouldInlineRuntimeChunk &&
|
||||
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime-.+[.]js/]),
|
||||
// Makes some environment variables available in index.html.
|
||||
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
|
||||
// <link rel="icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
// It will be an empty string unless you specify "homepage"
|
||||
// in `package.json`, in which case it will be the pathname of that URL.
|
||||
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
|
||||
// This gives some necessary context to module not found errors, such as
|
||||
// the requesting resource.
|
||||
new ModuleNotFoundPlugin(paths.appPath),
|
||||
|
|
@ -596,38 +625,35 @@ module.exports = function (webpackEnv) {
|
|||
// a plugin that prints an error when you attempt to do this.
|
||||
// See https://github.com/facebook/create-react-app/issues/240
|
||||
isEnvDevelopment && new CaseSensitivePathsPlugin(),
|
||||
new MiniCssExtractPlugin({
|
||||
// Options similar to the same options in webpackOptions.output
|
||||
// both options are optional
|
||||
filename: 'static/css/[name].[contenthash:8].css',
|
||||
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
|
||||
}),
|
||||
// Generate a manifest containing the required script / css for each entry.
|
||||
isEnvProduction &&
|
||||
new MiniCssExtractPlugin({
|
||||
// Options similar to the same options in webpackOptions.output
|
||||
// both options are optional
|
||||
filename: 'static/css/[name].[contenthash:8].css',
|
||||
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
|
||||
}),
|
||||
// Generate an asset manifest file with the following content:
|
||||
// - "files" key: Mapping of all asset filenames to their corresponding
|
||||
// output file so that tools can pick it up without having to parse
|
||||
// `index.html`
|
||||
// - "entrypoints" key: Array of files which are included in `index.html`,
|
||||
// can be used to reconstruct the HTML if necessary
|
||||
new WebpackManifestPlugin({
|
||||
fileName: 'entrypoint-manifest.json',
|
||||
fileName: 'asset-manifest.json',
|
||||
publicPath: paths.publicUrlOrPath,
|
||||
generate: (seed, files, entrypoints) => {
|
||||
const manifestFiles = files.reduce((manifest, file) => {
|
||||
manifest[file.name] = file.path;
|
||||
return manifest;
|
||||
}, seed);
|
||||
const entrypointFiles = entrypoints.main.filter(
|
||||
fileName => !fileName.endsWith('.map')
|
||||
);
|
||||
|
||||
const processedEntrypoints = {};
|
||||
for (let key in entrypoints) {
|
||||
processedEntrypoints[key] = {
|
||||
js: entrypoints[key].filter(
|
||||
filename =>
|
||||
// Include JS assets but ignore hot updates because they're not
|
||||
// safe to include as async script tags.
|
||||
filename.endsWith('.js') &&
|
||||
!filename.endsWith('.hot-update.js')
|
||||
),
|
||||
css: entrypoints[key].filter(filename =>
|
||||
filename.endsWith('.css')
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
return processedEntrypoints;
|
||||
return {
|
||||
files: manifestFiles,
|
||||
entrypoints: entrypointFiles,
|
||||
};
|
||||
},
|
||||
}),
|
||||
// Moment.js is an extremely popular library that bundles large locale files
|
||||
|
|
@ -639,6 +665,19 @@ module.exports = function (webpackEnv) {
|
|||
resourceRegExp: /^\.\/locale$/,
|
||||
contextRegExp: /moment$/,
|
||||
}),
|
||||
// Generate a service worker script that will precache, and keep up to date,
|
||||
// the HTML & assets that are part of the webpack build.
|
||||
isEnvProduction &&
|
||||
fs.existsSync(swSrc) &&
|
||||
new WorkboxWebpackPlugin.InjectManifest({
|
||||
swSrc,
|
||||
dontCacheBustURLsMatching: /\.[0-9a-f]{8}\./,
|
||||
exclude: [/\.map$/, /asset-manifest\.json$/, /LICENSE/],
|
||||
// Bump up the default maximum size (2mb) that's precached,
|
||||
// to make lazy-loading failure scenarios less likely.
|
||||
// See https://github.com/cra-template/pwa/issues/13#issuecomment-722667270
|
||||
maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
|
||||
}),
|
||||
// TypeScript type checking
|
||||
useTypeScript &&
|
||||
new ForkTsCheckerWebpackPlugin({
|
||||
|
|
@ -713,14 +752,7 @@ module.exports = function (webpackEnv) {
|
|||
// },
|
||||
// }),
|
||||
// Fork Start
|
||||
new ReactFlightWebpackPlugin({
|
||||
isServer: false,
|
||||
clientReferences: {
|
||||
directory: './src',
|
||||
recursive: true,
|
||||
include: /\.(js|ts|jsx|tsx)$/,
|
||||
},
|
||||
}),
|
||||
new ReactFlightWebpackPlugin({isServer: false}),
|
||||
// Fork End
|
||||
].filter(Boolean),
|
||||
// Turn off performance processing because we utilize
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
'use strict';
|
||||
const {createHash} = require('crypto');
|
||||
|
||||
module.exports = env => {
|
||||
const hash = createHash('md5');
|
||||
hash.update(JSON.stringify(env));
|
||||
|
||||
return hash.digest('hex');
|
||||
};
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const evalSourceMapMiddleware = require('react-dev-utils/evalSourceMapMiddleware');
|
||||
const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
|
||||
const ignoredFiles = require('react-dev-utils/ignoredFiles');
|
||||
const redirectServedPath = require('react-dev-utils/redirectServedPathMiddleware');
|
||||
const paths = require('./paths');
|
||||
const getHttpsConfig = require('./getHttpsConfig');
|
||||
|
||||
const host = process.env.HOST || '0.0.0.0';
|
||||
const sockHost = process.env.WDS_SOCKET_HOST;
|
||||
const sockPath = process.env.WDS_SOCKET_PATH; // default: '/ws'
|
||||
const sockPort = process.env.WDS_SOCKET_PORT;
|
||||
|
||||
module.exports = function(proxy, allowedHost) {
|
||||
const disableFirewall =
|
||||
!proxy || process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true';
|
||||
return {
|
||||
// WebpackDevServer 2.4.3 introduced a security fix that prevents remote
|
||||
// websites from potentially accessing local content through DNS rebinding:
|
||||
// https://github.com/webpack/webpack-dev-server/issues/887
|
||||
// https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a
|
||||
// However, it made several existing use cases such as development in cloud
|
||||
// environment or subdomains in development significantly more complicated:
|
||||
// https://github.com/facebook/create-react-app/issues/2271
|
||||
// https://github.com/facebook/create-react-app/issues/2233
|
||||
// While we're investigating better solutions, for now we will take a
|
||||
// compromise. Since our WDS configuration only serves files in the `public`
|
||||
// folder we won't consider accessing them a vulnerability. However, if you
|
||||
// use the `proxy` feature, it gets more dangerous because it can expose
|
||||
// remote code execution vulnerabilities in backends like Django and Rails.
|
||||
// So we will disable the host check normally, but enable it if you have
|
||||
// specified the `proxy` setting. Finally, we let you override it if you
|
||||
// really know what you're doing with a special environment variable.
|
||||
// Note: ["localhost", ".localhost"] will support subdomains - but we might
|
||||
// want to allow setting the allowedHosts manually for more complex setups
|
||||
allowedHosts: disableFirewall ? 'all' : [allowedHost],
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Methods': '*',
|
||||
'Access-Control-Allow-Headers': '*',
|
||||
},
|
||||
// Enable gzip compression of generated files.
|
||||
compress: true,
|
||||
static: {
|
||||
// By default WebpackDevServer serves physical files from current directory
|
||||
// in addition to all the virtual build products that it serves from memory.
|
||||
// This is confusing because those files won’t automatically be available in
|
||||
// production build folder unless we copy them. However, copying the whole
|
||||
// project directory is dangerous because we may expose sensitive files.
|
||||
// Instead, we establish a convention that only files in `public` directory
|
||||
// get served. Our build script will copy `public` into the `build` folder.
|
||||
// In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%:
|
||||
// <link rel="icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
// In JavaScript code, you can access it with `process.env.PUBLIC_URL`.
|
||||
// Note that we only recommend to use `public` folder as an escape hatch
|
||||
// for files like `favicon.ico`, `manifest.json`, and libraries that are
|
||||
// for some reason broken when imported through webpack. If you just want to
|
||||
// use an image, put it in `src` and `import` it from JavaScript instead.
|
||||
directory: paths.appPublic,
|
||||
publicPath: [paths.publicUrlOrPath],
|
||||
// By default files from `contentBase` will not trigger a page reload.
|
||||
watch: {
|
||||
// Reportedly, this avoids CPU overload on some systems.
|
||||
// https://github.com/facebook/create-react-app/issues/293
|
||||
// src/node_modules is not ignored to support absolute imports
|
||||
// https://github.com/facebook/create-react-app/issues/1065
|
||||
ignored: ignoredFiles(paths.appSrc),
|
||||
},
|
||||
},
|
||||
client: {
|
||||
webSocketURL: {
|
||||
// Enable custom sockjs pathname for websocket connection to hot reloading server.
|
||||
// Enable custom sockjs hostname, pathname and port for websocket connection
|
||||
// to hot reloading server.
|
||||
hostname: sockHost,
|
||||
pathname: sockPath,
|
||||
port: sockPort,
|
||||
},
|
||||
overlay: {
|
||||
errors: true,
|
||||
warnings: false,
|
||||
},
|
||||
},
|
||||
devMiddleware: {
|
||||
// Fork Start
|
||||
writeToDisk: filePath => {
|
||||
return /react-client-manifest\.json$/.test(filePath);
|
||||
},
|
||||
// Fork End
|
||||
|
||||
// It is important to tell WebpackDevServer to use the same "publicPath" path as
|
||||
// we specified in the webpack config. When homepage is '.', default to serving
|
||||
// from the root.
|
||||
// remove last slash so user can land on `/test` instead of `/test/`
|
||||
publicPath: paths.publicUrlOrPath.slice(0, -1),
|
||||
},
|
||||
|
||||
https: getHttpsConfig(),
|
||||
host,
|
||||
historyApiFallback: {
|
||||
// Paths with dots should still use the history fallback.
|
||||
// See https://github.com/facebook/create-react-app/issues/387.
|
||||
disableDotRule: true,
|
||||
index: paths.publicUrlOrPath,
|
||||
},
|
||||
// `proxy` is run between `before` and `after` `webpack-dev-server` hooks
|
||||
proxy,
|
||||
onBeforeSetupMiddleware(devServer) {
|
||||
// Keep `evalSourceMapMiddleware`
|
||||
// middlewares before `redirectServedPath` otherwise will not have any effect
|
||||
// This lets us fetch source contents from webpack for the error overlay
|
||||
devServer.app.use(evalSourceMapMiddleware(devServer));
|
||||
|
||||
if (fs.existsSync(paths.proxySetup)) {
|
||||
// This registers user provided middleware for proxy reasons
|
||||
require(paths.proxySetup)(devServer.app);
|
||||
}
|
||||
},
|
||||
onAfterSetupMiddleware(devServer) {
|
||||
// Redirect to `PUBLIC_URL` or `homepage` from `package.json` if url not match
|
||||
devServer.app.use(redirectServedPath(paths.publicUrlOrPath));
|
||||
|
||||
// This service worker file is effectively a 'no-op' that will reset any
|
||||
// previous service worker registered for the same host:port combination.
|
||||
// We do this in development to avoid hitting the production cache if
|
||||
// it used the same host and port.
|
||||
// https://github.com/facebook/create-react-app/issues/2272#issuecomment-302832432
|
||||
devServer.app.use(noopServiceWorkerMiddleware(paths.publicUrlOrPath));
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
import babel from '@babel/core';
|
||||
|
||||
const babelOptions = {
|
||||
babelrc: false,
|
||||
ignore: [/\/(build|node_modules)\//],
|
||||
plugins: [
|
||||
'@babel/plugin-syntax-import-meta',
|
||||
'@babel/plugin-transform-react-jsx',
|
||||
],
|
||||
};
|
||||
|
||||
export async function load(url, context, defaultLoad) {
|
||||
const {format} = context;
|
||||
const result = await defaultLoad(url, context, defaultLoad);
|
||||
if (result.format === 'module') {
|
||||
const opt = Object.assign({filename: url}, babelOptions);
|
||||
const newResult = await babel.transformAsync(result.source, opt);
|
||||
if (!newResult) {
|
||||
if (typeof result.source === 'string') {
|
||||
return result;
|
||||
}
|
||||
return {
|
||||
source: Buffer.from(result.source).toString('utf8'),
|
||||
format: 'module',
|
||||
};
|
||||
}
|
||||
return {source: newResult.code, format: 'module'};
|
||||
}
|
||||
return defaultLoad(url, context, defaultLoad);
|
||||
}
|
||||
|
||||
async function babelTransformSource(source, context, defaultTransformSource) {
|
||||
const {format} = context;
|
||||
if (format === 'module') {
|
||||
const opt = Object.assign({filename: context.url}, babelOptions);
|
||||
const newResult = await babel.transformAsync(source, opt);
|
||||
if (!newResult) {
|
||||
if (typeof source === 'string') {
|
||||
return {source};
|
||||
}
|
||||
return {
|
||||
source: Buffer.from(source).toString('utf8'),
|
||||
};
|
||||
}
|
||||
return {source: newResult.code};
|
||||
}
|
||||
return defaultTransformSource(source, context, defaultTransformSource);
|
||||
}
|
||||
|
||||
export const transformSource =
|
||||
process.version < 'v16' ? babelTransformSource : undefined;
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
import {
|
||||
resolve,
|
||||
getSource,
|
||||
transformSource as reactTransformSource,
|
||||
} from 'react-server-dom-webpack/node-loader';
|
||||
|
||||
export {resolve, getSource};
|
||||
|
||||
import babel from '@babel/core';
|
||||
|
||||
const babelOptions = {
|
||||
babelrc: false,
|
||||
ignore: [/\/(build|node_modules)\//],
|
||||
plugins: [
|
||||
'@babel/plugin-syntax-import-meta',
|
||||
'@babel/plugin-transform-react-jsx',
|
||||
],
|
||||
};
|
||||
|
||||
async function babelTransformSource(source, context, defaultTransformSource) {
|
||||
const {format} = context;
|
||||
if (format === 'module') {
|
||||
const opt = Object.assign({filename: context.url}, babelOptions);
|
||||
const {code} = await babel.transformAsync(source, opt);
|
||||
return {source: code};
|
||||
}
|
||||
return defaultTransformSource(source, context, defaultTransformSource);
|
||||
}
|
||||
|
||||
export async function transformSource(source, context, defaultTransformSource) {
|
||||
return reactTransformSource(source, context, (s, c) => {
|
||||
return babelTransformSource(s, c, defaultTransformSource);
|
||||
});
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
import {
|
||||
resolve,
|
||||
load as reactLoad,
|
||||
getSource as getSourceImpl,
|
||||
transformSource as reactTransformSource,
|
||||
} from 'react-server-dom-webpack/node-loader';
|
||||
|
||||
export {resolve};
|
||||
|
||||
import babel from '@babel/core';
|
||||
|
||||
const babelOptions = {
|
||||
babelrc: false,
|
||||
ignore: [/\/(build|node_modules)\//],
|
||||
plugins: [
|
||||
'@babel/plugin-syntax-import-meta',
|
||||
'@babel/plugin-transform-react-jsx',
|
||||
],
|
||||
};
|
||||
|
||||
async function babelLoad(url, context, defaultLoad) {
|
||||
const {format} = context;
|
||||
const result = await defaultLoad(url, context, defaultLoad);
|
||||
if (result.format === 'module') {
|
||||
const opt = Object.assign({filename: url}, babelOptions);
|
||||
const newResult = await babel.transformAsync(result.source, opt);
|
||||
if (!newResult) {
|
||||
if (typeof result.source === 'string') {
|
||||
return result;
|
||||
}
|
||||
return {
|
||||
source: Buffer.from(result.source).toString('utf8'),
|
||||
format: 'module',
|
||||
};
|
||||
}
|
||||
return {source: newResult.code, format: 'module'};
|
||||
}
|
||||
return defaultLoad(url, context, defaultLoad);
|
||||
}
|
||||
|
||||
export async function load(url, context, defaultLoad) {
|
||||
return await reactLoad(url, context, (u, c) => {
|
||||
return babelLoad(u, c, defaultLoad);
|
||||
});
|
||||
}
|
||||
|
||||
async function babelTransformSource(source, context, defaultTransformSource) {
|
||||
const {format} = context;
|
||||
if (format === 'module') {
|
||||
const opt = Object.assign({filename: context.url}, babelOptions);
|
||||
const newResult = await babel.transformAsync(source, opt);
|
||||
if (!newResult) {
|
||||
if (typeof source === 'string') {
|
||||
return {source};
|
||||
}
|
||||
return {
|
||||
source: Buffer.from(source).toString('utf8'),
|
||||
};
|
||||
}
|
||||
return {source: newResult.code};
|
||||
}
|
||||
return defaultTransformSource(source, context, defaultTransformSource);
|
||||
}
|
||||
|
||||
async function transformSourceImpl(source, context, defaultTransformSource) {
|
||||
return await reactTransformSource(source, context, (s, c) => {
|
||||
return babelTransformSource(s, c, defaultTransformSource);
|
||||
});
|
||||
}
|
||||
|
||||
export const transformSource =
|
||||
process.version < 'v16' ? transformSourceImpl : undefined;
|
||||
export const getSource = process.version < 'v16' ? getSourceImpl : undefined;
|
||||
|
|
@ -15,12 +15,10 @@
|
|||
"babel-loader": "^8.2.3",
|
||||
"babel-plugin-named-asset-import": "^0.3.8",
|
||||
"babel-preset-react-app": "^10.0.1",
|
||||
"body-parser": "^1.20.1",
|
||||
"bfj": "^7.0.2",
|
||||
"browserslist": "^4.18.1",
|
||||
"busboy": "^1.6.0",
|
||||
"camelcase": "^6.2.1",
|
||||
"case-sensitive-paths-webpack-plugin": "^2.4.0",
|
||||
"compression": "^1.7.4",
|
||||
"concurrently": "^7.3.0",
|
||||
"css-loader": "^6.5.1",
|
||||
"css-minimizer-webpack-plugin": "^3.2.0",
|
||||
|
|
@ -44,10 +42,10 @@
|
|||
"postcss-normalize": "^10.0.1",
|
||||
"postcss-preset-env": "^7.0.1",
|
||||
"prompts": "^2.4.2",
|
||||
"react": "experimental",
|
||||
"react": "^18.2.0",
|
||||
"react-app-polyfill": "^3.0.0",
|
||||
"react-dev-utils": "^12.0.1",
|
||||
"react-dom": "experimental",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-refresh": "^0.11.0",
|
||||
"resolve": "^1.20.0",
|
||||
"resolve-url-loader": "^4.0.0",
|
||||
|
|
@ -57,21 +55,21 @@
|
|||
"style-loader": "^3.3.1",
|
||||
"tailwindcss": "^3.0.2",
|
||||
"terser-webpack-plugin": "^5.2.5",
|
||||
"undici": "^5.20.0",
|
||||
"web-vitals": "^2.1.0",
|
||||
"webpack": "^5.64.4",
|
||||
"webpack-dev-middleware": "^5.3.1",
|
||||
"webpack-hot-middleware": "^2.25.3",
|
||||
"webpack-manifest-plugin": "^4.0.2"
|
||||
"webpack-dev-server": "^4.6.0",
|
||||
"webpack-manifest-plugin": "^4.0.2",
|
||||
"workbox-webpack-plugin": "^6.4.1"
|
||||
},
|
||||
"scripts": {
|
||||
"predev": "cp -r ../../build/oss-experimental/* ./node_modules/",
|
||||
"prebuild": "cp -r ../../build/oss-experimental/* ./node_modules/",
|
||||
"dev": "concurrently \"npm run dev:region\" \"npm run dev:global\"",
|
||||
"dev:global": "NODE_ENV=development BUILD_PATH=dist node --experimental-loader ./loader/global.js server/global",
|
||||
"dev:region": "NODE_ENV=development BUILD_PATH=dist nodemon --watch src --watch dist -- --experimental-loader ./loader/region.js --conditions=react-server server/region",
|
||||
"start": "node scripts/build.js && concurrently \"npm run start:region\" \"npm run start:global\"",
|
||||
"start:global": "NODE_ENV=production node --experimental-loader ./loader/global.js server/global",
|
||||
"start:region": "NODE_ENV=production node --experimental-loader ./loader/region.js --conditions=react-server server/region",
|
||||
"prestart": "cp -r ../../build/node_modules/* ./node_modules/",
|
||||
"prebuild": "cp -r ../../build/node_modules/* ./node_modules/",
|
||||
"start": "concurrently \"npm run start:server\" \"npm run start:client\"",
|
||||
"start:client": "NODE_ENV=development BUILD_PATH=dist node scripts/start.js",
|
||||
"start:server": "NODE_ENV=development BUILD_PATH=dist nodemon -- --experimental-loader ./loader/index.js --conditions=react-server server",
|
||||
"start:prod": "node scripts/build.js && concurrently \"npm run start:prod-server\" \"npm run start:prod-client\"",
|
||||
"start:prod-client": "cd ./build && python -m SimpleHTTPServer 3000",
|
||||
"start:prod-server": "NODE_ENV=production node --experimental-loader ./loader/index.js --conditions=react-server server",
|
||||
"build": "node scripts/build.js",
|
||||
"test": "node scripts/test.js --env=jsdom"
|
||||
},
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 24 KiB |
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Flight</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -15,8 +15,9 @@ process.on('unhandledRejection', err => {
|
|||
require('../config/env');
|
||||
|
||||
const path = require('path');
|
||||
const chalk = require('chalk');
|
||||
const chalk = require('react-dev-utils/chalk');
|
||||
const fs = require('fs-extra');
|
||||
const bfj = require('bfj');
|
||||
const webpack = require('webpack');
|
||||
const configFactory = require('../config/webpack.config');
|
||||
const paths = require('../config/paths');
|
||||
|
|
@ -38,7 +39,7 @@ const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
|
|||
const isInteractive = process.stdout.isTTY;
|
||||
|
||||
// Warn and crash if required files are missing
|
||||
if (!checkRequiredFiles([paths.appIndexJs])) {
|
||||
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
|
@ -196,13 +197,21 @@ function build(previousFileSizes) {
|
|||
warnings: messages.warnings,
|
||||
};
|
||||
|
||||
if (writeStatsJson) {
|
||||
return bfj
|
||||
.write(paths.appBuild + '/bundle-stats.json', stats.toJson())
|
||||
.then(() => resolve(resolveArgs))
|
||||
.catch(error => reject(new Error(error)));
|
||||
}
|
||||
|
||||
return resolve(resolveArgs);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function copyPublicFolder() {
|
||||
fs.copySync('public', 'build', {
|
||||
fs.copySync(paths.appPublic, paths.appBuild, {
|
||||
dereference: true,
|
||||
filter: file => file !== paths.appHtml,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,154 @@
|
|||
'use strict';
|
||||
|
||||
// Do this as the first thing so that any code reading it knows the right env.
|
||||
process.env.BABEL_ENV = 'development';
|
||||
process.env.NODE_ENV = 'development';
|
||||
|
||||
// Makes the script crash on unhandled rejections instead of silently
|
||||
// ignoring them. In the future, promise rejections that are not handled will
|
||||
// terminate the Node.js process with a non-zero exit code.
|
||||
process.on('unhandledRejection', err => {
|
||||
throw err;
|
||||
});
|
||||
|
||||
// Ensure environment variables are read.
|
||||
require('../config/env');
|
||||
|
||||
const fs = require('fs');
|
||||
const chalk = require('react-dev-utils/chalk');
|
||||
const webpack = require('webpack');
|
||||
const WebpackDevServer = require('webpack-dev-server');
|
||||
const clearConsole = require('react-dev-utils/clearConsole');
|
||||
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
|
||||
const {
|
||||
choosePort,
|
||||
createCompiler,
|
||||
prepareProxy,
|
||||
prepareUrls,
|
||||
} = require('react-dev-utils/WebpackDevServerUtils');
|
||||
const openBrowser = require('react-dev-utils/openBrowser');
|
||||
const semver = require('semver');
|
||||
const paths = require('../config/paths');
|
||||
const configFactory = require('../config/webpack.config');
|
||||
const createDevServerConfig = require('../config/webpackDevServer.config');
|
||||
const getClientEnvironment = require('../config/env');
|
||||
const react = require(require.resolve('react', {paths: [paths.appPath]}));
|
||||
|
||||
const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1));
|
||||
const useYarn = fs.existsSync(paths.yarnLockFile);
|
||||
const isInteractive = process.stdout.isTTY;
|
||||
|
||||
// Warn and crash if required files are missing
|
||||
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Tools like Cloud9 rely on this.
|
||||
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
|
||||
const HOST = process.env.HOST || '0.0.0.0';
|
||||
|
||||
if (process.env.HOST) {
|
||||
console.log(
|
||||
chalk.cyan(
|
||||
`Attempting to bind to HOST environment variable: ${chalk.yellow(
|
||||
chalk.bold(process.env.HOST)
|
||||
)}`
|
||||
)
|
||||
);
|
||||
console.log(
|
||||
`If this was unintentional, check that you haven't mistakenly set it in your shell.`
|
||||
);
|
||||
console.log(
|
||||
`Learn more here: ${chalk.yellow('https://cra.link/advanced-config')}`
|
||||
);
|
||||
console.log();
|
||||
}
|
||||
|
||||
// We require that you explicitly set browsers and do not fall back to
|
||||
// browserslist defaults.
|
||||
const {checkBrowsers} = require('react-dev-utils/browsersHelper');
|
||||
checkBrowsers(paths.appPath, isInteractive)
|
||||
.then(() => {
|
||||
// We attempt to use the default port but if it is busy, we offer the user to
|
||||
// run on a different port. `choosePort()` Promise resolves to the next free port.
|
||||
return choosePort(HOST, DEFAULT_PORT);
|
||||
})
|
||||
.then(port => {
|
||||
if (port == null) {
|
||||
// We have not found a port.
|
||||
return;
|
||||
}
|
||||
|
||||
const config = configFactory('development');
|
||||
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
|
||||
const appName = require(paths.appPackageJson).name;
|
||||
|
||||
const useTypeScript = fs.existsSync(paths.appTsConfig);
|
||||
const urls = prepareUrls(
|
||||
protocol,
|
||||
HOST,
|
||||
port,
|
||||
paths.publicUrlOrPath.slice(0, -1)
|
||||
);
|
||||
// Create a webpack compiler that is configured with custom messages.
|
||||
const compiler = createCompiler({
|
||||
appName,
|
||||
config,
|
||||
urls,
|
||||
useYarn,
|
||||
useTypeScript,
|
||||
webpack,
|
||||
});
|
||||
// Load proxy config
|
||||
const proxySetting = require(paths.appPackageJson).proxy;
|
||||
const proxyConfig = prepareProxy(
|
||||
proxySetting,
|
||||
paths.appPublic,
|
||||
paths.publicUrlOrPath
|
||||
);
|
||||
// Serve webpack assets generated by the compiler over a web server.
|
||||
const serverConfig = {
|
||||
...createDevServerConfig(proxyConfig, urls.lanUrlForConfig),
|
||||
host: HOST,
|
||||
port,
|
||||
};
|
||||
const devServer = new WebpackDevServer(serverConfig, compiler);
|
||||
// Launch WebpackDevServer.
|
||||
devServer.startCallback(() => {
|
||||
if (isInteractive) {
|
||||
clearConsole();
|
||||
}
|
||||
|
||||
if (env.raw.FAST_REFRESH && semver.lt(react.version, '16.10.0')) {
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
`Fast Refresh requires React 16.10 or higher. You are using React ${react.version}.`
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
console.log(chalk.cyan('Starting the development server...\n'));
|
||||
openBrowser(urls.localUrlForBrowser);
|
||||
});
|
||||
|
||||
['SIGINT', 'SIGTERM'].forEach(function(sig) {
|
||||
process.on(sig, function() {
|
||||
devServer.close();
|
||||
process.exit();
|
||||
});
|
||||
});
|
||||
|
||||
if (process.env.CI !== 'true') {
|
||||
// Gracefully exit when stdin ends
|
||||
process.stdin.on('end', function() {
|
||||
devServer.close();
|
||||
process.exit();
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
if (err && err.message) {
|
||||
console.log(err.message);
|
||||
}
|
||||
process.exit(1);
|
||||
});
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
'use strict';
|
||||
|
||||
const register = require('react-server-dom-webpack/node-register');
|
||||
register();
|
||||
|
||||
const babelRegister = require('@babel/register');
|
||||
const path = require('path');
|
||||
|
||||
babelRegister({
|
||||
babelrc: false,
|
||||
ignore: [
|
||||
/\/(build|node_modules)\//,
|
||||
function(file) {
|
||||
if ((path.dirname(file) + '/').startsWith(__dirname + '/')) {
|
||||
// Ignore everything in this folder
|
||||
// because it's a mix of CJS and ESM
|
||||
// and working with raw code is easier.
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
],
|
||||
presets: ['react-app'],
|
||||
plugins: ['@babel/transform-modules-commonjs'],
|
||||
});
|
||||
|
||||
const express = require('express');
|
||||
const app = express();
|
||||
|
||||
// Application
|
||||
app.get('/', function(req, res) {
|
||||
require('./handler.server.js')(req, res);
|
||||
});
|
||||
|
||||
app.get('/todos', function(req, res) {
|
||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
res.json([
|
||||
{
|
||||
id: 1,
|
||||
text: 'Shave yaks',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
text: 'Eat kale',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
app.listen(3001, () => {
|
||||
console.log('Flight Server listening on port 3001...');
|
||||
});
|
||||
|
||||
app.on('error', function(error) {
|
||||
if (error.syscall !== 'listen') {
|
||||
throw error;
|
||||
}
|
||||
|
||||
var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port;
|
||||
|
||||
switch (error.code) {
|
||||
case 'EACCES':
|
||||
console.error(bind + ' requires elevated privileges');
|
||||
process.exit(1);
|
||||
break;
|
||||
case 'EADDRINUSE':
|
||||
console.error(bind + ' is already in use');
|
||||
process.exit(1);
|
||||
break;
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
|
@ -1,205 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
// This is a server to host CDN distributed resources like Webpack bundles and SSR
|
||||
|
||||
const path = require('path');
|
||||
|
||||
// Do this as the first thing so that any code reading it knows the right env.
|
||||
process.env.BABEL_ENV = process.env.NODE_ENV;
|
||||
|
||||
const register = require('react-server-dom-webpack/node-register');
|
||||
register();
|
||||
|
||||
const babelRegister = require('@babel/register');
|
||||
babelRegister({
|
||||
babelrc: false,
|
||||
ignore: [
|
||||
/\/(build|node_modules)\//,
|
||||
function (file) {
|
||||
if ((path.dirname(file) + '/').startsWith(__dirname + '/')) {
|
||||
// Ignore everything in this folder
|
||||
// because it's a mix of CJS and ESM
|
||||
// and working with raw code is easier.
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
],
|
||||
presets: ['react-app'],
|
||||
plugins: ['@babel/transform-modules-commonjs'],
|
||||
});
|
||||
|
||||
// Ensure environment variables are read.
|
||||
require('../config/env');
|
||||
|
||||
const fs = require('fs').promises;
|
||||
const compress = require('compression');
|
||||
const chalk = require('chalk');
|
||||
const express = require('express');
|
||||
const http = require('http');
|
||||
|
||||
const {renderToPipeableStream} = require('react-dom/server');
|
||||
const {createFromNodeStream} = require('react-server-dom-webpack/client');
|
||||
|
||||
const app = express();
|
||||
|
||||
app.use(compress());
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
// In development we host the Webpack server for live bundling.
|
||||
const webpack = require('webpack');
|
||||
const webpackMiddleware = require('webpack-dev-middleware');
|
||||
const webpackHotMiddleware = require('webpack-hot-middleware');
|
||||
const paths = require('../config/paths');
|
||||
const configFactory = require('../config/webpack.config');
|
||||
const getClientEnvironment = require('../config/env');
|
||||
|
||||
const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1));
|
||||
|
||||
const config = configFactory('development');
|
||||
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
|
||||
const appName = require(paths.appPackageJson).name;
|
||||
|
||||
// Create a webpack compiler that is configured with custom messages.
|
||||
const compiler = webpack(config);
|
||||
app.use(
|
||||
webpackMiddleware(compiler, {
|
||||
publicPath: paths.publicUrlOrPath.slice(0, -1),
|
||||
serverSideRender: true,
|
||||
})
|
||||
);
|
||||
app.use(webpackHotMiddleware(compiler));
|
||||
}
|
||||
|
||||
function request(options, body) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = http.request(options, res => {
|
||||
resolve(res);
|
||||
});
|
||||
req.on('error', e => {
|
||||
reject(e);
|
||||
});
|
||||
body.pipe(req);
|
||||
});
|
||||
}
|
||||
|
||||
app.all('/', async function (req, res, next) {
|
||||
// Proxy the request to the regional server.
|
||||
const proxiedHeaders = {
|
||||
'X-Forwarded-Host': req.hostname,
|
||||
'X-Forwarded-For': req.ips,
|
||||
'X-Forwarded-Port': 3000,
|
||||
'X-Forwarded-Proto': req.protocol,
|
||||
};
|
||||
// Proxy other headers as desired.
|
||||
if (req.get('rsc-action')) {
|
||||
proxiedHeaders['Content-type'] = req.get('Content-type');
|
||||
proxiedHeaders['rsc-action'] = req.get('rsc-action');
|
||||
} else if (req.get('Content-type')) {
|
||||
proxiedHeaders['Content-type'] = req.get('Content-type');
|
||||
}
|
||||
|
||||
const promiseForData = request(
|
||||
{
|
||||
host: '127.0.0.1',
|
||||
port: 3001,
|
||||
method: req.method,
|
||||
path: '/',
|
||||
headers: proxiedHeaders,
|
||||
},
|
||||
req
|
||||
);
|
||||
|
||||
if (req.accepts('text/html')) {
|
||||
try {
|
||||
const rscResponse = await promiseForData;
|
||||
|
||||
let virtualFs;
|
||||
let buildPath;
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
const {devMiddleware} = res.locals.webpack;
|
||||
virtualFs = devMiddleware.outputFileSystem.promises;
|
||||
buildPath = devMiddleware.stats.toJson().outputPath;
|
||||
} else {
|
||||
virtualFs = fs;
|
||||
buildPath = path.join(__dirname, '../build/');
|
||||
}
|
||||
// Read the module map from the virtual file system.
|
||||
const moduleMap = JSON.parse(
|
||||
await virtualFs.readFile(
|
||||
path.join(buildPath, 'react-ssr-manifest.json'),
|
||||
'utf8'
|
||||
)
|
||||
);
|
||||
// Read the entrypoints containing the initial JS to bootstrap everything.
|
||||
// For other pages, the chunks in the RSC payload are enough.
|
||||
const mainJSChunks = JSON.parse(
|
||||
await virtualFs.readFile(
|
||||
path.join(buildPath, 'entrypoint-manifest.json'),
|
||||
'utf8'
|
||||
)
|
||||
).main.js;
|
||||
// For HTML, we're a "client" emulator that runs the client code,
|
||||
// so we start by consuming the RSC payload. This needs a module
|
||||
// map that reverse engineers the client-side path to the SSR path.
|
||||
const root = await createFromNodeStream(rscResponse, moduleMap);
|
||||
// Render it into HTML by resolving the client components
|
||||
res.set('Content-type', 'text/html');
|
||||
const {pipe} = renderToPipeableStream(root, {
|
||||
bootstrapScripts: mainJSChunks,
|
||||
});
|
||||
pipe(res);
|
||||
} catch (e) {
|
||||
console.error(`Failed to SSR: ${e.stack}`);
|
||||
res.statusCode = 500;
|
||||
res.end();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const rscResponse = await promiseForData;
|
||||
// For other request, we pass-through the RSC payload.
|
||||
res.set('Content-type', 'text/x-component');
|
||||
rscResponse.on('data', data => {
|
||||
res.write(data);
|
||||
res.flush();
|
||||
});
|
||||
rscResponse.on('end', data => {
|
||||
res.end();
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`Failed to proxy request: ${e.stack}`);
|
||||
res.statusCode = 500;
|
||||
res.end();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
app.use(express.static('public'));
|
||||
} else {
|
||||
// In production we host the static build output.
|
||||
app.use(express.static('build'));
|
||||
}
|
||||
|
||||
app.listen(3000, () => {
|
||||
console.log('Global Fizz/Webpack Server listening on port 3000...');
|
||||
});
|
||||
|
||||
app.on('error', function (error) {
|
||||
if (error.syscall !== 'listen') {
|
||||
throw error;
|
||||
}
|
||||
|
||||
switch (error.code) {
|
||||
case 'EACCES':
|
||||
console.error('port 3000 requires elevated privileges');
|
||||
process.exit(1);
|
||||
break;
|
||||
case 'EADDRINUSE':
|
||||
console.error('Port 3000 is already in use');
|
||||
process.exit(1);
|
||||
break;
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
'use strict';
|
||||
|
||||
const {renderToPipeableStream} = require('react-server-dom-webpack/server');
|
||||
const {readFile} = require('fs');
|
||||
const {resolve} = require('path');
|
||||
const React = require('react');
|
||||
|
||||
module.exports = function(req, res) {
|
||||
// const m = require('../src/App.server.js');
|
||||
import('../src/App.server.js').then(m => {
|
||||
const dist = process.env.NODE_ENV === 'development' ? 'dist' : 'build';
|
||||
readFile(
|
||||
resolve(__dirname, `../${dist}/react-client-manifest.json`),
|
||||
'utf8',
|
||||
(err, data) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
const App = m.default.default || m.default;
|
||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
const moduleMap = JSON.parse(data);
|
||||
const {pipe} = renderToPipeableStream(
|
||||
React.createElement(App),
|
||||
moduleMap
|
||||
);
|
||||
pipe(res);
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
{
|
||||
"type": "commonjs"
|
||||
"type": "commonjs",
|
||||
"main": "./cli.server.js"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,199 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
// This is a server to host data-local resources like databases and RSC
|
||||
|
||||
const path = require('path');
|
||||
|
||||
const register = require('react-server-dom-webpack/node-register');
|
||||
register();
|
||||
|
||||
const babelRegister = require('@babel/register');
|
||||
babelRegister({
|
||||
babelrc: false,
|
||||
ignore: [
|
||||
/\/(build|node_modules)\//,
|
||||
function (file) {
|
||||
if ((path.dirname(file) + '/').startsWith(__dirname + '/')) {
|
||||
// Ignore everything in this folder
|
||||
// because it's a mix of CJS and ESM
|
||||
// and working with raw code is easier.
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
],
|
||||
presets: ['react-app'],
|
||||
plugins: ['@babel/transform-modules-commonjs'],
|
||||
});
|
||||
|
||||
if (typeof fetch === 'undefined') {
|
||||
// Patch fetch for earlier Node versions.
|
||||
global.fetch = require('undici').fetch;
|
||||
}
|
||||
|
||||
const express = require('express');
|
||||
const bodyParser = require('body-parser');
|
||||
const busboy = require('busboy');
|
||||
const app = express();
|
||||
const compress = require('compression');
|
||||
const {Readable} = require('node:stream');
|
||||
|
||||
app.use(compress());
|
||||
|
||||
// Application
|
||||
|
||||
const {readFile} = require('fs').promises;
|
||||
|
||||
const React = require('react');
|
||||
|
||||
async function renderApp(res, returnValue) {
|
||||
const {renderToPipeableStream} = await import(
|
||||
'react-server-dom-webpack/server'
|
||||
);
|
||||
// const m = require('../src/App.js');
|
||||
const m = await import('../src/App.js');
|
||||
|
||||
let moduleMap;
|
||||
let mainCSSChunks;
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
// Read the module map from the HMR server in development.
|
||||
moduleMap = await (
|
||||
await fetch('http://localhost:3000/react-client-manifest.json')
|
||||
).json();
|
||||
mainCSSChunks = (
|
||||
await (
|
||||
await fetch('http://localhost:3000/entrypoint-manifest.json')
|
||||
).json()
|
||||
).main.css;
|
||||
} else {
|
||||
// Read the module map from the static build in production.
|
||||
moduleMap = JSON.parse(
|
||||
await readFile(
|
||||
path.resolve(__dirname, `../build/react-client-manifest.json`),
|
||||
'utf8'
|
||||
)
|
||||
);
|
||||
mainCSSChunks = JSON.parse(
|
||||
await readFile(
|
||||
path.resolve(__dirname, `../build/entrypoint-manifest.json`),
|
||||
'utf8'
|
||||
)
|
||||
).main.css;
|
||||
}
|
||||
const App = m.default.default || m.default;
|
||||
const root = [
|
||||
// Prepend the App's tree with stylesheets required for this entrypoint.
|
||||
mainCSSChunks.map(filename =>
|
||||
React.createElement('link', {
|
||||
rel: 'stylesheet',
|
||||
href: filename,
|
||||
precedence: 'default',
|
||||
})
|
||||
),
|
||||
React.createElement(App),
|
||||
];
|
||||
// For client-invoked server actions we refresh the tree and return a return value.
|
||||
const payload = returnValue ? {returnValue, root} : root;
|
||||
const {pipe} = renderToPipeableStream(payload, moduleMap);
|
||||
pipe(res);
|
||||
}
|
||||
|
||||
app.get('/', async function (req, res) {
|
||||
await renderApp(res, null);
|
||||
});
|
||||
|
||||
app.post('/', bodyParser.text(), async function (req, res) {
|
||||
const {
|
||||
renderToPipeableStream,
|
||||
decodeReply,
|
||||
decodeReplyFromBusboy,
|
||||
decodeAction,
|
||||
} = await import('react-server-dom-webpack/server');
|
||||
const serverReference = req.get('rsc-action');
|
||||
if (serverReference) {
|
||||
// This is the client-side case
|
||||
const [filepath, name] = serverReference.split('#');
|
||||
const action = (await import(filepath))[name];
|
||||
// Validate that this is actually a function we intended to expose and
|
||||
// not the client trying to invoke arbitrary functions. In a real app,
|
||||
// you'd have a manifest verifying this before even importing it.
|
||||
if (action.$$typeof !== Symbol.for('react.server.reference')) {
|
||||
throw new Error('Invalid action');
|
||||
}
|
||||
|
||||
let args;
|
||||
if (req.is('multipart/form-data')) {
|
||||
// Use busboy to streamingly parse the reply from form-data.
|
||||
const bb = busboy({headers: req.headers});
|
||||
const reply = decodeReplyFromBusboy(bb);
|
||||
req.pipe(bb);
|
||||
args = await reply;
|
||||
} else {
|
||||
args = await decodeReply(req.body);
|
||||
}
|
||||
const result = action.apply(null, args);
|
||||
try {
|
||||
// Wait for any mutations
|
||||
await result;
|
||||
} catch (x) {
|
||||
// We handle the error on the client
|
||||
}
|
||||
// Refresh the client and return the value
|
||||
renderApp(res, result);
|
||||
} else {
|
||||
// This is the progressive enhancement case
|
||||
const UndiciRequest = require('undici').Request;
|
||||
const fakeRequest = new UndiciRequest('http://localhost', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': req.headers['content-type']},
|
||||
body: Readable.toWeb(req),
|
||||
duplex: 'half',
|
||||
});
|
||||
const formData = await fakeRequest.formData();
|
||||
const action = await decodeAction(formData);
|
||||
try {
|
||||
// Wait for any mutations
|
||||
await action();
|
||||
} catch (x) {
|
||||
const {setServerState} = await import('../src/ServerState.js');
|
||||
setServerState('Error: ' + x.message);
|
||||
}
|
||||
renderApp(res, null);
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/todos', function (req, res) {
|
||||
res.json([
|
||||
{
|
||||
id: 1,
|
||||
text: 'Shave yaks',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
text: 'Eat kale',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
app.listen(3001, () => {
|
||||
console.log('Regional Flight Server listening on port 3001...');
|
||||
});
|
||||
|
||||
app.on('error', function (error) {
|
||||
if (error.syscall !== 'listen') {
|
||||
throw error;
|
||||
}
|
||||
|
||||
switch (error.code) {
|
||||
case 'EACCES':
|
||||
console.error('port 3001 requires elevated privileges');
|
||||
process.exit(1);
|
||||
break;
|
||||
case 'EADDRINUSE':
|
||||
console.error('Port 3001 is already in use');
|
||||
process.exit(1);
|
||||
break;
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
import * as React from 'react';
|
||||
|
||||
import Container from './Container.js';
|
||||
|
||||
import {Counter} from './Counter.js';
|
||||
import {Counter as Counter2} from './Counter2.js';
|
||||
|
||||
import ShowMore from './ShowMore.js';
|
||||
import Button from './Button.js';
|
||||
import Form from './Form.js';
|
||||
|
||||
import {like, greet} from './actions.js';
|
||||
|
||||
import {getServerState} from './ServerState.js';
|
||||
|
||||
export default async function App() {
|
||||
const res = await fetch('http://localhost:3001/todos');
|
||||
const todos = await res.json();
|
||||
return (
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Flight</title>
|
||||
</head>
|
||||
<body>
|
||||
<Container>
|
||||
<h1>{getServerState()}</h1>
|
||||
<Counter />
|
||||
<Counter2 />
|
||||
<ul>
|
||||
{todos.map(todo => (
|
||||
<li key={todo.id}>{todo.text}</li>
|
||||
))}
|
||||
</ul>
|
||||
<ShowMore>
|
||||
<p>Lorem ipsum</p>
|
||||
</ShowMore>
|
||||
<Form action={greet} />
|
||||
<div>
|
||||
<Button action={like}>Like</Button>
|
||||
</div>
|
||||
</Container>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import * as React from 'react';
|
||||
import {fetch} from 'react-fetch';
|
||||
|
||||
import Container from './Container.js';
|
||||
|
||||
import {Counter} from './Counter.client.js';
|
||||
import {Counter as Counter2} from './Counter2.client.js';
|
||||
|
||||
import ShowMore from './ShowMore.client.js';
|
||||
|
||||
export default function App() {
|
||||
const todos = fetch('http://localhost:3001/todos').json();
|
||||
return (
|
||||
<Container>
|
||||
<h1>Hello, world</h1>
|
||||
<Counter />
|
||||
<Counter2 />
|
||||
<ul>
|
||||
{todos.map(todo => (
|
||||
<li key={todo.id}>{todo.text}</li>
|
||||
))}
|
||||
</ul>
|
||||
<ShowMore>
|
||||
<p>Lorem ipsum</p>
|
||||
</ShowMore>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
'use client';
|
||||
|
||||
import * as React from 'react';
|
||||
import {experimental_useFormStatus as useFormStatus} from 'react-dom';
|
||||
import ErrorBoundary from './ErrorBoundary.js';
|
||||
|
||||
function ButtonDisabledWhilePending({action, children}) {
|
||||
const {pending} = useFormStatus();
|
||||
return (
|
||||
<button disabled={pending} formAction={action}>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Button({action, children}) {
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<form>
|
||||
<ButtonDisabledWhilePending action={action}>
|
||||
{children}
|
||||
</ButtonDisabledWhilePending>
|
||||
</form>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
'use client';
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
import Container from './Container.js';
|
||||
|
|
@ -0,0 +1 @@
|
|||
export * from './Counter.client.js';
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
'use client';
|
||||
|
||||
export * from './Counter.js';
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
'use client';
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
export default class ErrorBoundary extends React.Component {
|
||||
state = {error: null};
|
||||
static getDerivedStateFromError(error) {
|
||||
return {error};
|
||||
}
|
||||
render() {
|
||||
if (this.state.error) {
|
||||
return <div>Caught an error: {this.state.error.message}</div>;
|
||||
}
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
'use client';
|
||||
|
||||
import * as React from 'react';
|
||||
import {experimental_useFormStatus as useFormStatus} from 'react-dom';
|
||||
import ErrorBoundary from './ErrorBoundary.js';
|
||||
|
||||
function Status() {
|
||||
const {pending} = useFormStatus();
|
||||
return pending ? 'Saving...' : null;
|
||||
}
|
||||
|
||||
export default function Form({action, children}) {
|
||||
const [isPending, setIsPending] = React.useState(false);
|
||||
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<form action={action}>
|
||||
<label>
|
||||
Name: <input name="name" />
|
||||
</label>
|
||||
<label>
|
||||
File: <input type="file" name="file" />
|
||||
</label>
|
||||
<button>Say Hi</button>
|
||||
<Status />
|
||||
</form>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
let serverState = 'Hello World';
|
||||
|
||||
export function setServerState(message) {
|
||||
serverState = message;
|
||||
}
|
||||
|
||||
export function getServerState() {
|
||||
return serverState;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue