From 26459ef097b0dc9bae43d414a36e3c1eaa30aac1 Mon Sep 17 00:00:00 2001 From: Sukka Date: Sun, 8 May 2022 20:19:33 +0800 Subject: [PATCH] replace use-subscription with use-sync-external-store (#36733) - [x] Make sure the linting passes by running `yarn lint` Back in 2019, React released the first version of `use-subscription` (https://github.com/facebook/react/pull/15022). At the time, we only has limited information about concurrent rendering, and #9026 add the initial concurrent mode support. In 2020, React provides a first-party official API `useMutableSource` (https://github.com/reactjs/rfcs/pull/147, https://github.com/facebook/react/pull/18000): > ... enables React components to safely and efficiently read from a mutable external source in Concurrent Mode. React 18 introduces `useMutableSource`'s replacement `useSyncExternalStore` (see details here: https://github.com/reactwg/react-18/discussions/86), and React changes `use-subscription` implementation to use `useSyncExternalStore` directly: https://github.com/facebook/react/pull/24289 > In React 18, `React.useSyncExternalStore` is a built-in replacement for `useSubscription`. > > This PR makes `useSubscription` simply use `React.useSyncExternalStore` when available. For pre-18, it uses a `use-sync-external-store` shim which is very similar in `use-subscription` but fixes some flaws with concurrent rendering. And according to `use-subscription`: > You may now migrate to [`use-sync-external-store`](https://www.npmjs.com/package/use-sync-external-store) directly instead, which has the same API as `React.useSyncExternalStore`. The `use-subscription` package is now a thin wrapper over `use-sync-external-store` and will not be updated further. The PR does exactly that: - Removes the precompiled `use-subscription` introduced in #35746 - Adds the `use-sync-external-store` to the dependencies. - The `use-sync-external-store` package enables compatibility with React 16 and React 17. - Do not pre-compile `use-sync-external-store` since it is also the dependency of some popular React state management libraries like `react-redux`, `zustand`, `valtio`, `@xstate/react` and `@apollo/client`, etc. By install - Replace `useSubscription` usage with `useSyncExternalStore` --- Ref: #9026, #35746 and #36159 Co-authored-by: Jiachi Liu <4800338+huozhi@users.noreply.github.com> --- .../next/compiled/use-subscription/LICENSE | 21 ---------------- .../next/compiled/use-subscription/index.js | 25 ------------------- .../compiled/use-subscription/package.json | 1 - packages/next/package.json | 4 +-- packages/next/shared/lib/loadable.js | 11 ++++++-- packages/next/taskfile.js | 19 -------------- yarn.lock | 10 +++----- 7 files changed, 15 insertions(+), 76 deletions(-) delete mode 100644 packages/next/compiled/use-subscription/LICENSE delete mode 100644 packages/next/compiled/use-subscription/index.js delete mode 100644 packages/next/compiled/use-subscription/package.json diff --git a/packages/next/compiled/use-subscription/LICENSE b/packages/next/compiled/use-subscription/LICENSE deleted file mode 100644 index b96dcb0480a0b0b..000000000000000 --- a/packages/next/compiled/use-subscription/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) Facebook, Inc. and its affiliates. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/packages/next/compiled/use-subscription/index.js b/packages/next/compiled/use-subscription/index.js deleted file mode 100644 index 94087da0e39deb1..000000000000000 --- a/packages/next/compiled/use-subscription/index.js +++ /dev/null @@ -1,25 +0,0 @@ -(function(){"use strict";var e={800:function(e){ -/* -object-assign -(c) Sindre Sorhus -@license MIT -*/ -var r=Object.getOwnPropertySymbols;var t=Object.prototype.hasOwnProperty;var u=Object.prototype.propertyIsEnumerable;function toObject(e){if(e===null||e===undefined){throw new TypeError("Object.assign cannot be called with null or undefined")}return Object(e)}function shouldUseNative(){try{if(!Object.assign){return false}var e=new String("abc");e[5]="de";if(Object.getOwnPropertyNames(e)[0]==="5"){return false}var r={};for(var t=0;t<10;t++){r["_"+String.fromCharCode(t)]=t}var u=Object.getOwnPropertyNames(r).map((function(e){return r[e]}));if(u.join("")!=="0123456789"){return false}var n={};"abcdefghijklmnopqrst".split("").forEach((function(e){n[e]=e}));if(Object.keys(Object.assign({},n)).join("")!=="abcdefghijklmnopqrst"){return false}return true}catch(e){return false}}e.exports=shouldUseNative()?Object.assign:function(e,n){var a;var i=toObject(e);var s;for(var c=1;c= 3.1.0", @@ -260,7 +261,6 @@ "tty-browserify": "0.0.1", "ua-parser-js": "0.7.28", "unistore": "3.4.1", - "use-subscription": "1.5.1", "util": "0.12.4", "uuid": "8.3.2", "vm-browserify": "1.1.2", diff --git a/packages/next/shared/lib/loadable.js b/packages/next/shared/lib/loadable.js index e4591e4af14a6c0..06df00dacf554de 100644 --- a/packages/next/shared/lib/loadable.js +++ b/packages/next/shared/lib/loadable.js @@ -22,7 +22,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE // Modified to be compatible with webpack 4 / Next.js import React from 'react' -import { useSubscription } from 'next/dist/compiled/use-subscription' +import { useSyncExternalStore } from 'use-sync-external-store/shim' + import { LoadableContext } from './loadable-context' const ALL_INITIALIZERS = [] @@ -75,6 +76,7 @@ function createLoadableComponent(loadFn, options) { opts.lazy = React.lazy(opts.loader) } + /** @type LoadableSubscription */ let subscription = null function init() { if (!subscription) { @@ -116,7 +118,12 @@ function createLoadableComponent(loadFn, options) { init() const context = React.useContext(LoadableContext) - const state = useSubscription(subscription) + const state = useSyncExternalStore( + subscription.subscribe, + subscription.getCurrentValue, + subscription.getCurrentValue + ) + React.useImperativeHandle( ref, () => ({ diff --git a/packages/next/taskfile.js b/packages/next/taskfile.js index 3edcde3e5a6a657..58e0e94f4c8a4df 100644 --- a/packages/next/taskfile.js +++ b/packages/next/taskfile.js @@ -306,24 +306,6 @@ export async function ncc_react_refresh_utils(task, opts) { } } -// eslint-disable-next-line camelcase -export async function ncc_use_subscription(task, opts) { - await task - .source( - opts.src || relative(__dirname, require.resolve('use-subscription')) - ) - .ncc({ - packageName: 'use-subscription', - externals: { - ...externals, - react: 'react', - 'react-dom': 'react-dom', - }, - target: 'es5', - }) - .target('compiled/use-subscription') -} - // eslint-disable-next-line camelcase externals['chalk'] = 'next/dist/compiled/chalk' export async function ncc_chalk(task, opts) { @@ -1652,7 +1634,6 @@ export async function ncc(task, opts) { 'ncc_node_html_parser', 'ncc_watchpack', 'ncc_chalk', - 'ncc_use_subscription', 'ncc_napirs_triples', 'ncc_etag', 'ncc_p_limit', diff --git a/yarn.lock b/yarn.lock index 3cae0cb367a2fb6..d949c8074ba6c05 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21248,12 +21248,10 @@ url@^0.11.0: punycode "1.3.2" querystring "0.2.0" -use-subscription@1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.5.1.tgz#73501107f02fad84c6dd57965beb0b75c68c42d1" - integrity sha512-Xv2a1P/yReAjAbhylMfFplFKj9GssgTwN7RlcTxBujFQcloStWNDQdc4g4NRWH9xS4i/FDk04vQBptAXoF3VcA== - dependencies: - object-assign "^4.1.1" +use-sync-external-store@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.1.0.tgz#3343c3fe7f7e404db70f8c687adf5c1652d34e82" + integrity sha512-SEnieB2FPKEVne66NpXPd1Np4R1lTNKfjuy3XdIoPQKYBAFdzbzSZlSn1KJZUiihQLQC5Znot4SBz1EOTBwQAQ== use@^3.1.0: version "3.1.1"