Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Experimental] Move Babel transpile into a cached thread pool #9331

Merged
merged 4 commits into from
Dec 24, 2019

Conversation

developit
Copy link
Contributor

@developit developit commented Nov 7, 2019

This moves babel-loader work into two background threads. Modules are batched up into large groups (potentially even a single group) and sent to the worker(s) to be transpiled.

We've seen this improve build times by more than 5x when both granularChunks and modern are both enabled. This comes at the expense of some overhead transferring large code strings from the worker threads back to the main thread, however research seems to indicate this is worthwhile at least when both flags are enabled.

Still to be decided:

Should threading only be enabled when modern is enabled?

Moving Babel off the main thread is most effective when it's making breathing room for the child compiler instantiated by modern mode.

Should next-babel-loader's caching be disabled in favor of cache-loader?

I've actually not seen consistent results pointing to one being more effective than the other. Intuitively, cache-loader should perform better since it avoids roundtripping cached modules through the threadpool. However, I'm not convinced cache-loader is doing an adequate job of cleaning up invalidated cache entries, and I'm worried it ends up hitting the filesystem more than babel-loader's implementation.

To-Do

  • Decide on whether this should be enabled based on flags
  • Decide which caching implementation to use
  • Modify NextEsmPlugin to append -modern to cache-loader's cacheIdentifier option
  • Make sure babel config changes evict the cache

@ijjk
Copy link
Member

ijjk commented Nov 7, 2019

Stats from current PR

Default Server Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary developit/next.js babel-threadpool Change
buildDuration 13.9s 10.5s -3.4s
nodeModulesSize 49 MB 49.2 MB ⚠️ +239 kB
Client Bundles (main, webpack, commons)
zeit/next.js canary developit/next.js babel-threadpool Change
main-HASH.js 16.6 kB 16.6 kB
main-HASH.js gzip 5.89 kB 5.89 kB
webpack-HASH.js 1.53 kB 1.53 kB
webpack-HASH.js gzip 746 B 746 B
16b1a7225520..7459734ec.js 20.1 kB 20.1 kB
16b1a7225520..34ec.js gzip 7.38 kB 7.38 kB
4952ddcd88e7..bfe360fe6.js 10.5 kB 10.5 kB
4952ddcd88e7..0fe6.js gzip 4.06 kB 4.06 kB
commons.HASH.js 11.3 kB 11.3 kB
commons.HASH.js gzip 4.23 kB 4.23 kB
de003c3a9d30..254ddadd9.js 28.7 kB 28.7 kB
de003c3a9d30..add9.js gzip 10.9 kB 10.9 kB
framework.HASH.js 125 kB 125 kB
framework.HASH.js gzip 39.4 kB 39.4 kB
Overall change 214 kB 214 kB
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary developit/next.js babel-threadpool Change
main-HASH.module.js 14.1 kB 16.6 kB ⚠️ +2.52 kB
main-HASH.module.js gzip 5.31 kB 5.89 kB ⚠️ +580 B
webpack-HASH.module.js 1.53 kB 1.53 kB
webpack-HASH..dule.js gzip 746 B 746 B
16b1a7225520..0d.module.js 16.2 kB N/A N/A
16b1a7225520..dule.js gzip 6.22 kB N/A N/A
4952ddcd88e7..4a.module.js 12.8 kB N/A N/A
4952ddcd88e7..dule.js gzip 4.75 kB N/A N/A
de003c3a9d30..36.module.js 22.2 kB N/A N/A
de003c3a9d30..dule.js gzip 8.71 kB N/A N/A
framework.HASH.module.js 125 kB 125 kB
framework.HA..dule.js gzip 39.4 kB 39.4 kB
16b1a7225520..ec.module.js N/A 20.1 kB N/A
16b1a7225520..dule.js gzip N/A 7.38 kB N/A
4952ddcd88e7..e6.module.js N/A 10.5 kB N/A
4952ddcd88e7..dule.js gzip N/A 4.06 kB N/A
commons.HASH.module.js N/A 11.3 kB N/A
commons.HASH..dule.js gzip N/A 4.23 kB N/A
de003c3a9d30..d9.module.js N/A 28.7 kB N/A
de003c3a9d30..dule.js gzip N/A 10.9 kB N/A
Overall change 192 kB 214 kB ⚠️ +2.52 kB
Legacy Client Bundles (polyfills)
zeit/next.js canary developit/next.js babel-threadpool Change
polyfills-HASH.js 8.14 kB 8.14 kB
polyfills-HASH.js gzip 2.76 kB 2.76 kB
Overall change 8.14 kB 8.14 kB
Client Pages
zeit/next.js canary developit/next.js babel-threadpool Change
_app.js 1.63 kB 1.63 kB
_app.js gzip 788 B 788 B
_error.js 12.3 kB 12.3 kB
_error.js gzip 4.79 kB 4.79 kB
hooks.js 1.92 kB 1.92 kB
hooks.js gzip 941 B 941 B
index.js 318 B 318 B
index.js gzip 222 B 222 B
link.js 5.81 kB 5.81 kB
link.js gzip 2.56 kB 2.56 kB
routerDirect.js 413 B 413 B
routerDirect.js gzip 285 B 285 B
withRouter.js 423 B 423 B
withRouter.js gzip 284 B 284 B
Overall change 22.8 kB 22.8 kB
Client Pages Modern Overall increase ⚠️
zeit/next.js canary developit/next.js babel-threadpool Change
_app.module.js 1.54 kB 1.63 kB ⚠️ +85 B
_app.module.js gzip 759 B 788 B ⚠️ +29 B
_error.module.js 10.5 kB 12.3 kB ⚠️ +1.75 kB
_error.module.js gzip 4.26 kB 4.79 kB ⚠️ +526 B
hooks.module.js 1.52 kB 1.92 kB ⚠️ +395 B
hooks.module.js gzip 792 B 941 B ⚠️ +149 B
index.module.js 292 B 318 B ⚠️ +26 B
index.module.js gzip 223 B 222 B -1 B
link.module.js 5.49 kB 5.81 kB ⚠️ +318 B
link.module.js gzip 2.47 kB 2.56 kB ⚠️ +99 B
routerDirect.module.js 399 B 413 B ⚠️ +14 B
routerDirect..dule.js gzip 285 B 285 B
withRouter.module.js 409 B 423 B ⚠️ +14 B
withRouter.m..dule.js gzip 282 B 284 B ⚠️ +2 B
Overall change 20.2 kB 22.8 kB ⚠️ +2.6 kB
Client Build Manifests
zeit/next.js canary developit/next.js babel-threadpool Change
_buildManifest.js 244 B 244 B
_buildManifest.js gzip 201 B 201 B
_buildManifest.module.js 251 B 251 B
_buildManife..dule.js gzip 209 B 206 B -3 B
Overall change 495 B 495 B
Rendered Page Sizes Overall increase ⚠️
zeit/next.js canary developit/next.js babel-threadpool Change
index.html 4.06 kB 4.31 kB ⚠️ +254 B
index.html gzip 1.03 kB 992 B -43 B
link.html 4.58 kB 4.83 kB ⚠️ +254 B
link.html gzip 1.11 kB 1.06 kB -56 B
withRouter.html 4.59 kB 4.84 kB ⚠️ +254 B
withRouter.html gzip 1.1 kB 1.05 kB -57 B
Overall change 13.2 kB 14 kB ⚠️ +762 B

Diffs

Diff for main-HASH.module.js

Diff too large to display

