react icon indicating copy to clipboard operation
react copied to clipboard

Upgrade to modern version of Rollup and related plugins

Open 0xdevalias opened this issue 3 years ago • 2 comments
trafficstars

The inspiration for this came from @jasonwilliams 's PR for attempting to add sourcemap output support to React's builds:

  • https://github.com/facebook/react/issues/20186
    • https://github.com/facebook/react/pull/21946

But I figured that it would be useful to minimise the scope of changes in that PR, and to modernise the build tooling along the way.


There have been quite a few version releases for Rollup and the plugins that are currently used, as well as a number of the official Rollup plugins changing package name to use the @rollup/* package prefix.

Looking at package.json we can see all of the current Rollup packages:

// ..snip..
    "rollup": "^1.19.4",
    "rollup-plugin-babel": "^4.0.1",
    "rollup-plugin-commonjs": "^9.3.4",
    "rollup-plugin-node-resolve": "^2.1.1",
    "rollup-plugin-prettier": "^0.6.0",
    "rollup-plugin-replace": "^2.2.0",
    "rollup-plugin-strip-banner": "^0.2.0",
// ..snip..

And using grep, we can see some additional usages under packages/:

⇒  grep -r 'rollup' package.json packages/*/package.json
package.json:    "rollup": "^1.19.4",
package.json:    "rollup-plugin-babel": "^4.0.1",
package.json:    "rollup-plugin-commonjs": "^9.3.4",
package.json:    "rollup-plugin-node-resolve": "^2.1.1",
package.json:    "rollup-plugin-prettier": "^0.6.0",
package.json:    "rollup-plugin-replace": "^2.2.0",
package.json:    "rollup-plugin-strip-banner": "^0.2.0",
package.json:    "build": "node ./scripts/rollup/build.js",
package.json:    "build-combined": "node ./scripts/rollup/build-all-release-channels.js",
package.json:    "lint-build": "node ./scripts/rollup/validate/index.js",
packages/react-devtools-extensions/package.json:    "rollup": "^1.19.4",
packages/react-devtools-extensions/package.json:    "rollup-plugin-babel": "^4.0.1",
packages/react-devtools-extensions/package.json:    "rollup-plugin-commonjs": "^9.3.4",
packages/react-devtools-extensions/package.json:    "rollup-plugin-node-resolve": "^2.1.1",

The following is an attempt to capture all of the relevant information about package name changes, new versions, breaking changes, etc for these packages:

  • https://github.com/rollup/rollup
    • https://www.npmjs.com/package/rollup
      • Lockfile currently resolves to version "1.31.1"
        • https://github.com/rollup/rollup/blob/master/CHANGELOG.md#1311
        • The latest version is 2.76.0, but there are a number of other breaking changes leading up to that version
          • https://github.com/rollup/rollup/blob/master/CHANGELOG.md#200
            • Breaking Changes

  • https://github.com/rollup/plugins#plugins-found-here
    • https://github.com/rollup/plugins/tree/master/packages/babel
      • https://www.npmjs.com/package/@rollup/plugin-babel
        • Lockfile currently resolves to version "4.3.3"
        • Oldest version for @rollup/plugin-babel package name is 5.0.0
          • https://github.com/rollup/plugins/blob/master/packages/babel/CHANGELOG.md#500
            • Breaking Changes

              • Minimum compatible Rollup version is 1.2.0

              • Minimum supported Node version is 10.0.0

              • .custom factory is now available as separate createBabelInputPluginFactory export

              • Removed externalHelpers & runtimeHelpers options. There is now a single babelHelpers option which can take one of 'bundled', 'inline', 'runtime' and 'external' as a value. The default is 'bundled' which matches 4.x behavior, but it is recommended to configure this option explicitly.

          • There don't seem to be any other breaking changes up till the latest version which is 5.3.1
    • https://github.com/rollup/plugins/tree/master/packages/commonjs
      • https://www.npmjs.com/package/@rollup/plugin-commonjs
      • Lockfile currently resolves to version "9.3.4"
      • Oldest version for @rollup/plugin-commonjs package name is 11.0.0
        • https://github.com/rollup/plugins/blob/master/packages/commonjs/CHANGELOG.md#1100
          • Breaking: Minimum compatible Rollup version is 1.20.0

          • Breaking: Minimum supported Node version is 8.0.0

        • The latest version is 22.0.1, but there are a number of other breaking changes leading up to that version
      • Based on some comments in the source, I believe this dependency is only used for react-art, so presumably if that still works properly with the newest version of this lib, we could update to that.
    • https://github.com/rollup/plugins/tree/master/packages/node-resolve
      • https://www.npmjs.com/package/@rollup/plugin-node-resolve
        • Lockfile currently resolves to version "2.1.1"
        • Oldest version for @rollup/plugin-node-resolve package name is 6.0.0
          • https://github.com/rollup/plugins/blob/master/packages/node-resolve/CHANGELOG.md#600
            • Breaking: Minimum compatible Rollup version is 1.20.0

            • Breaking: Minimum supported Node version is 8.0.0

          • https://github.com/rollup/plugins/blob/master/packages/node-resolve/CHANGELOG.md#500-2019-05-15
            • Breaking Changes

              • Requires at least [email protected] to work (v1.12.0 for module side-effects to be respected)

              • If used with rollup-plugin-commonjs, it should be at least v10.0.0

          • https://github.com/rollup/plugins/blob/master/packages/node-resolve/CHANGELOG.md#300
            • [BREAKING] Remove options.skip

          • The latest version is 13.3.0, but there are a number of other breaking changes leading up to that version
    • https://github.com/rollup/plugins/tree/master/packages/replace
      • https://www.npmjs.com/package/@rollup/plugin-replace
        • Lockfile currently resolves to version "2.2.0"
        • Oldest version for @rollup/plugin-replace package name is 2.2.0
          • https://github.com/rollup/plugins/blob/master/packages/replace/CHANGELOG.md#220
          • The latest version is 4.0.0, but there are a number of other breaking changes leading up to that version
  • https://github.com/mjeanroy/rollup-plugin-strip-banner
    • https://www.npmjs.com/package/rollup-plugin-strip-banner
      • Lockfile currently resolves to version "0.2.0"
        • https://github.com/mjeanroy/rollup-plugin-strip-banner/blob/master/CHANGELOG.md#020-2017-05-10
        • The latest version is 2.0.0. The changelog doesn't explicitly mention any breaking changes, but I didn't look into it too deeply
        • Edit: Seems there is a secondary changelog in the README, though it still doesn't mention any breaking changes: https://github.com/mjeanroy/rollup-plugin-strip-banner#changelogs
  • https://github.com/mjeanroy/rollup-plugin-prettier
    • https://www.npmjs.com/package/rollup-plugin-prettier
    • Lockfile currently resolves to version "0.6.0"
      • https://github.com/mjeanroy/rollup-plugin-prettier/blob/master/CHANGELOG.md#060-2019-01-16
      • The latest version is 2.2.2. The changelog doesn't explicitly mention any breaking changes, but I didn't look into it too deeply
      • Edit: Seems there is a secondary changelog in the README that mentions a breaking change: https://github.com/mjeanroy/rollup-plugin-prettier#changelogs
        • Breaking Change: prettier dependency is now a peer dependency instead of a "direct" dependency: user of the plugin can choose to use prettier 1.x.x or prettier 2.x.x (note that this plugin should be compatible with all versions of prettier).

If any of these updates rely on a node version later than 10.x, then the following PR may have to land first, otherwise things might break on AppVeyor:

  • https://github.com/facebook/react/issues/24891
    • https://github.com/facebook/react/pull/24892

My plan/intent is to work through all of this and create a PR updating Rollup and the related plugins; but I wanted to create this issue in the meantime to capture what I have done so far, and also check whether there would be any issues/concerns with a PR like this being made.

Edit: PR opened in:

  • https://github.com/facebook/react/pull/24916

0xdevalias avatar Jul 12 '22 11:07 0xdevalias

It seems yarn 1.x's remove doesn't update the yarn.lock file particularly well.. is there a best practice way for doing this, or is it just a manual sort of thing to clean up?

  • https://github.com/yarnpkg/yarn/issues/2581

eg. yarn remove --force --ignore-workspace-root-check rollup-plugin-babel only updated package.json, not yarn.lock


Edit: I wonder if this is because it's used in other packages as well?

⇒  grep -r 'rollup-plugin-babel' packages
packages/react-devtools-timeline/node_modules/json5/package.json:    "rollup-plugin-babel": "^3.0.3",
packages/react-devtools-extensions/package.json:    "rollup-plugin-babel": "^4.0.1",
packages/react-devtools-shared/src/node_modules/react-window/package.json:    "rollup-plugin-babel": "^4.3.2",
packages/react-devtools-shared/src/hooks/__tests__/updateMockSourceMaps.js:const babel = require('rollup-plugin-babel');
⇒  yarn add --force --dev --ignore-workspace-root-check @rollup/plugin-babel
yarn add v1.22.19
[1/4] 🔍  Resolving packages...
warning workspace-aggregator-06b1766b-e8f5-406b-87e7-0089d7a59d18 > react-devtools-extensions > [email protected]: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-babel.
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...

...snip: a whole bunch of peer dependency warnings...

[4/4] 🔨  Rebuilding all packages...
success Saved lockfile.
success Saved 3 new dependencies.
info Direct dependencies
├─ @rollup/[email protected]
└─ [email protected]
info All dependencies
├─ @rollup/[email protected]
├─ [email protected]
└─ [email protected]

Edit 2: I tried using yarn's workspace command to manipulate the other packages:

  • https://classic.yarnpkg.com/en/docs/cli/workspace
  • https://classic.yarnpkg.com/lang/en/docs/cli/add/

But then I ran into an error about "Failed to install dependencies in workspace: expected workspace package to exist". After some googling, that lead me to the following issues, and the various proposed solutions within:

  • https://github.com/yarnpkg/yarn/issues/7807
    • Failed to install dependencies in workspace: expected workspace package to exist

    • https://github.com/yarnpkg/yarn/issues/7807#issuecomment-588632848
      • yarn policies set-version 1.18.0

    • https://github.com/yarnpkg/yarn/issues/7807#issuecomment-1097198463
      • npx yarn-deduplicate && yarn install

    • https://github.com/yarnpkg/yarn/issues/7807#issuecomment-1104082997
      • Re: deduping, this package actually dedupes: https://medium.com/@bnaya/yarn-deduplicate-the-hero-we-need-f4497a362128

  • https://github.com/yarnpkg/yarn/issues/7734
    • https://github.com/yarnpkg/yarn/issues/7734#issuecomment-578534560
      • For those looking for a solution that doesn't involve changing the version of yarn you're using, editing package.json to include the version of the package you want and then running the yarn command again works just fine.

    • https://github.com/yarnpkg/yarn/issues/7734#issuecomment-588282680
      • For me, the problem is a regression 1.19.1->1.19.2 (as reported here). Downgrading to 1.19.1 helped.

    • https://github.com/yarnpkg/yarn/issues/7734#issuecomment-671729912
      • An alternative is to issue the command yarn policies set-version 1.19.1 from inside your project.

    • https://github.com/yarnpkg/yarn/issues/7734#issuecomment-671866619
      • You could also use lerna to add a package without downgrading the yarn version

      • npx lerna add <package>[@version] --scope=<workspace>

      • The command above will add the package to the specified workspace package.json and update yarn.lock

0xdevalias avatar Jul 12 '22 11:07 0xdevalias

Playing around with things, this seems to be a working set of upgraded rollup version/plugins that still seems to produce the same build output for build/node_modules/react/umd/react.development.js.

Note that:

  • It is using the last 1.x version of Rollup before Rollup 2.x
  • It is using a version of @rollup/plugin-node-resolve below v13.0.0 as that requires Rollup 2.x
    • https://github.com/rollup/plugins/issues/1222#issuecomment-1182795892
  • The version of @rollup/plugin-node-resolve being used was determined by manually testing each version below 13.0.0 and trying to build yarn build react/index,react-dom/index --type=UMD. For versions 11.0.0 through to 11.2.1, the following error (presumably a bug in the resolver) was produced:
    • Error: Could not load /Users/devalias/dev/facebook/react/node_modules/react-dom/src/client/ReactDOMHostConfig (imported by /Users/devalias/dev/facebook/react/packages/react-reconciler/src/forks/ReactFiberHostConfig.dom.js): ENOENT: no such file or directory, open '/Users/devalias/dev/facebook/react/node_modules/react-dom/src/client/ReactDOMHostConfig'

diff --git a/package.json b/package.json
index 2e8445521..51e284ff6 100644
--- a/package.json
+++ b/package.json
@@ -36,6 +36,10 @@
     "@babel/preset-flow": "^7.10.4",
     "@babel/preset-react": "^7.10.4",
     "@babel/traverse": "^7.11.0",
+    "@rollup/plugin-babel": "^5.3.1",
+    "@rollup/plugin-commonjs": "^22.0.1",
+    "@rollup/plugin-node-resolve": "^10.0.0",
+    "@rollup/plugin-replace": "^4.0.0",
     "abort-controller": "^3.0.0",
     "art": "0.10.1",
     "babel-eslint": "^10.0.3",
@@ -83,13 +87,9 @@
     "random-seed": "^0.3.0",
     "react-lifecycles-compat": "^3.0.4",
     "rimraf": "^3.0.0",
-    "rollup": "^1.19.4",
-    "rollup-plugin-babel": "^4.0.1",
-    "rollup-plugin-commonjs": "^9.3.4",
-    "rollup-plugin-node-resolve": "^2.1.1",
-    "rollup-plugin-prettier": "^0.6.0",
-    "rollup-plugin-replace": "^2.2.0",
-    "rollup-plugin-strip-banner": "^0.2.0",
+    "rollup": "^1.32.1",
+    "rollup-plugin-prettier": "^2.2.2",
+    "rollup-plugin-strip-banner": "^2.0.0",
     "semver": "^7.1.1",
     "targz": "^1.0.1",
     "through2": "^3.0.1",

Moving to a 2.x version of Rollup seems to change the output of build/node_modules/react/umd/react.development.js. While it may be insignificant, I figured it was worth calling out the differences here for posterity (partial diff included below):

Details
diff --git a/build-currentMain/node_modules/react/umd/react.development.js b/build/node_modules/react/umd/react.development.js
index 74fb8652e..50a773692 100644
--- a/build-currentMain/node_modules/react/umd/react.development.js
+++ b/build/node_modules/react/umd/react.development.js
@@ -10,8 +10,8 @@
 (function (global, factory) {
   typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
   typeof define === 'function' && define.amd ? define(['exports'], factory) :
-  (global = global || self, factory(global.React = {}));
-}(this, (function (exports) { 'use strict';
+  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.React = {}));
+})(this, (function (exports) { 'use strict';
 
   // TODO: this is special because it gets imported during build.
   //
@@ -40,9 +40,12 @@
   var REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list');
   var REACT_MEMO_TYPE = Symbol.for('react.memo');
   var REACT_LAZY_TYPE = Symbol.for('react.lazy');
+  var REACT_SCOPE_TYPE = Symbol.for('react.scope');
   var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for('react.debug_trace_mode');
   var REACT_OFFSCREEN_TYPE = Symbol.for('react.offscreen');
+  var REACT_LEGACY_HIDDEN_TYPE = Symbol.for('react.legacy_hidden');
   var REACT_CACHE_TYPE = Symbol.for('react.cache');
+  var REACT_TRACING_MARKER_TYPE = Symbol.for('react.tracing_marker');
   var REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED = Symbol.for('react.default_value');
   var MAYBE_ITERATOR_SYMBOL = Symbol.iterator;
   var FAUX_ITERATOR_SYMBOL = '@@iterator';
@@ -63,13 +66,14 @@
   /**
    * Keeps track of the current dispatcher.
    */
-  var ReactCurrentDispatcher = {
+  var ReactCurrentDispatcher$1 = {
     /**
      * @internal
      * @type {ReactComponent}
      */
     current: null
   };
+  var ReactCurrentDispatcher$2 = ReactCurrentDispatcher$1;
 
   /**
    * Keeps track of the current batch's configuration such as how long an update
@@ -78,6 +82,7 @@
   var ReactCurrentBatchConfig = {
     transition: null
   };
+  var ReactCurrentBatchConfig$1 = ReactCurrentBatchConfig;
 
   var ReactCurrentActQueue = {
     current: null,
@@ -85,6 +90,7 @@
     isBatchingLegacy: false,
     didScheduleLegacyUpdate: false
   };
+  var ReactCurrentActQueue$1 = ReactCurrentActQueue;
 
   /**
    * Keeps track of the current owner.
@@ -99,8 +105,9 @@
      */
     current: null
   };
+  var ReactCurrentOwner$1 = ReactCurrentOwner;
 
-  var ReactDebugCurrentFrame = {};
+  var ReactDebugCurrentFrame$1 = {};
   var currentExtraStackFrame = null;
   function setExtraStackFrame(stack) {
     {
@@ -109,16 +116,16 @@
   }
 
   {
-    ReactDebugCurrentFrame.setExtraStackFrame = function (stack) {
+    ReactDebugCurrentFrame$1.setExtraStackFrame = function (stack) {
       {
         currentExtraStackFrame = stack;
       }
     }; // Stack implementation injected by the current renderer.
 
 
-    ReactDebugCurrentFrame.getCurrentStack = null;
+    ReactDebugCurrentFrame$1.getCurrentStack = null;
 
-    ReactDebugCurrentFrame.getStackAddendum = function () {
+    ReactDebugCurrentFrame$1.getStackAddendum = function () {
       var stack = ''; // Add an extra top frame while an element is being validated
 
       if (currentExtraStackFrame) {
@@ -126,7 +133,7 @@
       } // Delegate to the injected renderer-specific implementation
 
 
-      var impl = ReactDebugCurrentFrame.getCurrentStack;
+      var impl = ReactDebugCurrentFrame$1.getCurrentStack;
 
       if (impl) {
         stack += impl() || '';
@@ -136,9 +143,12 @@
     };
   }
 
+  var ReactDebugCurrentFrame$2 = ReactDebugCurrentFrame$1;
+
   // -----------------------------------------------------------------------------
 
   var enableScopeAPI = false; // Experimental Create Event Handle API.
+  var enableCacheElement = true;
   var enableTransitionTracing = false; // No known bugs, but needs performance testing
 
   var enableLegacyHidden = false; // Enables unstable_avoidThisFallback feature in Fiber
@@ -146,24 +156,28 @@
   // issues in DEV builds.
 
   var enableDebugTracing = false; // Track which Fiber(s) schedule render work.
+  var enableServerContext = true; // Internal only.
 
-  var ContextRegistry = {};
+  var ContextRegistry$1 = {};
 
-  var ReactSharedInternals = {
-    ReactCurrentDispatcher: ReactCurrentDispatcher,
-    ReactCurrentBatchConfig: ReactCurrentBatchConfig,
-    ReactCurrentOwner: ReactCurrentOwner
+  var ReactSharedInternals$2 = {
+    ReactCurrentDispatcher: ReactCurrentDispatcher$2,
+    ReactCurrentBatchConfig: ReactCurrentBatchConfig$1,
+    ReactCurrentOwner: ReactCurrentOwner$1
   };
 
   {
-    ReactSharedInternals.ReactDebugCurrentFrame = ReactDebugCurrentFrame;
-    ReactSharedInternals.ReactCurrentActQueue = ReactCurrentActQueue;
+    ReactSharedInternals$2.ReactDebugCurrentFrame = ReactDebugCurrentFrame$2;
+    ReactSharedInternals$2.ReactCurrentActQueue = ReactCurrentActQueue$1;
   }
 
   {
-    ReactSharedInternals.ContextRegistry = ContextRegistry;
+    ReactSharedInternals$2.ContextRegistry = ContextRegistry$1;
   }
 
+  var ReactSharedInternals$3 = ReactSharedInternals$2;
+
+  var suppressWarning = false;

//..snip..

I'm not currently sure if these changes are significant/change the semantics of the output, or are just a different way of the bundler working, but I did notice that it increases the output file sizes a bit (most dramatically in react.development.js):

⇒  yarn build react/index,react-dom/index --type=UMD
yarn run v1.22.19
$ node ./scripts/rollup/build.js react/index,react-dom/index --type=UMD

//..snip..

┌─────────────────────────────────────────────┬───────────┬──────────────┬───────┬───────────┬──────────────┬───────┐
│ Bundle                                      │ Prev Size │ Current Size │ Diff  │ Prev Gzip │ Current Gzip │ Diff  │
├─────────────────────────────────────────────┼───────────┼──────────────┼───────┼───────────┼──────────────┼───────┤
│ react.development.js  (UMD_DEV)             │ 111.96 KB │ 117.59 KB    │ +5.0% │ 28.82 KB  │ 30.35 KB     │ +5.3% │
├─────────────────────────────────────────────┼───────────┼──────────────┼───────┼───────────┼──────────────┼───────┤
│ react.production.min.js  (UMD_PROD)         │ 11.45 KB  │ 11.51 KB     │ +0.5% │ 4.42 KB   │ 4.43 KB      │ +0.4% │
├─────────────────────────────────────────────┼───────────┼──────────────┼───────┼───────────┼──────────────┼───────┤
│ react.profiling.min.js  (UMD_PROFILING)     │ 11.45 KB  │ 11.51 KB     │ +0.5% │ 4.42 KB   │ 4.44 KB      │ +0.4% │
├─────────────────────────────────────────────┼───────────┼──────────────┼───────┼───────────┼──────────────┼───────┤
│ react-dom.development.js  (UMD_DEV)         │ 1.07 MB   │ 1.07 MB      │ +0.1% │ 236.54 KB │ 236.89 KB    │ +0.1% │
├─────────────────────────────────────────────┼───────────┼──────────────┼───────┼───────────┼──────────────┼───────┤
│ react-dom.production.min.js  (UMD_PROD)     │ 135.13 KB │ 135.91 KB    │ +0.6% │ 43.93 KB  │ 44.21 KB     │ +0.6% │
├─────────────────────────────────────────────┼───────────┼──────────────┼───────┼───────────┼──────────────┼───────┤
│ react-dom.profiling.min.js  (UMD_PROFILING) │ 143.66 KB │ 144.44 KB    │ +0.5% │ 46.14 KB  │ 46.41 KB     │ +0.6% │
└─────────────────────────────────────────────┴───────────┴──────────────┴───────┴───────────┴──────────────┴───────┘
✨  Done in 36.89s.

This was using the following versions for Rollup and related plugins, which I believe are the latest versions of all of them:

diff --git a/package.json b/package.json
index 2e8445521..eb68a8d60 100644
--- a/package.json
+++ b/package.json
@@ -36,6 +36,10 @@
     "@babel/preset-flow": "^7.10.4",
     "@babel/preset-react": "^7.10.4",
     "@babel/traverse": "^7.11.0",
+    "@rollup/plugin-babel": "^5.3.1",
+    "@rollup/plugin-commonjs": "^22.0.1",
+    "@rollup/plugin-node-resolve": "^13.3.0",
+    "@rollup/plugin-replace": "^4.0.0",
     "abort-controller": "^3.0.0",
     "art": "0.10.1",
     "babel-eslint": "^10.0.3",
@@ -83,13 +87,9 @@
     "random-seed": "^0.3.0",
     "react-lifecycles-compat": "^3.0.4",
     "rimraf": "^3.0.0",
-    "rollup": "^1.19.4",
-    "rollup-plugin-babel": "^4.0.1",
-    "rollup-plugin-commonjs": "^9.3.4",
-    "rollup-plugin-node-resolve": "^2.1.1",
-    "rollup-plugin-prettier": "^0.6.0",
-    "rollup-plugin-replace": "^2.2.0",
-    "rollup-plugin-strip-banner": "^0.2.0",
+    "rollup": "^2.76.0",
+    "rollup-plugin-prettier": "^2.2.2",
+    "rollup-plugin-strip-banner": "^2.0.0",
     "semver": "^7.1.1",
     "targz": "^1.0.1",
     "through2": "^3.0.1",

0xdevalias avatar Jul 13 '22 07:07 0xdevalias