Diff for framework.HASH.module.js
@@ -1,4 +1,4 @@
-(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[1],{
+(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[2],{
 
 /***/ "+wdc":
 /***/ (function(module, exports, __webpack_require__) {
Diff for _app.module.js
@@ -1,62 +1,29 @@
-(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[5],{
+(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[6],{
 
-/***/ "+oT+":
+/***/ "B5Ud":
 /***/ (function(module, exports, __webpack_require__) {
 
-var _Promise = __webpack_require__("eVuF");
-
-function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
-  try {
-    var info = gen[key](arg);
-    var value = info.value;
-  } catch (error) {
-    reject(error);
-    return;
-  }
-
-  if (info.done) {
-    resolve(value);
-  } else {
-    _Promise.resolve(value).then(_next, _throw);
-  }
-}
-
-function _asyncToGenerator(fn) {
-  return function () {
-    var self = this,
-        args = arguments;
-    return new _Promise(function (resolve, reject) {
-      var gen = fn.apply(self, args);
-
-      function _next(value) {
-        asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
-      }
+"use strict";
 
-      function _throw(err) {
-        asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
-      }
 
-      _next(undefined);
-    });
-  };
-}
+var _classCallCheck = __webpack_require__("/HRN");
 
-module.exports = _asyncToGenerator;
+var _createClass = __webpack_require__("WaGi");
 
-/***/ }),
+var _possibleConstructorReturn = __webpack_require__("ZDA2");
 
-/***/ "B5Ud":
-/***/ (function(module, exports, __webpack_require__) {
+var _getPrototypeOf = __webpack_require__("/+P4");
 
-"use strict";
+var _inherits = __webpack_require__("N9n2");
 
+var _regeneratorRuntime = __webpack_require__("ln6h");
 
 var _interopRequireDefault = __webpack_require__("KI45");
 
 exports.__esModule = true;
 exports.Container = Container;
 exports.createUrl = createUrl;
-exports.default = void 0;
+exports["default"] = void 0;
 
 var _extends2 = _interopRequireDefault(__webpack_require__("htGi"));
 
@@ -77,42 +44,71 @@ function appGetInitialProps(_x) {
 }
 
 function _appGetInitialProps() {
-  _appGetInitialProps = (0, _asyncToGenerator2.default)(function* (_ref) {
-    var {
-      Component,
-      ctx
-    } = _ref;
-    var pageProps = yield (0, _utils.loadGetInitialProps)(Component, ctx);
-    return {
-      pageProps
-    };
-  });
+  _appGetInitialProps = (0, _asyncToGenerator2["default"])(
+  /*#__PURE__*/
+  _regeneratorRuntime.mark(function _callee(_ref) {
+    var Component, ctx, pageProps;
+    return _regeneratorRuntime.wrap(function _callee$(_context) {
+      while (1) {
+        switch (_context.prev = _context.next) {
+          case 0:
+            Component = _ref.Component, ctx = _ref.ctx;
+            _context.next = 3;
+            return (0, _utils.loadGetInitialProps)(Component, ctx);
+
+          case 3:
+            pageProps = _context.sent;
+            return _context.abrupt("return", {
+              pageProps: pageProps
+            });
+
+          case 5:
+          case "end":
+            return _context.stop();
+        }
+      }
+    }, _callee);
+  }));
   return _appGetInitialProps.apply(this, arguments);
 }
 
-class App extends _react.default.Component {
-  // Kept here for backwards compatibility.
-  // When someone ended App they could call `super.componentDidCatch`.
-  // @deprecated This method is no longer needed. Errors are caught at the top level
-  componentDidCatch(error, _errorInfo) {
-    throw error;
-  }
+var App =
+/*#__PURE__*/
+function (_react$default$Compon) {
+  _inherits(App, _react$default$Compon);
+
+  function App() {
+    _classCallCheck(this, App);
 
-  render() {
-    var {
-      router,
-      Component,
-      pageProps
-    } = this.props;
-    var url = createUrl(router);
-    return _react.default.createElement(Component, (0, _extends2.default)({}, pageProps, {
-      url: url
-    }));
+    return _possibleConstructorReturn(this, _getPrototypeOf(App).apply(this, arguments));
   }
 
-}
+  _createClass(App, [{
+    key: "componentDidCatch",
+    // Kept here for backwards compatibility.
+    // When someone ended App they could call `super.componentDidCatch`.
+    // @deprecated This method is no longer needed. Errors are caught at the top level
+    value: function componentDidCatch(error, _errorInfo) {
+      throw error;
+    }
+  }, {
+    key: "render",
+    value: function render() {
+      var _this$props = this.props,
+          router = _this$props.router,
+          Component = _this$props.Component,
+          pageProps = _this$props.pageProps;
+      var url = createUrl(router);
+      return _react["default"].createElement(Component, (0, _extends2["default"])({}, pageProps, {
+        url: url
+      }));
+    }
+  }]);
+
+  return App;
+}(_react["default"].Component);
 
-exports.default = App;
+exports["default"] = App;
 App.origGetInitialProps = appGetInitialProps;
 App.getInitialProps = appGetInitialProps;
 var warnContainer;
@@ -128,11 +124,9 @@ function Container(p) {
 
 function createUrl(router) {
   // This is to make sure we don't references the router object at call time
-  var {
-    pathname,
-    asPath,
-    query
-  } = router;
+  var pathname = router.pathname,
+      asPath = router.asPath,
+      query = router.query;
   return {
     get query() {
       if (false) {}
@@ -149,25 +143,25 @@ function createUrl(router) {
       return asPath;
     },
 
-    back: () => {
+    back: function back() {
       if (false) {}
       router.back();
     },
-    push: (url, as) => {
+    push: function push(url, as) {
       if (false) {}
       return router.push(url, as);
     },
-    pushTo: (href, as) => {
+    pushTo: function pushTo(href, as) {
       if (false) {}
       var pushRoute = as ? href : '';
       var pushUrl = as || href;
       return router.push(pushRoute, pushUrl);
     },
-    replace: (url, as) => {
+    replace: function replace(url, as) {
       if (false) {}
       return router.replace(url, as);
     },
-    replaceTo: (href, as) => {
+    replaceTo: function replaceTo(href, as) {
       if (false) {}
       var replaceRoute = as ? href : '';
       var replaceUrl = as || href;
@@ -191,4 +185,4 @@ function createUrl(router) {
 
 /***/ })
 
-},[["e9+W",0,1,2,3]]]);
\ No newline at end of file
+},[["e9+W",0,2,1,3,4]]]);
\ No newline at end of file
Diff for _error.module.js
@@ -1,4 +1,4 @@
-(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[6],{
+(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[7],{
 
 /***/ "+iuc":
 /***/ (function(module, exports, __webpack_require__) {
@@ -38,11 +38,14 @@ var react_1 = __importDefault(__webpack_require__("q1tI"));
 var amp_context_1 = __webpack_require__("lwAK");
 
 function isInAmpMode() {
-  var {
-    ampFirst = false,
-    hybrid = false,
-    hasQuery = false
-  } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+  var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
+      _ref$ampFirst = _ref.ampFirst,
+      ampFirst = _ref$ampFirst === void 0 ? false : _ref$ampFirst,
+      _ref$hybrid = _ref.hybrid,
+      hybrid = _ref$hybrid === void 0 ? false : _ref$hybrid,
+      _ref$hasQuery = _ref.hasQuery,
+      hasQuery = _ref$hasQuery === void 0 ? false : _ref$hasQuery;
+
   return ampFirst || hybrid && hasQuery;
 }
 
@@ -50,7 +53,7 @@ exports.isInAmpMode = isInAmpMode;
 
 function useAmp() {
   // Don't assign the context value to a variable to save bytes
-  return isInAmpMode(react_1.default.useContext(amp_context_1.AmpStateContext));
+  return isInAmpMode(react_1["default"].useContext(amp_context_1.AmpStateContext));
 }
 
 exports.useAmp = useAmp;
@@ -63,10 +66,20 @@ exports.useAmp = useAmp;
 "use strict";
 
 
+var _classCallCheck = __webpack_require__("/HRN");
+
+var _createClass = __webpack_require__("WaGi");
+
+var _possibleConstructorReturn = __webpack_require__("ZDA2");
+
+var _getPrototypeOf = __webpack_require__("/+P4");
+
+var _inherits = __webpack_require__("N9n2");
+
 var _interopRequireDefault = __webpack_require__("KI45");
 
 exports.__esModule = true;
-exports.default = void 0;
+exports["default"] = void 0;
 
 var _react = _interopRequireDefault(__webpack_require__("q1tI"));
 
@@ -82,41 +95,52 @@ var statusCodes = {
 * `Error` component used for handling errors.
 */
 
-class Error extends _react.default.Component {
-  static getInitialProps(_ref) {
-    var {
-      res,
-      err
-    } = _ref;
-    var statusCode = res && res.statusCode ? res.statusCode : err ? err.statusCode : 404;
-    return {
-      statusCode
-    };
-  }
+var Error =
+/*#__PURE__*/
+function (_react$default$Compon) {
+  _inherits(Error, _react$default$Compon);
 
-  render() {
-    var {
-      statusCode
-    } = this.props;
-    var title = this.props.title || statusCodes[statusCode] || 'An unexpected error has occurred';
-    return _react.default.createElement("div", {
-      style: styles.error
-    }, _react.default.createElement(_head.default, null, _react.default.createElement("title", null, statusCode, ": ", title)), _react.default.createElement("div", null, _react.default.createElement("style", {
-      dangerouslySetInnerHTML: {
-        __html: 'body { margin: 0 }'
-      }
-    }), statusCode ? _react.default.createElement("h1", {
-      style: styles.h1
-    }, statusCode) : null, _react.default.createElement("div", {
-      style: styles.desc
-    }, _react.default.createElement("h2", {
-      style: styles.h2
-    }, title, "."))));
+  function Error() {
+    _classCallCheck(this, Error);
+
+    return _possibleConstructorReturn(this, _getPrototypeOf(Error).apply(this, arguments));
   }
 
-}
+  _createClass(Error, [{
+    key: "render",
+    value: function render() {
+      var statusCode = this.props.statusCode;
+      var title = this.props.title || statusCodes[statusCode] || 'An unexpected error has occurred';
+      return _react["default"].createElement("div", {
+        style: styles.error
+      }, _react["default"].createElement(_head["default"], null, _react["default"].createElement("title", null, statusCode, ": ", title)), _react["default"].createElement("div", null, _react["default"].createElement("style", {
+        dangerouslySetInnerHTML: {
+          __html: 'body { margin: 0 }'
+        }
+      }), statusCode ? _react["default"].createElement("h1", {
+        style: styles.h1
+      }, statusCode) : null, _react["default"].createElement("div", {
+        style: styles.desc
+      }, _react["default"].createElement("h2", {
+        style: styles.h2
+      }, title, "."))));
+    }
+  }], [{
+    key: "getInitialProps",
+    value: function getInitialProps(_ref) {
+      var res = _ref.res,
+          err = _ref.err;
+      var statusCode = res && res.statusCode ? res.statusCode : err ? err.statusCode : 404;
+      return {
+        statusCode: statusCode
+      };
+    }
+  }]);
+
+  return Error;
+}(_react["default"].Component);
 
-exports.default = Error;
+exports["default"] = Error;
 Error.displayName = 'ErrorPage';
 var styles = {
   error: {
@@ -171,66 +195,27 @@ var styles = {
 
 /***/ }),
 
-/***/ "6/1s":
+/***/ "0tVQ":
 /***/ (function(module, exports, __webpack_require__) {
 
-var META = __webpack_require__("YqAc")('meta');
-var isObject = __webpack_require__("93I4");
-var has = __webpack_require__("B+OT");
-var setDesc = __webpack_require__("2faE").f;
-var id = 0;
-var isExtensible = Object.isExtensible || function () {
-  return true;
-};
-var FREEZE = !__webpack_require__("KUxP")(function () {
-  return isExtensible(Object.preventExtensions({}));
-});
-var setMeta = function (it) {
-  setDesc(it, META, { value: {
-    i: 'O' + ++id, // object ID
-    w: {}          // weak collections IDs
-  } });
-};
-var fastKey = function (it, create) {
-  // return primitive with prefix
-  if (!isObject(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;
-  if (!has(it, META)) {
-    // can't set metadata to uncaught frozen object
-    if (!isExtensible(it)) return 'F';
-    // not necessary to add metadata
-    if (!create) return 'E';
-    // add missing metadata
-    setMeta(it);
-  // return object ID
-  } return it[META].i;
-};
-var getWeak = function (it, create) {
-  if (!has(it, META)) {
-    // can't set metadata to uncaught frozen object
-    if (!isExtensible(it)) return true;
-    // not necessary to add metadata
-    if (!create) return false;
-    // add missing metadata
-    setMeta(it);
-  // return hash weak collections IDs
-  } return it[META].w;
-};
-// add metadata on freeze-family methods calling
-var onFreeze = function (it) {
-  if (FREEZE && meta.NEED && isExtensible(it) && !has(it, META)) setMeta(it);
-  return it;
-};
-var meta = module.exports = {
-  KEY: META,
-  NEED: false,
-  fastKey: fastKey,
-  getWeak: getWeak,
-  onFreeze: onFreeze
-};
+__webpack_require__("FlQf");
+__webpack_require__("VJsP");
+module.exports = __webpack_require__("WEpk").Array.from;
 
 
 /***/ }),
 
+/***/ "2PDY":
+/***/ (function(module, exports) {
+
+function _nonIterableSpread() {
+  throw new TypeError("Invalid attempt to spread non-iterable instance");
+}
+
+module.exports = _nonIterableSpread;
+
+/***/ }),
+
 /***/ "8Kt/":
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -263,13 +248,13 @@ var amp_1 = __webpack_require__("/0+H");
 
 function defaultHead() {
   var inAmpMode = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
-  var head = [react_1.default.createElement("meta", {
+  var head = [react_1["default"].createElement("meta", {
     key: "charSet",
     charSet: "utf-8"
   })];
 
   if (!inAmpMode) {
-    head.push(react_1.default.createElement("meta", {
+    head.push(react_1["default"].createElement("meta", {
       key: "viewport",
       name: "viewport",
       content: "width=device-width,minimum-scale=1,initial-scale=1"
@@ -288,8 +273,8 @@ function onlyReactElement(list, child) {
   } // Adds support for React.Fragment
 
 
-  if (child.type === react_1.default.Fragment) {
-    return list.concat(react_1.default.Children.toArray(child.props.children).reduce((fragmentList, fragmentChild) => {
+  if (child.type === react_1["default"].Fragment) {
+    return list.concat(react_1["default"].Children.toArray(child.props.children).reduce(function (fragmentList, fragmentChild) {
       if (typeof fragmentChild === 'string' || typeof fragmentChild === 'number') {
         return fragmentList;
       }
@@ -313,7 +298,7 @@ function unique() {
   var tags = new _Set();
   var metaTypes = new _Set();
   var metaCategories = {};
-  return h => {
+  return function (h) {
     if (h.key && typeof h.key !== 'number' && h.key.indexOf('.$') === 0) {
       if (keys.has(h.key)) return false;
       keys.add(h.key);
@@ -362,36 +347,38 @@ function unique() {
 
 
 function reduceComponents(headElements, props) {
-  return headElements.reduce((list, headElement) => {
-    var headElementChildren = react_1.default.Children.toArray(headElement.props.children);
+  return headElements.reduce(function (list, headElement) {
+    var headElementChildren = react_1["default"].Children.toArray(headElement.props.children);
     return list.concat(headElementChildren);
-  }, []).reduce(onlyReactElement, []).reverse().concat(defaultHead(props.inAmpMode)).filter(unique()).reverse().map((c, i) => {
+  }, []).reduce(onlyReactElement, []).reverse().concat(defaultHead(props.inAmpMode)).filter(unique()).reverse().map(function (c, i) {
     var key = c.key || i;
-    return react_1.default.cloneElement(c, {
-      key
+    return react_1["default"].cloneElement(c, {
+      key: key
     });
   });
 }
 
-var Effect = side_effect_1.default();
+var Effect = side_effect_1["default"]();
 /**
  * This component injects elements to `<head>` of your page.
  * To avoid duplicated `tags` in `<head>` you can use the `key` property, which will make sure every tag is only rendered once.
  */
 
 function Head(_ref) {
-  var {
-    children
-  } = _ref;
-  return react_1.default.createElement(amp_context_1.AmpStateContext.Consumer, null, ampState => react_1.default.createElement(head_manager_context_1.HeadManagerContext.Consumer, null, updateHead => react_1.default.createElement(Effect, {
-    reduceComponentsToState: reduceComponents,
-    handleStateChange: updateHead,
-    inAmpMode: amp_1.isInAmpMode(ampState)
-  }, children)));
+  var children = _ref.children;
+  return react_1["default"].createElement(amp_context_1.AmpStateContext.Consumer, null, function (ampState) {
+    return react_1["default"].createElement(head_manager_context_1.HeadManagerContext.Consumer, null, function (updateHead) {
+      return react_1["default"].createElement(Effect, {
+        reduceComponentsToState: reduceComponents,
+        handleStateChange: updateHead,
+        inAmpMode: amp_1.isInAmpMode(ampState)
+      }, children);
+    });
+  });
 }
 
 Head.rewind = Effect.rewind;
-exports.default = Head;
+exports["default"] = Head;
 
 /***/ }),
 
@@ -411,6 +398,15 @@ module.exports = function (NAME) {
 
 /***/ }),
 
+/***/ "9BDd":
+/***/ (function(module, exports, __webpack_require__) {
+
+__webpack_require__("GvbO");
+module.exports = __webpack_require__("WEpk").Array.isArray;
+
+
+/***/ }),
+
 /***/ "B9jh":
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -484,6 +480,48 @@ exports.HeadManagerContext = React.createContext(null);
 
 /***/ }),
 
+/***/ "GvbO":
+/***/ (function(module, exports, __webpack_require__) {
+
+// 22.1.2.2 / 15.4.3.2 Array.isArray(arg)
+var $export = __webpack_require__("Y7ZC");
+
+$export($export.S, 'Array', { isArray: __webpack_require__("kAMH") });
+
+
+/***/ }),
+
+/***/ "IP1Z":
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+var $defineProperty = __webpack_require__("2faE");
+var createDesc = __webpack_require__("rr1i");
+
+module.exports = function (object, index, value) {
+  if (index in object) $defineProperty.f(object, index, createDesc(0, value));
+  else object[index] = value;
+};
+
+
+/***/ }),
+
+/***/ "PQJW":
+/***/ (function(module, exports, __webpack_require__) {
+
+var _Array$from = __webpack_require__("d04V");
+
+var _isIterable = __webpack_require__("yLu3");
+
+function _iterableToArray(iter) {
+  if (_isIterable(Object(iter)) || Object.prototype.toString.call(iter) === "[object Arguments]") return _Array$from(iter);
+}
+
+module.exports = _iterableToArray;
+
+/***/ }),
+
 /***/ "RRc/":
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -498,6 +536,23 @@ module.exports = function (iter, ITERATOR) {
 
 /***/ }),
 
+/***/ "TbGu":
+/***/ (function(module, exports, __webpack_require__) {
+
+var arrayWithoutHoles = __webpack_require__("fGSI");
+
+var iterableToArray = __webpack_require__("PQJW");
+
+var nonIterableSpread = __webpack_require__("2PDY");
+
+function _toConsumableArray(arr) {
+  return arrayWithoutHoles(arr) || iterableToArray(arr) || nonIterableSpread();
+}
+
+module.exports = _toConsumableArray;
+
+/***/ }),
+
 /***/ "V+O7":
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -558,6 +613,61 @@ module.exports = function (TYPE, $create) {
 
 /***/ }),
 
+/***/ "VJsP":
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+var ctx = __webpack_require__("2GTP");
+var $export = __webpack_require__("Y7ZC");
+var toObject = __webpack_require__("JB68");
+var call = __webpack_require__("sNwI");
+var isArrayIter = __webpack_require__("NwJ3");
+var toLength = __webpack_require__("tEej");
+var createProperty = __webpack_require__("IP1Z");
+var getIterFn = __webpack_require__("fNZA");
+
+$export($export.S + $export.F * !__webpack_require__("TuGD")(function (iter) { Array.from(iter); }), 'Array', {
+  // 22.1.2.1 Array.from(arrayLike, mapfn = undefined, thisArg = undefined)
+  from: function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) {
+    var O = toObject(arrayLike);
+    var C = typeof this == 'function' ? this : Array;
+    var aLen = arguments.length;
+    var mapfn = aLen > 1 ? arguments[1] : undefined;
+    var mapping = mapfn !== undefined;
+    var index = 0;
+    var iterFn = getIterFn(O);
+    var length, result, step, iterator;
+    if (mapping) mapfn = ctx(mapfn, aLen > 2 ? arguments[2] : undefined, 2);
+    // if object isn't iterable or it's array with default iterator - use simple case
+    if (iterFn != undefined && !(C == Array && isArrayIter(iterFn))) {
+      for (iterator = iterFn.call(O), result = new C(); !(step = iterator.next()).done; index++) {
+        createProperty(result, index, mapping ? call(iterator, mapfn, [step.value, index], true) : step.value);
+      }
+    } else {
+      length = toLength(O.length);
+      for (result = new C(length); length > index; index++) {
+        createProperty(result, index, mapping ? mapfn(O[index], index) : O[index]);
+      }
+    }
+    result.length = index;
+    return result;
+  }
+});
+
+
+/***/ }),
+
+/***/ "VKFn":
+/***/ (function(module, exports, __webpack_require__) {
+
+__webpack_require__("bBy9");
+__webpack_require__("FlQf");
+module.exports = __webpack_require__("ldVq");
+
+
+/***/ }),
+
 /***/ "Wu5q":
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -716,6 +826,20 @@ module.exports = {
 "use strict";
 
 
+var _classCallCheck = __webpack_require__("/HRN");
+
+var _possibleConstructorReturn = __webpack_require__("ZDA2");
+
+var _getPrototypeOf = __webpack_require__("/+P4");
+
+var _assertThisInitialized = __webpack_require__("K47E");
+
+var _createClass = __webpack_require__("WaGi");
+
+var _inherits = __webpack_require__("N9n2");
+
+var _toConsumableArray = __webpack_require__("TbGu");
+
 var _Set = __webpack_require__("ttDY");
 
 var _Object$defineProperty = __webpack_require__("hfKm");
@@ -728,55 +852,76 @@ var react_1 = __webpack_require__("q1tI");
 
 var isServer = false;
 
-exports.default = () => {
+exports["default"] = function () {
   var mountedInstances = new _Set();
   var state;
 
   function emitChange(component) {
-    state = component.props.reduceComponentsToState([...mountedInstances], component.props);
+    state = component.props.reduceComponentsToState(_toConsumableArray(mountedInstances), component.props);
 
     if (component.props.handleStateChange) {
       component.props.handleStateChange(state);
     }
   }
 
-  return class extends react_1.Component {
-    // Used when server rendering
-    static rewind() {
-      var recordedState = state;
-      state = undefined;
-      mountedInstances.clear();
-      return recordedState;
-    }
+  return (
+    /*#__PURE__*/
+    function (_react_1$Component) {
+      _inherits(_class, _react_1$Component);
+
+      _createClass(_class, null, [{
+        key: "rewind",
+        // Used when server rendering
+        value: function rewind() {
+          var recordedState = state;
+          state = undefined;
+          mountedInstances.clear();
+          return recordedState;
+        }
+      }]);
 
-    constructor(props) {
-      super(props);
+      function _class(props) {
+        var _this;
 
-      if (isServer) {
-        mountedInstances.add(this);
-        emitChange(this);
-      }
-    }
+        _classCallCheck(this, _class);
 
-    componentDidMount() {
-      mountedInstances.add(this);
-      emitChange(this);
-    }
+        _this = _possibleConstructorReturn(this, _getPrototypeOf(_class).call(this, props));
 
-    componentDidUpdate() {
-      emitChange(this);
-    }
+        if (isServer) {
+          mountedInstances.add(_assertThisInitialized(_this));
+          emitChange(_assertThisInitialized(_this));
+        }
 
-    componentWillUnmount() {
-      mountedInstances.delete(this);
-      emitChange(this);
-    }
+        return _this;
+      }
 
-    render() {
-      return null;
-    }
+      _createClass(_class, [{
+        key: "componentDidMount",
+        value: function componentDidMount() {
+          mountedInstances.add(this);
+          emitChange(this);
+        }
+      }, {
+        key: "componentDidUpdate",
+        value: function componentDidUpdate() {
+          emitChange(this);
+        }
+      }, {
+        key: "componentWillUnmount",
+        value: function componentWillUnmount() {
+          mountedInstances["delete"](this);
+          emitChange(this);
+        }
+      }, {
+        key: "render",
+        value: function render() {
+          return null;
+        }
+      }]);
 
-  };
+      return _class;
+    }(react_1.Component)
+  );
 };
 
 /***/ }),
@@ -837,6 +982,13 @@ module.exports = function (COLLECTION) {
 
 /***/ }),
 
+/***/ "d04V":
+/***/ (function(module, exports, __webpack_require__) {
+
+module.exports = __webpack_require__("0tVQ");
+
+/***/ }),
+
 /***/ "dL40":
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -848,13 +1000,37 @@ $export($export.P + $export.R, 'Set', { toJSON: __webpack_require__("8iia")('Set
 
 /***/ }),
 
-/***/ "kAMH":
+/***/ "fGSI":
+/***/ (function(module, exports, __webpack_require__) {
+
+var _Array$isArray = __webpack_require__("p0XB");
+
+function _arrayWithoutHoles(arr) {
+  if (_Array$isArray(arr)) {
+    for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) {
+      arr2[i] = arr[i];
+    }
+
+    return arr2;
+  }
+}
+
+module.exports = _arrayWithoutHoles;
+
+/***/ }),
+
+/***/ "ldVq":
 /***/ (function(module, exports, __webpack_require__) {
 
-// 7.2.2 IsArray(argument)
-var cof = __webpack_require__("a0xu");
-module.exports = Array.isArray || function isArray(arg) {
-  return cof(arg) == 'Array';
+var classof = __webpack_require__("QMMT");
+var ITERATOR = __webpack_require__("UWiX")('iterator');
+var Iterators = __webpack_require__("SBuE");
+module.exports = __webpack_require__("WEpk").isIterable = function (it) {
+  var O = Object(it);
+  return O[ITERATOR] !== undefined
+    || '@@iterator' in O
+    // eslint-disable-next-line no-prototype-builtins
+    || Iterators.hasOwnProperty(classof(O));
 };
 
 
@@ -900,6 +1076,13 @@ module.exports = function (it, TYPE) {
 
 /***/ }),
 
+/***/ "p0XB":
+/***/ (function(module, exports, __webpack_require__) {
+
+module.exports = __webpack_require__("9BDd");
+
+/***/ }),
+
 /***/ "raTm":
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -994,6 +1177,13 @@ module.exports = function (original, length) {
 __webpack_require__("cHUd")('Set');
 
 
+/***/ }),
+
+/***/ "yLu3":
+/***/ (function(module, exports, __webpack_require__) {
+
+module.exports = __webpack_require__("VKFn");
+
 /***/ })
 
-},[["04ac",0,1,2]]]);
\ No newline at end of file
+},[["04ac",0,2,1,3]]]);
\ No newline at end of file
Diff for hooks.module.js
@@ -1,27 +1,96 @@
-(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[7],{
+(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[8],{
 
 /***/ "+MDD":
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 
 "use strict";
 __webpack_require__.r(__webpack_exports__);
-/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("q1tI");
-/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
-var __jsx = react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement;
-
-/* harmony default export */ __webpack_exports__["default"] = (() => {
-  var [clicks1, setClicks1] = react__WEBPACK_IMPORTED_MODULE_0___default.a.useState(0);
-  var {
-    0: clicks2,
-    1: setClicks2
-  } = Object(react__WEBPACK_IMPORTED_MODULE_0__["useState"])(0);
-  var doClick1 = react__WEBPACK_IMPORTED_MODULE_0___default.a.useCallback(() => {
+
+// EXTERNAL MODULE: ./node_modules/@babel/runtime-corejs2/core-js/array/is-array.js
+var is_array = __webpack_require__("p0XB");
+var is_array_default = /*#__PURE__*/__webpack_require__.n(is_array);
+
+// CONCATENATED MODULE: ./node_modules/@babel/runtime-corejs2/helpers/esm/arrayWithHoles.js
+
+function _arrayWithHoles(arr) {
+  if (is_array_default()(arr)) return arr;
+}
+// EXTERNAL MODULE: ./node_modules/@babel/runtime-corejs2/core-js/get-iterator.js
+var get_iterator = __webpack_require__("XXOK");
+var get_iterator_default = /*#__PURE__*/__webpack_require__.n(get_iterator);
+
+// EXTERNAL MODULE: ./node_modules/@babel/runtime-corejs2/core-js/is-iterable.js
+var is_iterable = __webpack_require__("yLu3");
+var is_iterable_default = /*#__PURE__*/__webpack_require__.n(is_iterable);
+
+// CONCATENATED MODULE: ./node_modules/@babel/runtime-corejs2/helpers/esm/iterableToArrayLimit.js
+
+
+function _iterableToArrayLimit(arr, i) {
+  if (!(is_iterable_default()(Object(arr)) || Object.prototype.toString.call(arr) === "[object Arguments]")) {
+    return;
+  }
+
+  var _arr = [];
+  var _n = true;
+  var _d = false;
+  var _e = undefined;
+
+  try {
+    for (var _i = get_iterator_default()(arr), _s; !(_n = (_s = _i.next()).done); _n = true) {
+      _arr.push(_s.value);
+
+      if (i && _arr.length === i) break;
+    }
+  } catch (err) {
+    _d = true;
+    _e = err;
+  } finally {
+    try {
+      if (!_n && _i["return"] != null) _i["return"]();
+    } finally {
+      if (_d) throw _e;
+    }
+  }
+
+  return _arr;
+}
+// CONCATENATED MODULE: ./node_modules/@babel/runtime-corejs2/helpers/esm/nonIterableRest.js
+function _nonIterableRest() {
+  throw new TypeError("Invalid attempt to destructure non-iterable instance");
+}
+// CONCATENATED MODULE: ./node_modules/@babel/runtime-corejs2/helpers/esm/slicedToArray.js
+
+
+
+function _slicedToArray(arr, i) {
+  return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();
+}
+// EXTERNAL MODULE: ./node_modules/react/index.js
+var react = __webpack_require__("q1tI");
+var react_default = /*#__PURE__*/__webpack_require__.n(react);
+
+// CONCATENATED MODULE: ./pages/hooks.js
+
+var __jsx = react_default.a.createElement;
+
+/* harmony default export */ var hooks = __webpack_exports__["default"] = (function () {
+  var _React$useState = react_default.a.useState(0),
+      _React$useState2 = _slicedToArray(_React$useState, 2),
+      clicks1 = _React$useState2[0],
+      setClicks1 = _React$useState2[1];
+
+  var _useState = Object(react["useState"])(0),
+      clicks2 = _useState[0],
+      setClicks2 = _useState[1];
+
+  var doClick1 = react_default.a.useCallback(function () {
     setClicks1(clicks1 + 1);
   }, [clicks1]);
-  var doClick2 = Object(react__WEBPACK_IMPORTED_MODULE_0__["useCallback"])(() => {
+  var doClick2 = Object(react["useCallback"])(function () {
     setClicks2(clicks2 + 1);
   }, [clicks2]);
-  return __jsx(react__WEBPACK_IMPORTED_MODULE_0___default.a.Fragment, null, __jsx("h3", null, "Clicks ", clicks1), __jsx("button", {
+  return __jsx(react_default.a.Fragment, null, __jsx("h3", null, "Clicks ", clicks1), __jsx("button", {
     onClick: doClick1
   }, "Click me"), __jsx("h3", null, "Clicks ", clicks2), __jsx("button", {
     onClick: doClick2
@@ -30,99 +99,62 @@ var __jsx = react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement;
 
 /***/ }),
 
-/***/ "MgzW":
+/***/ "9BDd":
 /***/ (function(module, exports, __webpack_require__) {
 
-"use strict";
-/*
-object-assign
-(c) Sindre Sorhus
-@license MIT
-*/
+__webpack_require__("GvbO");
+module.exports = __webpack_require__("WEpk").Array.isArray;
 
 
-/* eslint-disable no-unused-vars */
-var getOwnPropertySymbols = Object.getOwnPropertySymbols;
-var hasOwnProperty = Object.prototype.hasOwnProperty;
-var propIsEnumerable = Object.prototype.propertyIsEnumerable;
+/***/ }),
 
-function toObject(val) {
-	if (val === null || val === undefined) {
-		throw new TypeError('Object.assign cannot be called with null or undefined');
-	}
+/***/ "GvbO":
+/***/ (function(module, exports, __webpack_require__) {
 
-	return Object(val);
-}
+// 22.1.2.2 / 15.4.3.2 Array.isArray(arg)
+var $export = __webpack_require__("Y7ZC");
 
-function shouldUseNative() {
-	try {
-		if (!Object.assign) {
-			return false;
-		}
-
-		// Detect buggy property enumeration order in older V8 versions.
-
-		// https://bugs.chromium.org/p/v8/issues/detail?id=4118
-		var test1 = new String('abc');  // eslint-disable-line no-new-wrappers
-		test1[5] = 'de';
-		if (Object.getOwnPropertyNames(test1)[0] === '5') {
-			return false;
-		}
-
-		// https://bugs.chromium.org/p/v8/issues/detail?id=3056
-		var test2 = {};
-		for (var i = 0; i < 10; i++) {
-			test2['_' + String.fromCharCode(i)] = i;
-		}
-		var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
-			return test2[n];
-		});
-		if (order2.join('') !== '0123456789') {
-			return false;
-		}
-
-		// https://bugs.chromium.org/p/v8/issues/detail?id=3056
-		var test3 = {};
-		'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
-			test3[letter] = letter;
-		});
-		if (Object.keys(Object.assign({}, test3)).join('') !==
-				'abcdefghijklmnopqrst') {
-			return false;
-		}
-
-		return true;
-	} catch (err) {
-		// We don't expect any of the above to throw, but better to be safe.
-		return false;
-	}
-}
+$export($export.S, 'Array', { isArray: __webpack_require__("kAMH") });
+
+
+/***/ }),
 
-module.exports = shouldUseNative() ? Object.assign : function (target, source) {
-	var from;
-	var to = toObject(target);
-	var symbols;
-
-	for (var s = 1; s < arguments.length; s++) {
-		from = Object(arguments[s]);
-
-		for (var key in from) {
-			if (hasOwnProperty.call(from, key)) {
-				to[key] = from[key];
-			}
-		}
-
-		if (getOwnPropertySymbols) {
-			symbols = getOwnPropertySymbols(from);
-			for (var i = 0; i < symbols.length; i++) {
-				if (propIsEnumerable.call(from, symbols[i])) {
-					to[symbols[i]] = from[symbols[i]];
-				}
-			}
-		}
-	}
-
-	return to;
+/***/ "Rp86":
+/***/ (function(module, exports, __webpack_require__) {
+
+__webpack_require__("bBy9");
+__webpack_require__("FlQf");
+module.exports = __webpack_require__("fXsU");
+
+
+/***/ }),
+
+/***/ "VKFn":
+/***/ (function(module, exports, __webpack_require__) {
+
+__webpack_require__("bBy9");
+__webpack_require__("FlQf");
+module.exports = __webpack_require__("ldVq");
+
+
+/***/ }),
+
+/***/ "XXOK":
+/***/ (function(module, exports, __webpack_require__) {
+
+module.exports = __webpack_require__("Rp86");
+
+/***/ }),
+
+/***/ "fXsU":
+/***/ (function(module, exports, __webpack_require__) {
+
+var anObject = __webpack_require__("5K7Z");
+var get = __webpack_require__("fNZA");
+module.exports = __webpack_require__("WEpk").getIterator = function (it) {
+  var iterFn = get(it);
+  if (typeof iterFn != 'function') throw TypeError(it + ' is not iterable!');
+  return anObject(iterFn.call(it));
 };
 
 
@@ -139,6 +171,37 @@ module.exports = shouldUseNative() ? Object.assign : function (target, source) {
     }]);
   
 
+/***/ }),
+
+/***/ "ldVq":
+/***/ (function(module, exports, __webpack_require__) {
+
+var classof = __webpack_require__("QMMT");
+var ITERATOR = __webpack_require__("UWiX")('iterator');
+var Iterators = __webpack_require__("SBuE");
+module.exports = __webpack_require__("WEpk").isIterable = function (it) {
+  var O = Object(it);
+  return O[ITERATOR] !== undefined
+    || '@@iterator' in O
+    // eslint-disable-next-line no-prototype-builtins
+    || Iterators.hasOwnProperty(classof(O));
+};
+
+
+/***/ }),
+
+/***/ "p0XB":
+/***/ (function(module, exports, __webpack_require__) {
+
+module.exports = __webpack_require__("9BDd");
+
+/***/ }),
+
+/***/ "yLu3":
+/***/ (function(module, exports, __webpack_require__) {
+
+module.exports = __webpack_require__("VKFn");
+
 /***/ })
 
-},[["g1vQ",0,1]]]);
\ No newline at end of file
+},[["g1vQ",0,2,1]]]);
\ No newline at end of file
Diff for index.module.js
@@ -1,13 +1,17 @@
-(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[8],{
+(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[9],{
 
 /***/ "RNiq":
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 
 "use strict";
 __webpack_require__.r(__webpack_exports__);
-var Page = () => 'Hello world 👋';
+var Page = function Page() {
+  return 'Hello world 👋';
+};
 
-Page.getInitialProps = () => ({});
+Page.getInitialProps = function () {
+  return {};
+};
 
 /* harmony default export */ __webpack_exports__["default"] = (Page);
Diff for link.module.js
@@ -1,4 +1,4 @@
-(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[9],{
+(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[10],{
 
 /***/ "/h46":
 /***/ (function(module, exports, __webpack_require__) {
@@ -51,7 +51,9 @@ function aLink(props) {
   }, "Go to /"));
 }
 
-aLink.getInitialProps = () => ({});
+aLink.getInitialProps = function () {
+  return {};
+};
 
 /* harmony default export */ __webpack_exports__["default"] = (aLink);
 
@@ -276,12 +278,22 @@ module.exports = __webpack_require__("cTJO")
 "use strict";
 
 
+var _classCallCheck = __webpack_require__("/HRN");
+
+var _createClass = __webpack_require__("WaGi");
+
+var _possibleConstructorReturn = __webpack_require__("ZDA2");
+
+var _getPrototypeOf = __webpack_require__("/+P4");
+
+var _inherits = __webpack_require__("N9n2");
+
 var _interopRequireWildcard = __webpack_require__("5Uuq");
 
 var _interopRequireDefault = __webpack_require__("KI45");
 
 exports.__esModule = true;
-exports.default = void 0;
+exports["default"] = void 0;
 
 var _map = _interopRequireDefault(__webpack_require__("LX0d"));
 
@@ -309,7 +321,7 @@ function memoizedFormatUrl(formatFunc) {
   var lastHref = null;
   var lastAs = null;
   var lastResult = null;
-  return (href, as) => {
+  return function (href, as) {
     if (lastResult && href === lastHref && as === lastAs) {
       return lastResult;
     }
@@ -327,7 +339,7 @@ function formatUrl(url) {
 }
 
 var observer;
-var listeners = new _map.default();
+var listeners = new _map["default"]();
 var IntersectionObserver = true ? window.IntersectionObserver : undefined;
 
 function getObserver() {
@@ -341,8 +353,8 @@ function getObserver() {
     return undefined;
   }
 
-  return observer = new IntersectionObserver(entries => {
-    entries.forEach(entry => {
+  return observer = new IntersectionObserver(function (entries) {
+    entries.forEach(function (entry) {
       if (!listeners.has(entry.target)) {
         return;
       }
@@ -351,7 +363,7 @@ function getObserver() {
 
       if (entry.isIntersecting || entry.intersectionRatio > 0) {
         observer.unobserve(entry.target);
-        listeners.delete(entry.target);
+        listeners["delete"](entry.target);
         cb();
       }
     });
@@ -360,81 +372,83 @@ function getObserver() {
   });
 }
 
-var listenToIntersections = (el, cb) => {
+var listenToIntersections = function listenToIntersections(el, cb) {
   var observer = getObserver();
 
   if (!observer) {
-    return () => {};
+    return function () {};
   }
 
   observer.observe(el);
   listeners.set(el, cb);
-  return () => {
+  return function () {
     try {
       observer.unobserve(el);
     } catch (err) {
       console.error(err);
     }
 
-    listeners.delete(el);
+    listeners["delete"](el);
   };
 };
 
-class Link extends _react.Component {
-  constructor(props) {
-    super(props);
-    this.p = void 0;
+var Link =
+/*#__PURE__*/
+function (_react$Component) {
+  _inherits(Link, _react$Component);
+
+  function Link(props) {
+    var _this;
+
+    _classCallCheck(this, Link);
+
+    _this = _possibleConstructorReturn(this, _getPrototypeOf(Link).call(this, props));
+    _this.p = void 0;
 
-    this.cleanUpListeners = () => {};
+    _this.cleanUpListeners = function () {};
 
-    this.formatUrls = memoizedFormatUrl((href, asHref) => {
+    _this.formatUrls = memoizedFormatUrl(function (href, asHref) {
       return {
         href: formatUrl(href),
         as: asHref ? formatUrl(asHref) : asHref
       };
     });
 
-    this.linkClicked = e => {
+    _this.linkClicked = function (e) {
       // @ts-ignore target exists on currentTarget
-      var {
-        nodeName,
-        target
-      } = e.currentTarget;
+      var _e$currentTarget = e.currentTarget,
+          nodeName = _e$currentTarget.nodeName,
+          target = _e$currentTarget.target;
 
       if (nodeName === 'A' && (target && target !== '_self' || e.metaKey || e.ctrlKey || e.shiftKey || e.nativeEvent && e.nativeEvent.which === 2)) {
         // ignore click for new tab / new window behavior
         return;
       }
 
-      var {
-        href,
-        as
-      } = this.formatUrls(this.props.href, this.props.as);
+      var _this$formatUrls = _this.formatUrls(_this.props.href, _this.props.as),
+          href = _this$formatUrls.href,
+          as = _this$formatUrls.as;
 
       if (!isLocal(href)) {
         // ignore click if it's outside our scope (e.g. https://google.com)
         return;
       }
 
-      var {
-        pathname
-      } = window.location;
+      var pathname = window.location.pathname;
       href = (0, _url.resolve)(pathname, href);
       as = as ? (0, _url.resolve)(pathname, as) : href;
       e.preventDefault(); //  avoid scroll for urls with anchor refs
 
-      var {
-        scroll
-      } = this.props;
+      var scroll = _this.props.scroll;
 
       if (scroll == null) {
         scroll = as.indexOf('#') < 0;
       } // replace state instead of push if prop is present
 
 
-      _router.default[this.props.replace ? 'replace' : 'push'](href, as, {
-        shallow: this.props.shallow
-      }).then(success => {
+      _router["default"][_this.props.replace ? 'replace' : 'push'](href, as, {
+        shallow: _this.props.shallow
+      }).then(function (success) {
         if (!success) return;
 
         if (scroll) {
@@ -446,102 +460,112 @@ class Link extends _react.Component {
 
     if (false) {}
 
-    this.p = props.prefetch !== false;
+    _this.p = props.prefetch !== false;
+    return _this;
   }
 
-  componentWillUnmount() {
-    this.cleanUpListeners();
-  }
-
-  handleRef(ref) {
-    if (this.p && IntersectionObserver && ref && ref.tagName) {
+  _createClass(Link, [{
+    key: "componentWillUnmount",
+    value: function componentWillUnmount() {
       this.cleanUpListeners();
-      this.cleanUpListeners = listenToIntersections(ref, () => {
-        this.prefetch();
-      });
     }
-  } // The function is memoized so that no extra lifecycles are needed
-  // as per https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
+  }, {
+    key: "handleRef",
+    value: function handleRef(ref) {
+      var _this2 = this;
+
+      if (this.p && IntersectionObserver && ref && ref.tagName) {
+        this.cleanUpListeners();
+        this.cleanUpListeners = listenToIntersections(ref, function () {
+          _this2.prefetch();
+        });
+      }
+    } // The function is memoized so that no extra lifecycles are needed
+    // as per https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
+
+  }, {
+    key: "prefetch",
+    value: function prefetch() {
+      if (!this.p || false) return; // Prefetch the JSON page if asked (only in the client)
 
+      var pathname = window.location.pathname;
 
-  prefetch() {
-    if (!this.p || false) return; // Prefetch the JSON page if asked (only in the client)
+      var _this$formatUrls2 = this.formatUrls(this.props.href, this.props.as),
+          parsedHref = _this$formatUrls2.href;
 
-    var {
-      pathname
-    } = window.location;
-    var {
-      href: parsedHref
-    } = this.formatUrls(this.props.href, this.props.as);
-    var href = (0, _url.resolve)(pathname, parsedHref);
+      var href = (0, _url.resolve)(pathname, parsedHref);
 
-    _router.default.prefetch(href);
-  }
+      _router["default"].prefetch(href);
+    }
+  }, {
+    key: "render",
+    value: function render() {
+      var _this3 = this;
+
+      var children = this.props.children;
 
-  render() {
-    var {
-      children
-    } = this.props;
-    var {
-      href,
-      as
-    } = this.formatUrls(this.props.href, this.props.as); // Deprecated. Warning shown by propType check. If the children provided is a string (<Link>example</Link>) we wrap it in an <a> tag
+      var _this$formatUrls3 = this.formatUrls(this.props.href, this.props.as),
+          href = _this$formatUrls3.href,
+          as = _this$formatUrls3.as; // Deprecated. Warning shown by propType check. If the children provided is a string (<Link>example</Link>) we wrap it in an <a> tag
 
-    if (typeof children === 'string') {
-      children = _react.default.createElement("a", null, children);
-    } // This will return the first child, if multiple are provided it will throw an error
 
+      if (typeof children === 'string') {
+        children = _react["default"].createElement("a", null, children);
+      } // This will return the first child, if multiple are provided it will throw an error
 
-    var child = _react.Children.only(children);
 
-    var props = {
-      ref: el => {
-        this.handleRef(el);
+      var child = _react.Children.only(children);
 
-        if (child && typeof child === 'object' && child.ref) {
-          if (typeof child.ref === 'function') child.ref(el);else if (typeof child.ref === 'object') {
-            child.ref.current = el;
+      var props = {
+        ref: function ref(el) {
+          _this3.handleRef(el);
+
+          if (child && typeof child === 'object' && child.ref) {
+            if (typeof child.ref === 'function') child.ref(el);else if (typeof child.ref === 'object') {
+              child.ref.current = el;
+            }
+          }
+        },
+        onMouseEnter: function onMouseEnter(e) {
+          if (child.props && typeof child.props.onMouseEnter === 'function') {
+            child.props.onMouseEnter(e);
           }
-        }
-      },
-      onMouseEnter: e => {
-        if (child.props && typeof child.props.onMouseEnter === 'function') {
-          child.props.onMouseEnter(e);
-        }
 
-        this.prefetch();
-      },
-      onClick: e => {
-        if (child.props && typeof child.props.onClick === 'function') {
-          child.props.onClick(e);
-        }
+          _this3.prefetch();
+        },
+        onClick: function onClick(e) {
+          if (child.props && typeof child.props.onClick === 'function') {
+            child.props.onClick(e);
+          }
 
-        if (!e.defaultPrevented) {
-          this.linkClicked(e);
+          if (!e.defaultPrevented) {
+            _this3.linkClicked(e);
+          }
         }
-      }
-    }; // If child is an <a> tag and doesn't have a href attribute, or if the 'passHref' property is
-    // defined, we specify the current 'href', so that repetition is not needed by the user
+      }; // If child is an <a> tag and doesn't have a href attribute, or if the 'passHref' property is
+      // defined, we specify the current 'href', so that repetition is not needed by the user
 
-    if (this.props.passHref || child.type === 'a' && !('href' in child.props)) {
-      props.href = as || href;
-    } // Add the ending slash to the paths. So, we can serve the
-    // "<page>/index.html" directly.
+      if (this.props.passHref || child.type === 'a' && !('href' in child.props)) {
+        props.href = as || href;
+      } // Add the ending slash to the paths. So, we can serve the
+      // "<page>/index.html" directly.
 
 
-    if (false) {}
+      if (false) {}
 
-    return _react.default.cloneElement(child, props);
-  }
+      return _react["default"].cloneElement(child, props);
+    }
+  }]);
 
-}
+  return Link;
+}(_react.Component);
 
 Link.propTypes = void 0;
 
 if (false) { var exact, warn; }
 
 var _default = Link;
-exports.default = _default;
+exports["default"] = _default;
 
 /***/ }),
 
@@ -581,4 +605,4 @@ module.exports = __webpack_require__("raTm")(MAP, function (get) {
 
 /***/ })
 
-},[["V8Sf",0,1,2,3,4]]]);
\ No newline at end of file
+},[["V8Sf",0,2,1,3,4,5]]]);
\ No newline at end of file
Diff for routerDirect.module.js
@@ -1,4 +1,4 @@
-(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[10],{
+(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[11],{
 
 /***/ "LtRI":
 /***/ (function(module, exports, __webpack_require__) {
@@ -32,10 +32,12 @@ function routerDirect(props) {
   return __jsx("div", null, "I import the router directly");
 }
 
-routerDirect.getInitialProps = () => ({});
+routerDirect.getInitialProps = function () {
+  return {};
+};
 
 /* harmony default export */ __webpack_exports__["default"] = (routerDirect);
 
 /***/ })
 
-},[["LtRI",0,1,2,3,4]]]);
\ No newline at end of file
+},[["LtRI",0,2,1,3,4,5]]]);
\ No newline at end of file
Diff for withRouter.module.js
@@ -1,4 +1,4 @@
-(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[11],{
+(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[12],{
 
 /***/ "0Hlz":
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
@@ -17,7 +17,9 @@ function useWithRouter(props) {
   return __jsx("div", null, "I use withRouter");
 }
 
-useWithRouter.getInitialProps = () => ({});
+useWithRouter.getInitialProps = function () {
+  return {};
+};
 
 /* harmony default export */ __webpack_exports__["default"] = (Object(next_router__WEBPACK_IMPORTED_MODULE_1__["withRouter"])(useWithRouter));
 
@@ -36,4 +38,4 @@ useWithRouter.getInitialProps = () => ({});
 
 /***/ })
 
-},[["eThv",0,1,2,3,4]]]);
\ No newline at end of file
+},[["eThv",0,2,1,3,4,5]]]);
\ No newline at end of file
Diff for _buildManifest.module.js
@@ -1 +1 @@
-self.__BUILD_MANIFEST = (function(a){return {"/link":[a],"/routerDirect":[a],"/withRouter":[a]}}("static\u002Fchunks\u002F16b1a72255206b7853bf6603dc58ec83de39b142.13a61a2410d3fe9a0cb1.module.js"));self.__BUILD_MANIFEST_CB && self.__BUILD_MANIFEST_CB()
\ No newline at end of file
+self.__BUILD_MANIFEST = (function(a){return {"/link":[a],"/routerDirect":[a],"/withRouter":[a]}}("static\u002Fchunks\u002F16b1a72255206b7853bf6603dc58ec83de39b142.a9e45275d81f65ce1b3a.module.js"));self.__BUILD_MANIFEST_CB && self.__BUILD_MANIFEST_CB()
\ No newline at end of file
Diff for index.html
@@ -12,13 +12,15 @@
         as="script" crossorigin="anonymous" />
         <link rel="preload" href="/_next/static/runtime/webpack-7928590be3ef2e55b835.module.js"
         as="script" crossorigin="anonymous" />
-        <link rel="preload" href="/_next/static/runtime/main-f0273520bbdb916796e0.module.js"
+        <link rel="preload" href="/_next/static/runtime/main-44f5b3a294fbc49824cf.module.js"
         as="script" crossorigin="anonymous" />
-        <link rel="preload" href="/_next/static/chunks/framework.cdb73e402d876d4ac87f.module.js"
+        <link rel="preload" href="/_next/static/chunks/framework.219514909c9db8a9ff76.module.js"
         as="script" crossorigin="anonymous" />
-        <link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.89ebf3e33b855a0478ce.module.js"
+        <link rel="preload" href="/_next/static/chunks/commons.ae25279399a9d28ee270.module.js"
         as="script" crossorigin="anonymous" />
-        <link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.dda3a797bb804537ed85.module.js"
+        <link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.cf0e4a968d6e5bfa6e29.module.js"
+        as="script" crossorigin="anonymous" />
+        <link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.aa9b9639e60cb81cd54f.module.js"
         as="script" crossorigin="anonymous" />
     </head>
     
@@ -46,21 +48,23 @@
         async="" crossorigin="anonymous" type="module"></script>
         <script src="/_next/static/runtime/main-44f5b3a294fbc49824cf.js"
         async="" crossorigin="anonymous" nomodule=""></script>
-        <script src="/_next/static/runtime/main-f0273520bbdb916796e0.module.js"
+        <script src="/_next/static/runtime/main-44f5b3a294fbc49824cf.module.js"
         async="" crossorigin="anonymous" type="module"></script>
         <script src="/_next/static/chunks/framework.219514909c9db8a9ff76.js"
         async="" crossorigin="anonymous" nomodule=""></script>
-        <script src="/_next/static/chunks/framework.cdb73e402d876d4ac87f.module.js"
+        <script src="/_next/static/chunks/framework.219514909c9db8a9ff76.module.js"
         async="" crossorigin="anonymous" type="module"></script>
         <script src="/_next/static/chunks/commons.ae25279399a9d28ee270.js"
         async="" crossorigin="anonymous" nomodule=""></script>
+        <script src="/_next/static/chunks/commons.ae25279399a9d28ee270.module.js"
+        async="" crossorigin="anonymous" type="module"></script>
         <script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.cf0e4a968d6e5bfa6e29.js"
         async="" crossorigin="anonymous" nomodule=""></script>
-        <script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.89ebf3e33b855a0478ce.module.js"
+        <script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.cf0e4a968d6e5bfa6e29.module.js"
         async="" crossorigin="anonymous" type="module"></script>
         <script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.aa9b9639e60cb81cd54f.js"
         async="" crossorigin="anonymous" nomodule=""></script>
-        <script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.dda3a797bb804537ed85.module.js"
+        <script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.aa9b9639e60cb81cd54f.module.js"
         async="" crossorigin="anonymous" type="module"></script>
         <script src="/_next/static/BUILD_ID/_buildManifest.js" async=""
         crossorigin="anonymous" nomodule=""></script>
Diff for link.html
@@ -12,15 +12,17 @@
         as="script" crossorigin="anonymous" />
         <link rel="preload" href="/_next/static/runtime/webpack-7928590be3ef2e55b835.module.js"
         as="script" crossorigin="anonymous" />
-        <link rel="preload" href="/_next/static/chunks/framework.cdb73e402d876d4ac87f.module.js"
+        <link rel="preload" href="/_next/static/chunks/framework.219514909c9db8a9ff76.module.js"
         as="script" crossorigin="anonymous" />
-        <link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.89ebf3e33b855a0478ce.module.js"
+        <link rel="preload" href="/_next/static/chunks/commons.ae25279399a9d28ee270.module.js"
         as="script" crossorigin="anonymous" />
-        <link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.dda3a797bb804537ed85.module.js"
+        <link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.cf0e4a968d6e5bfa6e29.module.js"
         as="script" crossorigin="anonymous" />
-        <link rel="preload" href="/_next/static/chunks/16b1a72255206b7853bf6603dc58ec83de39b142.13a61a2410d3fe9a0cb1.module.js"
+        <link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.aa9b9639e60cb81cd54f.module.js"
         as="script" crossorigin="anonymous" />
-        <link rel="preload" href="/_next/static/runtime/main-f0273520bbdb916796e0.module.js"
+        <link rel="preload" href="/_next/static/chunks/16b1a72255206b7853bf6603dc58ec83de39b142.a9e45275d81f65ce1b3a.module.js"
+        as="script" crossorigin="anonymous" />
+        <link rel="preload" href="/_next/static/runtime/main-44f5b3a294fbc49824cf.module.js"
         as="script" crossorigin="anonymous" />
     </head>
     
@@ -51,25 +53,27 @@
         async="" crossorigin="anonymous" type="module"></script>
         <script src="/_next/static/chunks/framework.219514909c9db8a9ff76.js"
         async="" crossorigin="anonymous" nomodule=""></script>
-        <script src="/_next/static/chunks/framework.cdb73e402d876d4ac87f.module.js"
+        <script src="/_next/static/chunks/framework.219514909c9db8a9ff76.module.js"
         async="" crossorigin="anonymous" type="module"></script>
         <script src="/_next/static/chunks/commons.ae25279399a9d28ee270.js"
         async="" crossorigin="anonymous" nomodule=""></script>
+        <script src="/_next/static/chunks/commons.ae25279399a9d28ee270.module.js"
+        async="" crossorigin="anonymous" type="module"></script>
         <script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.cf0e4a968d6e5bfa6e29.js"
         async="" crossorigin="anonymous" nomodule=""></script>
-        <script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.89ebf3e33b855a0478ce.module.js"
+        <script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.cf0e4a968d6e5bfa6e29.module.js"
         async="" crossorigin="anonymous" type="module"></script>
         <script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.aa9b9639e60cb81cd54f.js"
         async="" crossorigin="anonymous" nomodule=""></script>
-        <script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.dda3a797bb804537ed85.module.js"
+        <script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.aa9b9639e60cb81cd54f.module.js"
         async="" crossorigin="anonymous" type="module"></script>
         <script src="/_next/static/chunks/16b1a72255206b7853bf6603dc58ec83de39b142.a9e45275d81f65ce1b3a.js"
         async="" crossorigin="anonymous" nomodule=""></script>
-        <script src="/_next/static/chunks/16b1a72255206b7853bf6603dc58ec83de39b142.13a61a2410d3fe9a0cb1.module.js"
+        <script src="/_next/static/chunks/16b1a72255206b7853bf6603dc58ec83de39b142.a9e45275d81f65ce1b3a.module.js"
         async="" crossorigin="anonymous" type="module"></script>
         <script src="/_next/static/runtime/main-44f5b3a294fbc49824cf.js"
         async="" crossorigin="anonymous" nomodule=""></script>
-        <script src="/_next/static/runtime/main-f0273520bbdb916796e0.module.js"
+        <script src="/_next/static/runtime/main-44f5b3a294fbc49824cf.module.js"
         async="" crossorigin="anonymous" type="module"></script>
         <script src="/_next/static/BUILD_ID/_buildManifest.js" async=""
         crossorigin="anonymous" nomodule=""></script>
Diff for withRouter.html
@@ -12,15 +12,17 @@
         as="script" crossorigin="anonymous" />
         <link rel="preload" href="/_next/static/runtime/webpack-7928590be3ef2e55b835.module.js"
         as="script" crossorigin="anonymous" />
-        <link rel="preload" href="/_next/static/chunks/framework.cdb73e402d876d4ac87f.module.js"
+        <link rel="preload" href="/_next/static/chunks/framework.219514909c9db8a9ff76.module.js"
         as="script" crossorigin="anonymous" />
-        <link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.89ebf3e33b855a0478ce.module.js"
+        <link rel="preload" href="/_next/static/chunks/commons.ae25279399a9d28ee270.module.js"
         as="script" crossorigin="anonymous" />
-        <link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.dda3a797bb804537ed85.module.js"
+        <link rel="preload" href="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.cf0e4a968d6e5bfa6e29.module.js"
         as="script" crossorigin="anonymous" />
-        <link rel="preload" href="/_next/static/chunks/16b1a72255206b7853bf6603dc58ec83de39b142.13a61a2410d3fe9a0cb1.module.js"
+        <link rel="preload" href="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.aa9b9639e60cb81cd54f.module.js"
         as="script" crossorigin="anonymous" />
-        <link rel="preload" href="/_next/static/runtime/main-f0273520bbdb916796e0.module.js"
+        <link rel="preload" href="/_next/static/chunks/16b1a72255206b7853bf6603dc58ec83de39b142.a9e45275d81f65ce1b3a.module.js"
+        as="script" crossorigin="anonymous" />
+        <link rel="preload" href="/_next/static/runtime/main-44f5b3a294fbc49824cf.module.js"
         as="script" crossorigin="anonymous" />
     </head>
     
@@ -49,25 +51,27 @@
         async="" crossorigin="anonymous" type="module"></script>
         <script src="/_next/static/chunks/framework.219514909c9db8a9ff76.js"
         async="" crossorigin="anonymous" nomodule=""></script>
-        <script src="/_next/static/chunks/framework.cdb73e402d876d4ac87f.module.js"
+        <script src="/_next/static/chunks/framework.219514909c9db8a9ff76.module.js"
         async="" crossorigin="anonymous" type="module"></script>
         <script src="/_next/static/chunks/commons.ae25279399a9d28ee270.js"
         async="" crossorigin="anonymous" nomodule=""></script>
+        <script src="/_next/static/chunks/commons.ae25279399a9d28ee270.module.js"
+        async="" crossorigin="anonymous" type="module"></script>
         <script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.cf0e4a968d6e5bfa6e29.js"
         async="" crossorigin="anonymous" nomodule=""></script>
-        <script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.89ebf3e33b855a0478ce.module.js"
+        <script src="/_next/static/chunks/4952ddcd88e7185e66c9cf40e2d848b7e27f1574.cf0e4a968d6e5bfa6e29.module.js"
         async="" crossorigin="anonymous" type="module"></script>
         <script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.aa9b9639e60cb81cd54f.js"
         async="" crossorigin="anonymous" nomodule=""></script>
-        <script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.dda3a797bb804537ed85.module.js"
+        <script src="/_next/static/chunks/de003c3a9d308750aa009870a5926f9b18ab31f4.aa9b9639e60cb81cd54f.module.js"
         async="" crossorigin="anonymous" type="module"></script>
         <script src="/_next/static/chunks/16b1a72255206b7853bf6603dc58ec83de39b142.a9e45275d81f65ce1b3a.js"
         async="" crossorigin="anonymous" nomodule=""></script>
-        <script src="/_next/static/chunks/16b1a72255206b7853bf6603dc58ec83de39b142.13a61a2410d3fe9a0cb1.module.js"
+        <script src="/_next/static/chunks/16b1a72255206b7853bf6603dc58ec83de39b142.a9e45275d81f65ce1b3a.module.js"
         async="" crossorigin="anonymous" type="module"></script>
         <script src="/_next/static/runtime/main-44f5b3a294fbc49824cf.js"
         async="" crossorigin="anonymous" nomodule=""></script>
-        <script src="/_next/static/runtime/main-f0273520bbdb916796e0.module.js"
+        <script src="/_next/static/runtime/main-44f5b3a294fbc49824cf.module.js"
         async="" crossorigin="anonymous" type="module"></script>
         <script src="/_next/static/BUILD_ID/_buildManifest.js" async=""
         crossorigin="anonymous" nomodule=""></script>

Serverless Mode (Increase detected ⚠️)
General Overall increase ⚠️
zeit/next.js canary developit/next.js babel-threadpool Change
buildDuration 14.6s 12.2s -2.4s
nodeModulesSize 49 MB 49.2 MB ⚠️ +239 kB
Client Bundles (main, webpack, commons)
zeit/next.js canary developit/next.js babel-threadpool Change
main-HASH.js 16.6 kB 16.6 kB
main-HASH.js gzip 5.89 kB 5.89 kB
webpack-HASH.js 1.53 kB 1.53 kB
webpack-HASH.js gzip 746 B 746 B
16b1a7225520..7459734ec.js 20.1 kB 20.1 kB
16b1a7225520..34ec.js gzip 7.38 kB 7.38 kB
4952ddcd88e7..bfe360fe6.js 10.5 kB 10.5 kB
4952ddcd88e7..0fe6.js gzip 4.06 kB 4.06 kB
commons.HASH.js 11.3 kB 11.3 kB
commons.HASH.js gzip 4.23 kB 4.23 kB
de003c3a9d30..254ddadd9.js 28.7 kB 28.7 kB
de003c3a9d30..add9.js gzip 10.9 kB 10.9 kB
framework.HASH.js 125 kB 125 kB
framework.HASH.js gzip 39.4 kB 39.4 kB
Overall change 214 kB 214 kB
Client Bundles (main, webpack, commons) Modern Overall increase ⚠️
zeit/next.js canary developit/next.js babel-threadpool Change
main-HASH.module.js 14.1 kB 16.6 kB ⚠️ +2.52 kB
main-HASH.module.js gzip 5.31 kB 5.89 kB ⚠️ +580 B
webpack-HASH.module.js 1.53 kB 1.53 kB
webpack-HASH..dule.js gzip 746 B 746 B
16b1a7225520..0d.module.js 16.2 kB N/A N/A
16b1a7225520..dule.js gzip 6.22 kB N/A N/A
4952ddcd88e7..4a.module.js 12.8 kB N/A N/A
4952ddcd88e7..dule.js gzip 4.75 kB N/A N/A
de003c3a9d30..36.module.js 22.2 kB N/A N/A
de003c3a9d30..dule.js gzip 8.71 kB N/A N/A
framework.HASH.module.js 125 kB 125 kB
framework.HA..dule.js gzip 39.4 kB 39.4 kB
16b1a7225520..ec.module.js N/A 20.1 kB N/A
16b1a7225520..dule.js gzip N/A 7.38 kB N/A
4952ddcd88e7..e6.module.js N/A 10.5 kB N/A
4952ddcd88e7..dule.js gzip N/A 4.06 kB N/A
commons.HASH.module.js N/A 11.3 kB N/A
commons.HASH..dule.js gzip N/A 4.23 kB N/A
de003c3a9d30..d9.module.js N/A 28.7 kB N/A
de003c3a9d30..dule.js gzip N/A 10.9 kB N/A
Overall change 192 kB 214 kB ⚠️ +2.52 kB
Legacy Client Bundles (polyfills)
zeit/next.js canary developit/next.js babel-threadpool Change
polyfills-HASH.js 8.14 kB 8.14 kB
polyfills-HASH.js gzip 2.76 kB 2.76 kB
Overall change 8.14 kB 8.14 kB
Client Pages
zeit/next.js canary developit/next.js babel-threadpool Change
_app.js 1.63 kB 1.63 kB
_app.js gzip 788 B 788 B
_error.js 12.3 kB 12.3 kB
_error.js gzip 4.79 kB 4.79 kB
hooks.js 1.92 kB 1.92 kB
hooks.js gzip 941 B 941 B
index.js 318 B 318 B
index.js gzip 222 B 222 B
link.js 5.81 kB 5.81 kB
link.js gzip 2.56 kB 2.56 kB
routerDirect.js 413 B 413 B
routerDirect.js gzip 285 B 285 B
withRouter.js 423 B 423 B
withRouter.js gzip 284 B 284 B
Overall change 22.8 kB 22.8 kB
Client Pages Modern Overall increase ⚠️
zeit/next.js canary developit/next.js babel-threadpool Change
_app.module.js 1.54 kB 1.63 kB ⚠️ +85 B
_app.module.js gzip 759 B 788 B ⚠️ +29 B
_error.module.js 10.5 kB 12.3 kB ⚠️ +1.75 kB
_error.module.js gzip 4.26 kB 4.79 kB ⚠️ +526 B
hooks.module.js 1.52 kB 1.92 kB ⚠️ +395 B
hooks.module.js gzip 792 B 941 B ⚠️ +149 B
index.module.js 292 B 318 B ⚠️ +26 B
index.module.js gzip 223 B 222 B -1 B
link.module.js 5.49 kB 5.81 kB ⚠️ +318 B
link.module.js gzip 2.47 kB 2.56 kB ⚠️ +99 B
routerDirect.module.js 399 B 413 B ⚠️ +14 B
routerDirect..dule.js gzip 285 B 285 B
withRouter.module.js 409 B 423 B ⚠️ +14 B
withRouter.m..dule.js gzip 282 B 284 B ⚠️ +2 B
Overall change 20.2 kB 22.8 kB ⚠️ +2.6 kB
Client Build Manifests
zeit/next.js canary developit/next.js babel-threadpool Change
_buildManifest.js 244 B 244 B
_buildManifest.js gzip 201 B 201 B
_buildManifest.module.js 251 B 251 B
_buildManife..dule.js gzip 209 B 206 B -3 B
Overall change 495 B 495 B
Serverless bundles Overall increase ⚠️
zeit/next.js canary developit/next.js babel-threadpool Change
_error.js 248 kB 248 kB ⚠️ +342 B
_error.js gzip 65.6 kB 65.5 kB -93 B
hooks.html 4.19 kB 4.45 kB ⚠️ +254 B
hooks.html gzip 1.07 kB 1.02 kB -44 B
index.js 248 kB 248 kB ⚠️ +342 B
index.js gzip 65.8 kB 65.7 kB -90 B
link.js 280 kB 281 kB ⚠️ +342 B
link.js gzip 74.7 kB 74.6 kB -86 B
routerDirect.js 273 kB 274 kB ⚠️ +342 B
routerDirect.js gzip 72.8 kB 72.7 kB -88 B
withRouter.js 273 kB 274 kB ⚠️ +342 B
withRouter.js gzip 72.9 kB 72.8 kB -97 B
Overall change 1.33 MB 1.33 MB ⚠️ +1.96 kB

Commit: 7c0892f

@developit developit requested a review from Timer November 7, 2019 03:11
@timneutkens
Copy link
Member

Decide on whether this should be enabled based on flags

I think we can enable it by default

Decide which caching implementation to use

babel-loader's caching also doesn't clear itself up right?


I'd like to merge this PR if possible 👍

@timneutkens timneutkens changed the title Move Babel transpile into a cached thread pool [Experimental] Move Babel transpile into a cached thread pool Dec 24, 2019
@timneutkens timneutkens marked this pull request as ready for review December 24, 2019 15:54
…-threadpool

# Conflicts:
#	packages/next/package.json
@timneutkens timneutkens merged commit 93c745c into vercel:canary Dec 24, 2019
@schmod
Copy link

schmod commented Jan 6, 2020

The build stats are making this look like we might have broken the modern build (or regressed so that the modern build is now the same as the non-modern one)?

@Timer
Copy link
Member

Timer commented Jan 6, 2020

@schmod note those stats are likely incorrect, and this option is not enabled by default (it's flagged behind babelMultiThread).

@vercel vercel locked as resolved and limited conversation to collaborators Jan 31, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants