-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Replace <link rel=stylesheet> client-side transitions with <style> tags #16581
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
Conversation
Failing test suitesCommit: f40d80d test/integration/css-client-nav/test/index.test.js
Expand output● CSS Module client-side navigation in Production › should be able to client-side navigate from blue to red test/integration/css/test/index.test.js
Expand output● CSS Support › CSS Modules Composes Ordering › Production Mode › should have correct CSS injection order ● CSS Support › CSS Modules Composes Ordering › Production Mode › should have correct color on index page (on nav from other) |
Stats from current PRDefault Server Mode (Increase detected
|
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| buildDuration | 12.2s | 12s | -237ms |
| nodeModulesSize | 57.5 MB | 57.5 MB | -3.18 kB |
Page Load Tests Overall increase ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| / failed reqs | 0 | 0 | ✓ |
| / total time (seconds) | 2.185 | 2.138 | -0.05 |
| / avg req/sec | 1144.28 | 1169.49 | +25.21 |
| /error-in-render failed reqs | 0 | 0 | ✓ |
| /error-in-render total time (seconds) | 1.192 | 1.177 | -0.01 |
| /error-in-render avg req/sec | 2098.07 | 2123.59 | +25.52 |
Client Bundles (main, webpack, commons) Overall decrease ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| 677f882d2ed8..7f47.js gzip | 10.3 kB | 10.3 kB | ✓ |
| framework.HASH.js gzip | 39 kB | 39 kB | ✓ |
| main-d4bab31..824e.js gzip | 7.34 kB | 7.32 kB | -20 B |
| webpack-e067..f178.js gzip | 751 B | 751 B | ✓ |
| Overall change | 57.4 kB | 57.3 kB | -20 B |
Client Bundles (main, webpack, commons) Modern Overall decrease ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| 677f882d2ed8..dule.js gzip | 6.15 kB | 6.15 kB | ✓ |
| framework.HA..dule.js gzip | 39 kB | 39 kB | ✓ |
| main-438d30a..dule.js gzip | 6.39 kB | 6.39 kB | -4 B |
| webpack-07c5..dule.js gzip | 751 B | 751 B | ✓ |
| Overall change | 52.3 kB | 52.3 kB | -4 B |
Legacy Client Bundles (polyfills)
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| polyfills-4b..e242.js gzip | 31 kB | 31 kB | ✓ |
| Overall change | 31 kB | 31 kB | ✓ |
Client Pages
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _app-9a0b9e1..b37e.js gzip | 1.28 kB | 1.28 kB | ✓ |
| _error-28298..e0c9.js gzip | 3.44 kB | 3.44 kB | ✓ |
| hooks-89731c..c609.js gzip | 887 B | 887 B | ✓ |
| index-17468f..5d83.js gzip | 227 B | 227 B | ✓ |
| link-000f151..65d4.js gzip | 1.29 kB | 1.29 kB | ✓ |
| routerDirect..924c.js gzip | 284 B | 284 B | ✓ |
| withRouter-7..c13d.js gzip | 284 B | 284 B | ✓ |
| Overall change | 7.69 kB | 7.69 kB | ✓ |
Client Pages Modern
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _app-75d3a82..dule.js gzip | 625 B | 625 B | ✓ |
| _error-65c8a..dule.js gzip | 2.29 kB | 2.29 kB | ✓ |
| hooks-cbf13f..dule.js gzip | 387 B | 387 B | ✓ |
| index-b9a643..dule.js gzip | 226 B | 226 B | ✓ |
| link-4cfda7a..dule.js gzip | 1.26 kB | 1.26 kB | ✓ |
| routerDirect..dule.js gzip | 284 B | 284 B | ✓ |
| withRouter-f..dule.js gzip | 282 B | 282 B | ✓ |
| Overall change | 5.35 kB | 5.35 kB | ✓ |
Client Build Manifests
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _buildManifest.js gzip | 322 B | 322 B | ✓ |
| _buildManife..dule.js gzip | 330 B | 330 B | ✓ |
| Overall change | 652 B | 652 B | ✓ |
Rendered Page Sizes Overall increase ⚠️
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| index.html gzip | 948 B | 970 B | |
| link.html gzip | 954 B | 977 B | |
| withRouter.html gzip | 940 B | 963 B | |
| Overall change | 2.84 kB | 2.91 kB |
Diffs
Diff for main-209a935..118ae6828.js
@@ -275,7 +275,7 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var _headManager = _interopRequireDefault(__webpack_require__("DqTX"));
- var _pageLoader = _interopRequireWildcard3(__webpack_require__("zmvN"));
+ var _pageLoader = _interopRequireDefault(__webpack_require__("zmvN"));
var _performanceRelayer = _interopRequireDefault(
__webpack_require__("bGXG")
@@ -319,14 +319,31 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
asPath = (0, _router.delBasePath)(asPath);
}
+ var looseToArray = function looseToArray(input) {
+ return [].slice.call(input);
+ };
+
var pageLoader = new _pageLoader["default"](
buildId,
prefix,
page,
- [].slice
- .call(document.querySelectorAll("link[rel=stylesheet][data-n-p]"))
- .map(function(e) {
- return e.getAttribute("href");
+ looseToArray(document.styleSheets)
+ .filter(function(el) {
+ return (
+ el.ownerNode &&
+ el.ownerNode.tagName === "LINK" &&
+ el.ownerNode.hasAttribute("data-n-p")
+ );
+ })
+ .map(function(sheet) {
+ return {
+ href: sheet.ownerNode.getAttribute("href"),
+ text: looseToArray(sheet.cssRules)
+ .map(function(r) {
+ return r.cssText;
+ })
+ .join("")
+ };
})
);
@@ -967,8 +984,8 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
); // lastAppProps has to be set before ReactDom.render to account for ReactDom throwing an error.
lastAppProps = appProps;
+ var canceled = false;
var resolvePromise;
- var renderPromiseReject;
var renderPromise = new Promise(function(resolve, reject) {
if (_lastRenderReject) {
_lastRenderReject();
@@ -979,17 +996,15 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
resolve();
};
- renderPromiseReject = _lastRenderReject = function lastRenderReject() {
+ _lastRenderReject = function lastRenderReject() {
+ canceled = true;
_lastRenderReject = null;
var error = new Error("Cancel rendering route");
error.cancelled = true;
reject(error);
};
- }); // TODO: consider replacing this with real `<style>` tags that have
- // plain-text CSS content that's provided by RouteInfo. That'd remove the
- // need for the staging `<link>`s and the ability for CSS to be missing at
- // this phase, allowing us to remove the error handling flow that reloads the
- // page.
+ }); // This function has a return type to ensure it doesn't start returning a
+ // Promise. It should remain synchronous.
function onStart() {
if (
@@ -999,82 +1014,30 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
// unless we're in production:
false
) {
- return Promise.resolve([]);
- } // Clean up previous render if canceling:
+ return false;
+ }
- [].slice
- .call(
- document.querySelectorAll(
- "link[data-n-staging], noscript[data-n-staging]"
- )
- )
- .forEach(function(el) {
- el.parentNode.removeChild(el);
- });
- var referenceNodes = [].slice.call(
- document.querySelectorAll("link[data-n-g], link[data-n-p]")
+ var currentStyleTags = looseToArray(
+ document.querySelectorAll("style[data-n-href]")
);
- var referenceHrefs = new Set(
- referenceNodes.map(function(e) {
- return e.getAttribute("href");
+ var currentHrefs = new Set(
+ currentStyleTags.map(function(tag) {
+ return tag.getAttribute("data-n-href");
})
);
- var referenceNode = referenceNodes[referenceNodes.length - 1];
- var required = styleSheets.map(function(href) {
- var newNode, promise;
- var existingLink = referenceHrefs.has(href);
-
- if (existingLink) {
- newNode = document.createElement("noscript");
- newNode.setAttribute("data-n-staging", href);
- promise = true;
- } else {
- var _ref9 = (0, _pageLoader.createLink)(href, "stylesheet"),
- _ref10 = _slicedToArray(_ref9, 2),
- link = _ref10[0],
- onload = _ref10[1];
-
- link.setAttribute("data-n-staging", ""); // Media `none` does not work in Firefox, so `print` is more
- // cross-browser. Since this is so short lived we don't have to worry
- // about style thrashing in a print view (where no routing is going to be
- // happening anyway).
-
- link.setAttribute("media", "print");
- newNode = link;
- promise = onload;
- }
-
- if (referenceNode) {
- referenceNode.parentNode.insertBefore(
- newNode,
- referenceNode.nextSibling
- );
- referenceNode = newNode;
- } else {
- document.head.appendChild(newNode);
+ styleSheets.forEach(function(_ref9) {
+ var href = _ref9.href,
+ text = _ref9.text;
+
+ if (!currentHrefs.has(href)) {
+ var styleTag = document.createElement("style");
+ styleTag.setAttribute("data-n-href", href);
+ styleTag.setAttribute("media", "x");
+ document.head.appendChild(styleTag);
+ styleTag.appendChild(document.createTextNode(text));
}
-
- return promise;
- });
- return Promise.all(required)["catch"](function() {
- // This is too late in the rendering lifecycle to use the existing
- // `PAGE_LOAD_ERROR` flow (via `handleRouteInfoError`).
- // To match that behavior, we request the page to reload with the current
- // asPath. This is already set at this phase since we "committed" to the
- // render.
- // This handles an edge case where a new deployment is rolled during
- // client-side transition and the CSS assets are missing.
- // This prevents:
- // 1. An unstyled page from being rendered (old behavior)
- // 2. The `/_error` page being rendered (we want to reload for the new
- // deployment)
- window.location.href = router.asPath; // Instead of rethrowing the CSS loading error, we give a promise that
- // won't resolve. This pauses the rendering process until the page
- // reloads. Re-throwing the error could result in a flash of error page.
- // throw cssLoadingError
-
- return new Promise(function() {});
});
+ return true;
}
function onCommit() {
@@ -1083,45 +1046,60 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
// unless we're in production:
true && // We can skip this during hydration. Running it wont cause any harm, but
// we may as well save the CPU cycles:
- !isInitialRender && // Ensure this render commit owns the currently staged stylesheets:
- renderPromiseReject === _lastRenderReject
+ !isInitialRender && // Ensure this render was not canceled
+ !canceled
) {
- // Remove or relocate old stylesheets:
- var relocatePlaceholders = [].slice.call(
- document.querySelectorAll("noscript[data-n-staging]")
+ var desiredHrefs = new Set(
+ styleSheets.map(function(s) {
+ return s.href;
+ })
);
- var relocateHrefs = relocatePlaceholders.map(function(e) {
- return e.getAttribute("data-n-staging");
- });
- [].slice
- .call(document.querySelectorAll("link[data-n-p]"))
- .forEach(function(el) {
- var currentHref = el.getAttribute("href");
- var relocateIndex = relocateHrefs.indexOf(currentHref);
-
- if (relocateIndex !== -1) {
- var _placeholderElement$p;
-
- var placeholderElement = relocatePlaceholders[relocateIndex];
- (_placeholderElement$p = placeholderElement.parentNode) ==
- null
- ? void 0
- : _placeholderElement$p.replaceChild(
- el,
- placeholderElement
- );
- } else {
- el.parentNode.removeChild(el);
+ var currentStyleTags = looseToArray(
+ document.querySelectorAll("style[data-n-href]")
+ );
+ var currentHrefs = currentStyleTags.map(function(tag) {
+ return tag.getAttribute("data-n-href");
+ }); // Toggle `<style>` tags on or off depending on if they're needed:
+
+ for (var idx = 0; idx < currentHrefs.length; ++idx) {
+ if (desiredHrefs.has(currentHrefs[idx])) {
+ currentStyleTags[idx].removeAttribute("media");
+ } else {
+ currentStyleTags[idx].setAttribute("media", "x");
+ }
+ } // Reorder styles into intended order:
+
+ var referenceNode = document.querySelector("noscript[data-n-css]");
+
+ if (
+ // This should be an invariant:
+ referenceNode
+ ) {
+ styleSheets.forEach(function(_ref10) {
+ var href = _ref10.href;
+ var targetTag = document.querySelector(
+ 'style[data-n-href="'.concat(href, '"]')
+ );
+
+ if (
+ // This should be an invariant:
+ targetTag
+ ) {
+ referenceNode.parentNode.insertBefore(
+ targetTag,
+ referenceNode.nextSibling
+ );
+ referenceNode = targetTag;
}
- }); // Activate new stylesheets:
- [].slice
- .call(document.querySelectorAll("link[data-n-staging]"))
- .forEach(function(el) {
- el.removeAttribute("data-n-staging");
- el.removeAttribute("media");
- el.setAttribute("data-n-p", "");
- }); // Force browser to recompute layout, which prevents a flash of unstyled
- // content:
+ });
+ } // Finally, clean up server rendered stylesheets:
+
+ looseToArray(document.querySelectorAll("link[data-n-p]")).forEach(
+ function(el) {
+ el.parentNode.removeChild(el);
+ }
+ ); // Force browser to recompute layout, which should prevent a flash of
+ // unstyled content:
getComputedStyle(document.body, "height");
}
@@ -1139,29 +1117,12 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
null,
/*#__PURE__*/ _react["default"].createElement(App, appProps)
)
- ); // We catch runtime errors using componentDidCatch which will trigger renderError
-
- return Promise.race([
- // Download required CSS assets first:
- onStart()
- .then(function() {
- // Ensure a new render has not been started:
- if (renderPromiseReject === _lastRenderReject) {
- // Queue rendering:
- renderReactElement(
- false ? /*#__PURE__*/ undefined : elem,
- appElement
- );
- }
- })
- .then(function() {
- return (
- // Wait for rendering to complete:
- renderPromise
- );
- }), // Bail early on route cancelation (rejection):
- renderPromise
- ]);
+ );
+
+ onStart(); // We catch runtime errors using componentDidCatch which will trigger renderError
+
+ renderReactElement(false ? /*#__PURE__*/ undefined : elem, appElement);
+ return renderPromise;
}
function Root(_ref11) {
@@ -1617,12 +1578,9 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var _createClass = __webpack_require__("W8MJ");
- var _slicedToArray = __webpack_require__("J4zp");
-
var _interopRequireDefault = __webpack_require__("TqRt");
exports.__esModule = true;
- exports.createLink = createLink;
exports["default"] = void 0;
var _mitt = _interopRequireDefault(__webpack_require__("dZ6Y"));
@@ -1667,6 +1625,7 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
: // IE 11, Edge 12+, nearly all evergreen
"prefetch";
var relPreload = hasRel("preload") ? "preload" : relPrefetch;
+ var relPreloadStyle = "fetch";
var hasNoModule = "noModule" in document.createElement("script");
var requestIdleCallback =
@@ -1686,31 +1645,19 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
return route.replace(/\/$/, "");
}
- function createLink(href, rel, as, link) {
- link = document.createElement("link");
- return [
- link,
- new Promise(function(res, rej) {
- // The order of property assignment here is intentional:
- if (as) link.as = as;
- link.rel = rel;
- link.crossOrigin = "anonymous";
- link.onload = res;
- link.onerror = rej; // `href` should always be last:
-
- link.href = href;
- })
- ];
- }
+ function appendLink(href, rel, as, link) {
+ return new Promise(function(res, rej) {
+ link = document.createElement("link"); // The order of property assignment here is intentional:
- function appendLink(href, rel, as) {
- var _createLink = createLink(href, rel, as),
- _createLink2 = _slicedToArray(_createLink, 2),
- link = _createLink2[0],
- res = _createLink2[1];
+ if (as) link.as = as;
+ link.rel = rel;
+ link.crossOrigin = "anonymous";
+ link.onload = res;
+ link.onerror = rej; // `href` should always be last:
- document.head.appendChild(link);
- return res;
+ link.href = href;
+ document.head.appendChild(link);
+ });
}
function loadScript(url) {
@@ -2007,7 +1954,7 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
// wait for these to resolve. To prevent an unhandled
// rejection, we swallow the error which is handled later in
// the rendering cycle (this is just a preload optimization).
- appendLink(d, relPreload, "style")["catch"](
+ appendLink(d, relPreload, relPreloadStyle)["catch"](
function() {
/* ignore preload error */
}
@@ -2064,20 +2011,44 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var check;
}
+ function fetchStyleSheet(href) {
+ return fetch(href).then(function(res) {
+ if (!res.ok) throw pageLoadError(href);
+ return res.text().then(function(text) {
+ return {
+ href: href,
+ text: text
+ };
+ });
+ });
+ }
+
var promisedDeps = // Shared styles will already be on the page:
route === "/_app" || false // We use `style-loader` in development:
? Promise.resolve([])
: route === this.initialPage
? Promise.resolve(this.initialStyleSheets) // Tests that this does not block hydration:
: // test/integration/css-fixtures/hydrate-without-deps/
- this.getDependencies(route);
+ this.getDependencies(route)
+ .then(function(deps) {
+ return deps.filter(function(d) {
+ return d.endsWith(".css");
+ });
+ })
+ .then(function(cssFiles) {
+ return (
+ // These files should've already been fetched by now, so this
+ // should resolve pretty much instantly.
+ Promise.all(
+ cssFiles.map(function(d) {
+ return fetchStyleSheet(d);
+ })
+ )
+ );
+ });
promisedDeps.then(
function(deps) {
- return register(
- deps.filter(function(d) {
- return d.endsWith(".css");
- })
- );
+ return register(deps);
},
function(error) {
_this5.pageCache[route] = {
@@ -2133,7 +2104,7 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
appendLink(
url,
relPrefetch,
- url.endsWith(".css") ? "style" : "script"
+ url.endsWith(".css") ? relPreloadStyle : "script"
),
true &&
!isDependency &&Diff for main-be61079..e7.module.js
@@ -193,7 +193,7 @@
var _headManager = _interopRequireDefault(__webpack_require__("DqTX"));
- var _pageLoader = _interopRequireWildcard3(__webpack_require__("zmvN"));
+ var _pageLoader = _interopRequireDefault(__webpack_require__("zmvN"));
var _performanceRelayer = _interopRequireDefault(
__webpack_require__("bGXG")
@@ -239,13 +239,25 @@
asPath = (0, _router.delBasePath)(asPath);
}
+ var looseToArray = input => [].slice.call(input);
+
var pageLoader = new _pageLoader.default(
buildId,
prefix,
page,
- [].slice
- .call(document.querySelectorAll("link[rel=stylesheet][data-n-p]"))
- .map(e => e.getAttribute("href"))
+ looseToArray(document.styleSheets)
+ .filter(
+ el =>
+ el.ownerNode &&
+ el.ownerNode.tagName === "LINK" &&
+ el.ownerNode.hasAttribute("data-n-p")
+ )
+ .map(sheet => ({
+ href: sheet.ownerNode.getAttribute("href"),
+ text: looseToArray(sheet.cssRules)
+ .map(r => r.cssText)
+ .join("")
+ }))
);
var register = _ref => {
@@ -702,8 +714,8 @@
); // lastAppProps has to be set before ReactDom.render to account for ReactDom throwing an error.
lastAppProps = appProps;
+ var canceled = false;
var resolvePromise;
- var renderPromiseReject;
var renderPromise = new Promise((resolve, reject) => {
if (lastRenderReject) {
lastRenderReject();
@@ -714,17 +726,15 @@
resolve();
};
- renderPromiseReject = lastRenderReject = () => {
+ lastRenderReject = () => {
+ canceled = true;
lastRenderReject = null;
var error = new Error("Cancel rendering route");
error.cancelled = true;
reject(error);
};
- }); // TODO: consider replacing this with real `<style>` tags that have
- // plain-text CSS content that's provided by RouteInfo. That'd remove the
- // need for the staging `<link>`s and the ability for CSS to be missing at
- // this phase, allowing us to remove the error handling flow that reloads the
- // page.
+ }); // This function has a return type to ensure it doesn't start returning a
+ // Promise. It should remain synchronous.
function onStart() {
if (
@@ -734,79 +744,27 @@
// unless we're in production:
false
) {
- return Promise.resolve([]);
- } // Clean up previous render if canceling:
+ return false;
+ }
- [].slice
- .call(
- document.querySelectorAll(
- "link[data-n-staging], noscript[data-n-staging]"
- )
- )
- .forEach(el => {
- el.parentNode.removeChild(el);
- });
- var referenceNodes = [].slice.call(
- document.querySelectorAll("link[data-n-g], link[data-n-p]")
+ var currentStyleTags = looseToArray(
+ document.querySelectorAll("style[data-n-href]")
);
- var referenceHrefs = new Set(
- referenceNodes.map(e => e.getAttribute("href"))
+ var currentHrefs = new Set(
+ currentStyleTags.map(tag => tag.getAttribute("data-n-href"))
);
- var referenceNode = referenceNodes[referenceNodes.length - 1];
- var required = styleSheets.map(href => {
- var newNode, promise;
- var existingLink = referenceHrefs.has(href);
-
- if (existingLink) {
- newNode = document.createElement("noscript");
- newNode.setAttribute("data-n-staging", href);
- promise = true;
- } else {
- var [link, onload] = (0, _pageLoader.createLink)(
- href,
- "stylesheet"
- );
- link.setAttribute("data-n-staging", ""); // Media `none` does not work in Firefox, so `print` is more
- // cross-browser. Since this is so short lived we don't have to worry
- // about style thrashing in a print view (where no routing is going to be
- // happening anyway).
-
- link.setAttribute("media", "print");
- newNode = link;
- promise = onload;
- }
-
- if (referenceNode) {
- referenceNode.parentNode.insertBefore(
- newNode,
- referenceNode.nextSibling
- );
- referenceNode = newNode;
- } else {
- document.head.appendChild(newNode);
+ styleSheets.forEach(_ref7 => {
+ var { href, text } = _ref7;
+
+ if (!currentHrefs.has(href)) {
+ var styleTag = document.createElement("style");
+ styleTag.setAttribute("data-n-href", href);
+ styleTag.setAttribute("media", "x");
+ document.head.appendChild(styleTag);
+ styleTag.appendChild(document.createTextNode(text));
}
-
- return promise;
- });
- return Promise.all(required).catch(() => {
- // This is too late in the rendering lifecycle to use the existing
- // `PAGE_LOAD_ERROR` flow (via `handleRouteInfoError`).
- // To match that behavior, we request the page to reload with the current
- // asPath. This is already set at this phase since we "committed" to the
- // render.
- // This handles an edge case where a new deployment is rolled during
- // client-side transition and the CSS assets are missing.
- // This prevents:
- // 1. An unstyled page from being rendered (old behavior)
- // 2. The `/_error` page being rendered (we want to reload for the new
- // deployment)
- window.location.href = router.asPath; // Instead of rethrowing the CSS loading error, we give a promise that
- // won't resolve. This pauses the rendering process until the page
- // reloads. Re-throwing the error could result in a flash of error page.
- // throw cssLoadingError
-
- return new Promise(() => {});
});
+ return true;
}
function onCommit() {
@@ -815,45 +773,56 @@
// unless we're in production:
true && // We can skip this during hydration. Running it wont cause any harm, but
// we may as well save the CPU cycles:
- !isInitialRender && // Ensure this render commit owns the currently staged stylesheets:
- renderPromiseReject === lastRenderReject
+ !isInitialRender && // Ensure this render was not canceled
+ !canceled
) {
- // Remove or relocate old stylesheets:
- var relocatePlaceholders = [].slice.call(
- document.querySelectorAll("noscript[data-n-staging]")
+ var desiredHrefs = new Set(styleSheets.map(s => s.href));
+ var currentStyleTags = looseToArray(
+ document.querySelectorAll("style[data-n-href]")
);
- var relocateHrefs = relocatePlaceholders.map(e =>
- e.getAttribute("data-n-staging")
- );
- [].slice
- .call(document.querySelectorAll("link[data-n-p]"))
- .forEach(el => {
- var currentHref = el.getAttribute("href");
- var relocateIndex = relocateHrefs.indexOf(currentHref);
-
- if (relocateIndex !== -1) {
- var _placeholderElement$p;
-
- var placeholderElement = relocatePlaceholders[relocateIndex];
- (_placeholderElement$p = placeholderElement.parentNode) ==
- null
- ? void 0
- : _placeholderElement$p.replaceChild(
- el,
- placeholderElement
- );
- } else {
- el.parentNode.removeChild(el);
+ var currentHrefs = currentStyleTags.map(tag =>
+ tag.getAttribute("data-n-href")
+ ); // Toggle `<style>` tags on or off depending on if they're needed:
+
+ for (var idx = 0; idx < currentHrefs.length; ++idx) {
+ if (desiredHrefs.has(currentHrefs[idx])) {
+ currentStyleTags[idx].removeAttribute("media");
+ } else {
+ currentStyleTags[idx].setAttribute("media", "x");
+ }
+ } // Reorder styles into intended order:
+
+ var referenceNode = document.querySelector("noscript[data-n-css]");
+
+ if (
+ // This should be an invariant:
+ referenceNode
+ ) {
+ styleSheets.forEach(_ref8 => {
+ var { href } = _ref8;
+ var targetTag = document.querySelector(
+ 'style[data-n-href="'.concat(href, '"]')
+ );
+
+ if (
+ // This should be an invariant:
+ targetTag
+ ) {
+ referenceNode.parentNode.insertBefore(
+ targetTag,
+ referenceNode.nextSibling
+ );
+ referenceNode = targetTag;
}
- }); // Activate new stylesheets:
- [].slice
- .call(document.querySelectorAll("link[data-n-staging]"))
- .forEach(el => {
- el.removeAttribute("data-n-staging");
- el.removeAttribute("media");
- el.setAttribute("data-n-p", "");
- }); // Force browser to recompute layout, which prevents a flash of unstyled
- // content:
+ });
+ } // Finally, clean up server rendered stylesheets:
+
+ looseToArray(document.querySelectorAll("link[data-n-p]")).forEach(
+ el => {
+ el.parentNode.removeChild(el);
+ }
+ ); // Force browser to recompute layout, which should prevent a flash of
+ // unstyled content:
getComputedStyle(document.body, "height");
}
@@ -871,32 +840,16 @@
null,
/*#__PURE__*/ _react.default.createElement(App, appProps)
)
- ); // We catch runtime errors using componentDidCatch which will trigger renderError
-
- return Promise.race([
- // Download required CSS assets first:
- onStart()
- .then(() => {
- // Ensure a new render has not been started:
- if (renderPromiseReject === lastRenderReject) {
- // Queue rendering:
- renderReactElement(
- false ? /*#__PURE__*/ undefined : elem,
- appElement
- );
- }
- })
- .then(
- () =>
- // Wait for rendering to complete:
- renderPromise
- ), // Bail early on route cancelation (rejection):
- renderPromise
- ]);
+ );
+
+ onStart(); // We catch runtime errors using componentDidCatch which will trigger renderError
+
+ renderReactElement(false ? /*#__PURE__*/ undefined : elem, appElement);
+ return renderPromise;
}
- function Root(_ref7) {
- var { callback, children } = _ref7;
+ function Root(_ref9) {
+ var { callback, children } = _ref9;
// We use `useLayoutEffect` to guarantee the callback is executed
// as soon as React flushes the update.
@@ -1287,7 +1240,6 @@
var _interopRequireDefault = __webpack_require__("TqRt");
exports.__esModule = true;
- exports.createLink = createLink;
exports.default = void 0;
var _mitt = _interopRequireDefault(__webpack_require__("dZ6Y"));
@@ -1332,6 +1284,7 @@
: // IE 11, Edge 12+, nearly all evergreen
"prefetch";
var relPreload = hasRel("preload") ? "preload" : relPrefetch;
+ var relPreloadStyle = "fetch";
var hasNoModule = "noModule" in document.createElement("script");
var requestIdleCallback =
@@ -1351,27 +1304,19 @@
return route.replace(/\/$/, "");
}
- function createLink(href, rel, as, link) {
- link = document.createElement("link");
- return [
- link,
- new Promise((res, rej) => {
- // The order of property assignment here is intentional:
- if (as) link.as = as;
- link.rel = rel;
- link.crossOrigin = "anonymous";
- link.onload = res;
- link.onerror = rej; // `href` should always be last:
-
- link.href = href;
- })
- ];
- }
+ function appendLink(href, rel, as, link) {
+ return new Promise((res, rej) => {
+ link = document.createElement("link"); // The order of property assignment here is intentional:
- function appendLink(href, rel, as) {
- var [link, res] = createLink(href, rel, as);
- document.head.appendChild(link);
- return res;
+ if (as) link.as = as;
+ link.rel = rel;
+ link.crossOrigin = "anonymous";
+ link.onload = res;
+ link.onerror = rej; // `href` should always be last:
+
+ link.href = href;
+ document.head.appendChild(link);
+ });
}
function loadScript(url) {
@@ -1617,7 +1562,7 @@
// wait for these to resolve. To prevent an unhandled
// rejection, we swallow the error which is handled later in
// the rendering cycle (this is just a preload optimization).
- appendLink(d, relPreload, "style").catch(() => {
+ appendLink(d, relPreload, relPreloadStyle).catch(() => {
/* ignore preload error */
});
}
@@ -1666,15 +1611,32 @@
var check;
}
+ function fetchStyleSheet(href) {
+ return fetch(href).then(res => {
+ if (!res.ok) throw pageLoadError(href);
+ return res.text().then(text => ({
+ href,
+ text
+ }));
+ });
+ }
+
var promisedDeps = // Shared styles will already be on the page:
route === "/_app" || false // We use `style-loader` in development:
? Promise.resolve([])
: route === this.initialPage
? Promise.resolve(this.initialStyleSheets) // Tests that this does not block hydration:
: // test/integration/css-fixtures/hydrate-without-deps/
- this.getDependencies(route);
+ this.getDependencies(route)
+ .then(deps => deps.filter(d => d.endsWith(".css")))
+ .then((
+ cssFiles // These files should've already been fetched by now, so this
+ ) =>
+ // should resolve pretty much instantly.
+ Promise.all(cssFiles.map(d => fetchStyleSheet(d)))
+ );
promisedDeps.then(
- deps => register(deps.filter(d => d.endsWith(".css"))),
+ deps => register(deps),
error => {
this.pageCache[route] = {
error
@@ -1722,7 +1684,7 @@
appendLink(
url,
relPrefetch,
- url.endsWith(".css") ? "style" : "script"
+ url.endsWith(".css") ? relPreloadStyle : "script"
),
true &&
!isDependency &&Diff for index.html
@@ -4,9 +4,10 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta name="next-head-count" content="2" />
+ <noscript data-n-css="true"></noscript>
<link
rel="preload"
- href="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ href="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
as="script"
crossorigin="anonymous"
/>
@@ -81,13 +82,13 @@
src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
></script>
<script
- src="/_next/static/chunks/main-209a935a087118ae6828.js"
+ src="/_next/static/chunks/main-fe24fe70b35ca4db2791.js"
async=""
crossorigin="anonymous"
nomodule=""
></script>
<script
- src="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ src="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
async=""
crossorigin="anonymous"
type="module"Diff for link.html
@@ -4,9 +4,10 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta name="next-head-count" content="2" />
+ <noscript data-n-css="true"></noscript>
<link
rel="preload"
- href="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ href="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
as="script"
crossorigin="anonymous"
/>
@@ -86,13 +87,13 @@
src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
></script>
<script
- src="/_next/static/chunks/main-209a935a087118ae6828.js"
+ src="/_next/static/chunks/main-fe24fe70b35ca4db2791.js"
async=""
crossorigin="anonymous"
nomodule=""
></script>
<script
- src="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ src="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
async=""
crossorigin="anonymous"
type="module"Diff for withRouter.html
@@ -4,9 +4,10 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta name="next-head-count" content="2" />
+ <noscript data-n-css="true"></noscript>
<link
rel="preload"
- href="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ href="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
as="script"
crossorigin="anonymous"
/>
@@ -81,13 +82,13 @@
src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
></script>
<script
- src="/_next/static/chunks/main-209a935a087118ae6828.js"
+ src="/_next/static/chunks/main-fe24fe70b35ca4db2791.js"
async=""
crossorigin="anonymous"
nomodule=""
></script>
<script
- src="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ src="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
async=""
crossorigin="anonymous"
type="module"Serverless Mode (Increase detected ⚠️ )
General Overall decrease ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| buildDuration | 13.5s | 13.6s | |
| nodeModulesSize | 57.5 MB | 57.5 MB | -3.18 kB |
Client Bundles (main, webpack, commons) Overall decrease ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| 677f882d2ed8..7f47.js gzip | 10.3 kB | 10.3 kB | ✓ |
| framework.HASH.js gzip | 39 kB | 39 kB | ✓ |
| main-d4bab31..824e.js gzip | 7.34 kB | N/A | N/A |
| webpack-e067..f178.js gzip | 751 B | 751 B | ✓ |
| main-ff68bee..74d0.js gzip | N/A | 7.32 kB | N/A |
| Overall change | 57.4 kB | 57.3 kB | -20 B |
Client Bundles (main, webpack, commons) Modern Overall decrease ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| 677f882d2ed8..dule.js gzip | 6.15 kB | 6.15 kB | ✓ |
| framework.HA..dule.js gzip | 39 kB | 39 kB | ✓ |
| main-438d30a..dule.js gzip | 6.39 kB | N/A | N/A |
| webpack-07c5..dule.js gzip | 751 B | 751 B | ✓ |
| main-91bc16e..dule.js gzip | N/A | 6.39 kB | N/A |
| Overall change | 52.3 kB | 52.3 kB | -4 B |
Legacy Client Bundles (polyfills)
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| polyfills-4b..e242.js gzip | 31 kB | 31 kB | ✓ |
| Overall change | 31 kB | 31 kB | ✓ |
Client Pages
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _app-9a0b9e1..b37e.js gzip | 1.28 kB | 1.28 kB | ✓ |
| _error-28298..e0c9.js gzip | 3.44 kB | 3.44 kB | ✓ |
| hooks-89731c..c609.js gzip | 887 B | 887 B | ✓ |
| index-17468f..5d83.js gzip | 227 B | 227 B | ✓ |
| link-000f151..65d4.js gzip | 1.29 kB | 1.29 kB | ✓ |
| routerDirect..924c.js gzip | 284 B | 284 B | ✓ |
| withRouter-7..c13d.js gzip | 284 B | 284 B | ✓ |
| Overall change | 7.69 kB | 7.69 kB | ✓ |
Client Pages Modern
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _app-75d3a82..dule.js gzip | 625 B | 625 B | ✓ |
| _error-65c8a..dule.js gzip | 2.29 kB | 2.29 kB | ✓ |
| hooks-cbf13f..dule.js gzip | 387 B | 387 B | ✓ |
| index-b9a643..dule.js gzip | 226 B | 226 B | ✓ |
| link-4cfda7a..dule.js gzip | 1.26 kB | 1.26 kB | ✓ |
| routerDirect..dule.js gzip | 284 B | 284 B | ✓ |
| withRouter-f..dule.js gzip | 282 B | 282 B | ✓ |
| Overall change | 5.35 kB | 5.35 kB | ✓ |
Client Build Manifests
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _buildManifest.js gzip | 322 B | 322 B | ✓ |
| _buildManife..dule.js gzip | 330 B | 330 B | ✓ |
| Overall change | 652 B | 652 B | ✓ |
Serverless bundles Overall increase ⚠️
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _error.js | 1.03 MB | 1.03 MB | |
| 404.html | 4.18 kB | 4.22 kB | |
| hooks.html | 3.82 kB | 3.86 kB | |
| index.js | 1.03 MB | 1.03 MB | |
| link.js | 1.07 MB | 1.07 MB | |
| routerDirect.js | 1.07 MB | 1.07 MB | |
| withRouter.js | 1.07 MB | 1.07 MB | |
| Overall change | 5.28 MB | 5.28 MB |
Stats from current PRDefault Server Mode (Increase detected
|
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| buildDuration | 11.5s | 11.8s | |
| nodeModulesSize | 57.5 MB | 57.5 MB | -3.18 kB |
Page Load Tests Overall decrease ⚠️
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| / failed reqs | 0 | 0 | ✓ |
| / total time (seconds) | 2.044 | 2.18 | |
| / avg req/sec | 1223.02 | 1146.53 | |
| /error-in-render failed reqs | 0 | 0 | ✓ |
| /error-in-render total time (seconds) | 1.124 | 1.119 | -0.01 |
| /error-in-render avg req/sec | 2224 | 2233.17 | +9.17 |
Client Bundles (main, webpack, commons) Overall decrease ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| 677f882d2ed8..7f47.js gzip | 10.3 kB | 10.3 kB | ✓ |
| framework.HASH.js gzip | 39 kB | 39 kB | ✓ |
| main-d4bab31..824e.js gzip | 7.34 kB | 7.32 kB | -20 B |
| webpack-e067..f178.js gzip | 751 B | 751 B | ✓ |
| Overall change | 57.4 kB | 57.3 kB | -20 B |
Client Bundles (main, webpack, commons) Modern Overall decrease ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| 677f882d2ed8..dule.js gzip | 6.15 kB | 6.15 kB | ✓ |
| framework.HA..dule.js gzip | 39 kB | 39 kB | ✓ |
| main-438d30a..dule.js gzip | 6.39 kB | 6.39 kB | -4 B |
| webpack-07c5..dule.js gzip | 751 B | 751 B | ✓ |
| Overall change | 52.3 kB | 52.3 kB | -4 B |
Legacy Client Bundles (polyfills)
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| polyfills-4b..e242.js gzip | 31 kB | 31 kB | ✓ |
| Overall change | 31 kB | 31 kB | ✓ |
Client Pages
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _app-9a0b9e1..b37e.js gzip | 1.28 kB | 1.28 kB | ✓ |
| _error-28298..e0c9.js gzip | 3.44 kB | 3.44 kB | ✓ |
| hooks-89731c..c609.js gzip | 887 B | 887 B | ✓ |
| index-17468f..5d83.js gzip | 227 B | 227 B | ✓ |
| link-000f151..65d4.js gzip | 1.29 kB | 1.29 kB | ✓ |
| routerDirect..924c.js gzip | 284 B | 284 B | ✓ |
| withRouter-7..c13d.js gzip | 284 B | 284 B | ✓ |
| Overall change | 7.69 kB | 7.69 kB | ✓ |
Client Pages Modern
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _app-75d3a82..dule.js gzip | 625 B | 625 B | ✓ |
| _error-65c8a..dule.js gzip | 2.29 kB | 2.29 kB | ✓ |
| hooks-cbf13f..dule.js gzip | 387 B | 387 B | ✓ |
| index-b9a643..dule.js gzip | 226 B | 226 B | ✓ |
| link-4cfda7a..dule.js gzip | 1.26 kB | 1.26 kB | ✓ |
| routerDirect..dule.js gzip | 284 B | 284 B | ✓ |
| withRouter-f..dule.js gzip | 282 B | 282 B | ✓ |
| Overall change | 5.35 kB | 5.35 kB | ✓ |
Client Build Manifests
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _buildManifest.js gzip | 322 B | 322 B | ✓ |
| _buildManife..dule.js gzip | 330 B | 330 B | ✓ |
| Overall change | 652 B | 652 B | ✓ |
Rendered Page Sizes Overall increase ⚠️
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| index.html gzip | 948 B | 970 B | |
| link.html gzip | 954 B | 977 B | |
| withRouter.html gzip | 940 B | 963 B | |
| Overall change | 2.84 kB | 2.91 kB |
Diffs
Diff for main-209a935..118ae6828.js
@@ -275,7 +275,7 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var _headManager = _interopRequireDefault(__webpack_require__("DqTX"));
- var _pageLoader = _interopRequireWildcard3(__webpack_require__("zmvN"));
+ var _pageLoader = _interopRequireDefault(__webpack_require__("zmvN"));
var _performanceRelayer = _interopRequireDefault(
__webpack_require__("bGXG")
@@ -319,14 +319,31 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
asPath = (0, _router.delBasePath)(asPath);
}
+ var looseToArray = function looseToArray(input) {
+ return [].slice.call(input);
+ };
+
var pageLoader = new _pageLoader["default"](
buildId,
prefix,
page,
- [].slice
- .call(document.querySelectorAll("link[rel=stylesheet][data-n-p]"))
- .map(function(e) {
- return e.getAttribute("href");
+ looseToArray(document.styleSheets)
+ .filter(function(el) {
+ return (
+ el.ownerNode &&
+ el.ownerNode.tagName === "LINK" &&
+ el.ownerNode.hasAttribute("data-n-p")
+ );
+ })
+ .map(function(sheet) {
+ return {
+ href: sheet.ownerNode.getAttribute("href"),
+ text: looseToArray(sheet.cssRules)
+ .map(function(r) {
+ return r.cssText;
+ })
+ .join("")
+ };
})
);
@@ -967,8 +984,8 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
); // lastAppProps has to be set before ReactDom.render to account for ReactDom throwing an error.
lastAppProps = appProps;
+ var canceled = false;
var resolvePromise;
- var renderPromiseReject;
var renderPromise = new Promise(function(resolve, reject) {
if (_lastRenderReject) {
_lastRenderReject();
@@ -979,17 +996,15 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
resolve();
};
- renderPromiseReject = _lastRenderReject = function lastRenderReject() {
+ _lastRenderReject = function lastRenderReject() {
+ canceled = true;
_lastRenderReject = null;
var error = new Error("Cancel rendering route");
error.cancelled = true;
reject(error);
};
- }); // TODO: consider replacing this with real `<style>` tags that have
- // plain-text CSS content that's provided by RouteInfo. That'd remove the
- // need for the staging `<link>`s and the ability for CSS to be missing at
- // this phase, allowing us to remove the error handling flow that reloads the
- // page.
+ }); // This function has a return type to ensure it doesn't start returning a
+ // Promise. It should remain synchronous.
function onStart() {
if (
@@ -999,82 +1014,30 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
// unless we're in production:
false
) {
- return Promise.resolve([]);
- } // Clean up previous render if canceling:
+ return false;
+ }
- [].slice
- .call(
- document.querySelectorAll(
- "link[data-n-staging], noscript[data-n-staging]"
- )
- )
- .forEach(function(el) {
- el.parentNode.removeChild(el);
- });
- var referenceNodes = [].slice.call(
- document.querySelectorAll("link[data-n-g], link[data-n-p]")
+ var currentStyleTags = looseToArray(
+ document.querySelectorAll("style[data-n-href]")
);
- var referenceHrefs = new Set(
- referenceNodes.map(function(e) {
- return e.getAttribute("href");
+ var currentHrefs = new Set(
+ currentStyleTags.map(function(tag) {
+ return tag.getAttribute("data-n-href");
})
);
- var referenceNode = referenceNodes[referenceNodes.length - 1];
- var required = styleSheets.map(function(href) {
- var newNode, promise;
- var existingLink = referenceHrefs.has(href);
-
- if (existingLink) {
- newNode = document.createElement("noscript");
- newNode.setAttribute("data-n-staging", href);
- promise = true;
- } else {
- var _ref9 = (0, _pageLoader.createLink)(href, "stylesheet"),
- _ref10 = _slicedToArray(_ref9, 2),
- link = _ref10[0],
- onload = _ref10[1];
-
- link.setAttribute("data-n-staging", ""); // Media `none` does not work in Firefox, so `print` is more
- // cross-browser. Since this is so short lived we don't have to worry
- // about style thrashing in a print view (where no routing is going to be
- // happening anyway).
-
- link.setAttribute("media", "print");
- newNode = link;
- promise = onload;
- }
-
- if (referenceNode) {
- referenceNode.parentNode.insertBefore(
- newNode,
- referenceNode.nextSibling
- );
- referenceNode = newNode;
- } else {
- document.head.appendChild(newNode);
+ styleSheets.forEach(function(_ref9) {
+ var href = _ref9.href,
+ text = _ref9.text;
+
+ if (!currentHrefs.has(href)) {
+ var styleTag = document.createElement("style");
+ styleTag.setAttribute("data-n-href", href);
+ styleTag.setAttribute("media", "x");
+ document.head.appendChild(styleTag);
+ styleTag.appendChild(document.createTextNode(text));
}
-
- return promise;
- });
- return Promise.all(required)["catch"](function() {
- // This is too late in the rendering lifecycle to use the existing
- // `PAGE_LOAD_ERROR` flow (via `handleRouteInfoError`).
- // To match that behavior, we request the page to reload with the current
- // asPath. This is already set at this phase since we "committed" to the
- // render.
- // This handles an edge case where a new deployment is rolled during
- // client-side transition and the CSS assets are missing.
- // This prevents:
- // 1. An unstyled page from being rendered (old behavior)
- // 2. The `/_error` page being rendered (we want to reload for the new
- // deployment)
- window.location.href = router.asPath; // Instead of rethrowing the CSS loading error, we give a promise that
- // won't resolve. This pauses the rendering process until the page
- // reloads. Re-throwing the error could result in a flash of error page.
- // throw cssLoadingError
-
- return new Promise(function() {});
});
+ return true;
}
function onCommit() {
@@ -1083,45 +1046,60 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
// unless we're in production:
true && // We can skip this during hydration. Running it wont cause any harm, but
// we may as well save the CPU cycles:
- !isInitialRender && // Ensure this render commit owns the currently staged stylesheets:
- renderPromiseReject === _lastRenderReject
+ !isInitialRender && // Ensure this render was not canceled
+ !canceled
) {
- // Remove or relocate old stylesheets:
- var relocatePlaceholders = [].slice.call(
- document.querySelectorAll("noscript[data-n-staging]")
+ var desiredHrefs = new Set(
+ styleSheets.map(function(s) {
+ return s.href;
+ })
);
- var relocateHrefs = relocatePlaceholders.map(function(e) {
- return e.getAttribute("data-n-staging");
- });
- [].slice
- .call(document.querySelectorAll("link[data-n-p]"))
- .forEach(function(el) {
- var currentHref = el.getAttribute("href");
- var relocateIndex = relocateHrefs.indexOf(currentHref);
-
- if (relocateIndex !== -1) {
- var _placeholderElement$p;
-
- var placeholderElement = relocatePlaceholders[relocateIndex];
- (_placeholderElement$p = placeholderElement.parentNode) ==
- null
- ? void 0
- : _placeholderElement$p.replaceChild(
- el,
- placeholderElement
- );
- } else {
- el.parentNode.removeChild(el);
+ var currentStyleTags = looseToArray(
+ document.querySelectorAll("style[data-n-href]")
+ );
+ var currentHrefs = currentStyleTags.map(function(tag) {
+ return tag.getAttribute("data-n-href");
+ }); // Toggle `<style>` tags on or off depending on if they're needed:
+
+ for (var idx = 0; idx < currentHrefs.length; ++idx) {
+ if (desiredHrefs.has(currentHrefs[idx])) {
+ currentStyleTags[idx].removeAttribute("media");
+ } else {
+ currentStyleTags[idx].setAttribute("media", "x");
+ }
+ } // Reorder styles into intended order:
+
+ var referenceNode = document.querySelector("noscript[data-n-css]");
+
+ if (
+ // This should be an invariant:
+ referenceNode
+ ) {
+ styleSheets.forEach(function(_ref10) {
+ var href = _ref10.href;
+ var targetTag = document.querySelector(
+ 'style[data-n-href="'.concat(href, '"]')
+ );
+
+ if (
+ // This should be an invariant:
+ targetTag
+ ) {
+ referenceNode.parentNode.insertBefore(
+ targetTag,
+ referenceNode.nextSibling
+ );
+ referenceNode = targetTag;
}
- }); // Activate new stylesheets:
- [].slice
- .call(document.querySelectorAll("link[data-n-staging]"))
- .forEach(function(el) {
- el.removeAttribute("data-n-staging");
- el.removeAttribute("media");
- el.setAttribute("data-n-p", "");
- }); // Force browser to recompute layout, which prevents a flash of unstyled
- // content:
+ });
+ } // Finally, clean up server rendered stylesheets:
+
+ looseToArray(document.querySelectorAll("link[data-n-p]")).forEach(
+ function(el) {
+ el.parentNode.removeChild(el);
+ }
+ ); // Force browser to recompute layout, which should prevent a flash of
+ // unstyled content:
getComputedStyle(document.body, "height");
}
@@ -1139,29 +1117,12 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
null,
/*#__PURE__*/ _react["default"].createElement(App, appProps)
)
- ); // We catch runtime errors using componentDidCatch which will trigger renderError
-
- return Promise.race([
- // Download required CSS assets first:
- onStart()
- .then(function() {
- // Ensure a new render has not been started:
- if (renderPromiseReject === _lastRenderReject) {
- // Queue rendering:
- renderReactElement(
- false ? /*#__PURE__*/ undefined : elem,
- appElement
- );
- }
- })
- .then(function() {
- return (
- // Wait for rendering to complete:
- renderPromise
- );
- }), // Bail early on route cancelation (rejection):
- renderPromise
- ]);
+ );
+
+ onStart(); // We catch runtime errors using componentDidCatch which will trigger renderError
+
+ renderReactElement(false ? /*#__PURE__*/ undefined : elem, appElement);
+ return renderPromise;
}
function Root(_ref11) {
@@ -1617,12 +1578,9 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var _createClass = __webpack_require__("W8MJ");
- var _slicedToArray = __webpack_require__("J4zp");
-
var _interopRequireDefault = __webpack_require__("TqRt");
exports.__esModule = true;
- exports.createLink = createLink;
exports["default"] = void 0;
var _mitt = _interopRequireDefault(__webpack_require__("dZ6Y"));
@@ -1667,6 +1625,7 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
: // IE 11, Edge 12+, nearly all evergreen
"prefetch";
var relPreload = hasRel("preload") ? "preload" : relPrefetch;
+ var relPreloadStyle = "fetch";
var hasNoModule = "noModule" in document.createElement("script");
var requestIdleCallback =
@@ -1686,31 +1645,19 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
return route.replace(/\/$/, "");
}
- function createLink(href, rel, as, link) {
- link = document.createElement("link");
- return [
- link,
- new Promise(function(res, rej) {
- // The order of property assignment here is intentional:
- if (as) link.as = as;
- link.rel = rel;
- link.crossOrigin = "anonymous";
- link.onload = res;
- link.onerror = rej; // `href` should always be last:
-
- link.href = href;
- })
- ];
- }
+ function appendLink(href, rel, as, link) {
+ return new Promise(function(res, rej) {
+ link = document.createElement("link"); // The order of property assignment here is intentional:
- function appendLink(href, rel, as) {
- var _createLink = createLink(href, rel, as),
- _createLink2 = _slicedToArray(_createLink, 2),
- link = _createLink2[0],
- res = _createLink2[1];
+ if (as) link.as = as;
+ link.rel = rel;
+ link.crossOrigin = "anonymous";
+ link.onload = res;
+ link.onerror = rej; // `href` should always be last:
- document.head.appendChild(link);
- return res;
+ link.href = href;
+ document.head.appendChild(link);
+ });
}
function loadScript(url) {
@@ -2007,7 +1954,7 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
// wait for these to resolve. To prevent an unhandled
// rejection, we swallow the error which is handled later in
// the rendering cycle (this is just a preload optimization).
- appendLink(d, relPreload, "style")["catch"](
+ appendLink(d, relPreload, relPreloadStyle)["catch"](
function() {
/* ignore preload error */
}
@@ -2064,20 +2011,44 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var check;
}
+ function fetchStyleSheet(href) {
+ return fetch(href).then(function(res) {
+ if (!res.ok) throw pageLoadError(href);
+ return res.text().then(function(text) {
+ return {
+ href: href,
+ text: text
+ };
+ });
+ });
+ }
+
var promisedDeps = // Shared styles will already be on the page:
route === "/_app" || false // We use `style-loader` in development:
? Promise.resolve([])
: route === this.initialPage
? Promise.resolve(this.initialStyleSheets) // Tests that this does not block hydration:
: // test/integration/css-fixtures/hydrate-without-deps/
- this.getDependencies(route);
+ this.getDependencies(route)
+ .then(function(deps) {
+ return deps.filter(function(d) {
+ return d.endsWith(".css");
+ });
+ })
+ .then(function(cssFiles) {
+ return (
+ // These files should've already been fetched by now, so this
+ // should resolve pretty much instantly.
+ Promise.all(
+ cssFiles.map(function(d) {
+ return fetchStyleSheet(d);
+ })
+ )
+ );
+ });
promisedDeps.then(
function(deps) {
- return register(
- deps.filter(function(d) {
- return d.endsWith(".css");
- })
- );
+ return register(deps);
},
function(error) {
_this5.pageCache[route] = {
@@ -2133,7 +2104,7 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
appendLink(
url,
relPrefetch,
- url.endsWith(".css") ? "style" : "script"
+ url.endsWith(".css") ? relPreloadStyle : "script"
),
true &&
!isDependency &&Diff for main-be61079..e7.module.js
@@ -193,7 +193,7 @@
var _headManager = _interopRequireDefault(__webpack_require__("DqTX"));
- var _pageLoader = _interopRequireWildcard3(__webpack_require__("zmvN"));
+ var _pageLoader = _interopRequireDefault(__webpack_require__("zmvN"));
var _performanceRelayer = _interopRequireDefault(
__webpack_require__("bGXG")
@@ -239,13 +239,25 @@
asPath = (0, _router.delBasePath)(asPath);
}
+ var looseToArray = input => [].slice.call(input);
+
var pageLoader = new _pageLoader.default(
buildId,
prefix,
page,
- [].slice
- .call(document.querySelectorAll("link[rel=stylesheet][data-n-p]"))
- .map(e => e.getAttribute("href"))
+ looseToArray(document.styleSheets)
+ .filter(
+ el =>
+ el.ownerNode &&
+ el.ownerNode.tagName === "LINK" &&
+ el.ownerNode.hasAttribute("data-n-p")
+ )
+ .map(sheet => ({
+ href: sheet.ownerNode.getAttribute("href"),
+ text: looseToArray(sheet.cssRules)
+ .map(r => r.cssText)
+ .join("")
+ }))
);
var register = _ref => {
@@ -702,8 +714,8 @@
); // lastAppProps has to be set before ReactDom.render to account for ReactDom throwing an error.
lastAppProps = appProps;
+ var canceled = false;
var resolvePromise;
- var renderPromiseReject;
var renderPromise = new Promise((resolve, reject) => {
if (lastRenderReject) {
lastRenderReject();
@@ -714,17 +726,15 @@
resolve();
};
- renderPromiseReject = lastRenderReject = () => {
+ lastRenderReject = () => {
+ canceled = true;
lastRenderReject = null;
var error = new Error("Cancel rendering route");
error.cancelled = true;
reject(error);
};
- }); // TODO: consider replacing this with real `<style>` tags that have
- // plain-text CSS content that's provided by RouteInfo. That'd remove the
- // need for the staging `<link>`s and the ability for CSS to be missing at
- // this phase, allowing us to remove the error handling flow that reloads the
- // page.
+ }); // This function has a return type to ensure it doesn't start returning a
+ // Promise. It should remain synchronous.
function onStart() {
if (
@@ -734,79 +744,27 @@
// unless we're in production:
false
) {
- return Promise.resolve([]);
- } // Clean up previous render if canceling:
+ return false;
+ }
- [].slice
- .call(
- document.querySelectorAll(
- "link[data-n-staging], noscript[data-n-staging]"
- )
- )
- .forEach(el => {
- el.parentNode.removeChild(el);
- });
- var referenceNodes = [].slice.call(
- document.querySelectorAll("link[data-n-g], link[data-n-p]")
+ var currentStyleTags = looseToArray(
+ document.querySelectorAll("style[data-n-href]")
);
- var referenceHrefs = new Set(
- referenceNodes.map(e => e.getAttribute("href"))
+ var currentHrefs = new Set(
+ currentStyleTags.map(tag => tag.getAttribute("data-n-href"))
);
- var referenceNode = referenceNodes[referenceNodes.length - 1];
- var required = styleSheets.map(href => {
- var newNode, promise;
- var existingLink = referenceHrefs.has(href);
-
- if (existingLink) {
- newNode = document.createElement("noscript");
- newNode.setAttribute("data-n-staging", href);
- promise = true;
- } else {
- var [link, onload] = (0, _pageLoader.createLink)(
- href,
- "stylesheet"
- );
- link.setAttribute("data-n-staging", ""); // Media `none` does not work in Firefox, so `print` is more
- // cross-browser. Since this is so short lived we don't have to worry
- // about style thrashing in a print view (where no routing is going to be
- // happening anyway).
-
- link.setAttribute("media", "print");
- newNode = link;
- promise = onload;
- }
-
- if (referenceNode) {
- referenceNode.parentNode.insertBefore(
- newNode,
- referenceNode.nextSibling
- );
- referenceNode = newNode;
- } else {
- document.head.appendChild(newNode);
+ styleSheets.forEach(_ref7 => {
+ var { href, text } = _ref7;
+
+ if (!currentHrefs.has(href)) {
+ var styleTag = document.createElement("style");
+ styleTag.setAttribute("data-n-href", href);
+ styleTag.setAttribute("media", "x");
+ document.head.appendChild(styleTag);
+ styleTag.appendChild(document.createTextNode(text));
}
-
- return promise;
- });
- return Promise.all(required).catch(() => {
- // This is too late in the rendering lifecycle to use the existing
- // `PAGE_LOAD_ERROR` flow (via `handleRouteInfoError`).
- // To match that behavior, we request the page to reload with the current
- // asPath. This is already set at this phase since we "committed" to the
- // render.
- // This handles an edge case where a new deployment is rolled during
- // client-side transition and the CSS assets are missing.
- // This prevents:
- // 1. An unstyled page from being rendered (old behavior)
- // 2. The `/_error` page being rendered (we want to reload for the new
- // deployment)
- window.location.href = router.asPath; // Instead of rethrowing the CSS loading error, we give a promise that
- // won't resolve. This pauses the rendering process until the page
- // reloads. Re-throwing the error could result in a flash of error page.
- // throw cssLoadingError
-
- return new Promise(() => {});
});
+ return true;
}
function onCommit() {
@@ -815,45 +773,56 @@
// unless we're in production:
true && // We can skip this during hydration. Running it wont cause any harm, but
// we may as well save the CPU cycles:
- !isInitialRender && // Ensure this render commit owns the currently staged stylesheets:
- renderPromiseReject === lastRenderReject
+ !isInitialRender && // Ensure this render was not canceled
+ !canceled
) {
- // Remove or relocate old stylesheets:
- var relocatePlaceholders = [].slice.call(
- document.querySelectorAll("noscript[data-n-staging]")
+ var desiredHrefs = new Set(styleSheets.map(s => s.href));
+ var currentStyleTags = looseToArray(
+ document.querySelectorAll("style[data-n-href]")
);
- var relocateHrefs = relocatePlaceholders.map(e =>
- e.getAttribute("data-n-staging")
- );
- [].slice
- .call(document.querySelectorAll("link[data-n-p]"))
- .forEach(el => {
- var currentHref = el.getAttribute("href");
- var relocateIndex = relocateHrefs.indexOf(currentHref);
-
- if (relocateIndex !== -1) {
- var _placeholderElement$p;
-
- var placeholderElement = relocatePlaceholders[relocateIndex];
- (_placeholderElement$p = placeholderElement.parentNode) ==
- null
- ? void 0
- : _placeholderElement$p.replaceChild(
- el,
- placeholderElement
- );
- } else {
- el.parentNode.removeChild(el);
+ var currentHrefs = currentStyleTags.map(tag =>
+ tag.getAttribute("data-n-href")
+ ); // Toggle `<style>` tags on or off depending on if they're needed:
+
+ for (var idx = 0; idx < currentHrefs.length; ++idx) {
+ if (desiredHrefs.has(currentHrefs[idx])) {
+ currentStyleTags[idx].removeAttribute("media");
+ } else {
+ currentStyleTags[idx].setAttribute("media", "x");
+ }
+ } // Reorder styles into intended order:
+
+ var referenceNode = document.querySelector("noscript[data-n-css]");
+
+ if (
+ // This should be an invariant:
+ referenceNode
+ ) {
+ styleSheets.forEach(_ref8 => {
+ var { href } = _ref8;
+ var targetTag = document.querySelector(
+ 'style[data-n-href="'.concat(href, '"]')
+ );
+
+ if (
+ // This should be an invariant:
+ targetTag
+ ) {
+ referenceNode.parentNode.insertBefore(
+ targetTag,
+ referenceNode.nextSibling
+ );
+ referenceNode = targetTag;
}
- }); // Activate new stylesheets:
- [].slice
- .call(document.querySelectorAll("link[data-n-staging]"))
- .forEach(el => {
- el.removeAttribute("data-n-staging");
- el.removeAttribute("media");
- el.setAttribute("data-n-p", "");
- }); // Force browser to recompute layout, which prevents a flash of unstyled
- // content:
+ });
+ } // Finally, clean up server rendered stylesheets:
+
+ looseToArray(document.querySelectorAll("link[data-n-p]")).forEach(
+ el => {
+ el.parentNode.removeChild(el);
+ }
+ ); // Force browser to recompute layout, which should prevent a flash of
+ // unstyled content:
getComputedStyle(document.body, "height");
}
@@ -871,32 +840,16 @@
null,
/*#__PURE__*/ _react.default.createElement(App, appProps)
)
- ); // We catch runtime errors using componentDidCatch which will trigger renderError
-
- return Promise.race([
- // Download required CSS assets first:
- onStart()
- .then(() => {
- // Ensure a new render has not been started:
- if (renderPromiseReject === lastRenderReject) {
- // Queue rendering:
- renderReactElement(
- false ? /*#__PURE__*/ undefined : elem,
- appElement
- );
- }
- })
- .then(
- () =>
- // Wait for rendering to complete:
- renderPromise
- ), // Bail early on route cancelation (rejection):
- renderPromise
- ]);
+ );
+
+ onStart(); // We catch runtime errors using componentDidCatch which will trigger renderError
+
+ renderReactElement(false ? /*#__PURE__*/ undefined : elem, appElement);
+ return renderPromise;
}
- function Root(_ref7) {
- var { callback, children } = _ref7;
+ function Root(_ref9) {
+ var { callback, children } = _ref9;
// We use `useLayoutEffect` to guarantee the callback is executed
// as soon as React flushes the update.
@@ -1287,7 +1240,6 @@
var _interopRequireDefault = __webpack_require__("TqRt");
exports.__esModule = true;
- exports.createLink = createLink;
exports.default = void 0;
var _mitt = _interopRequireDefault(__webpack_require__("dZ6Y"));
@@ -1332,6 +1284,7 @@
: // IE 11, Edge 12+, nearly all evergreen
"prefetch";
var relPreload = hasRel("preload") ? "preload" : relPrefetch;
+ var relPreloadStyle = "fetch";
var hasNoModule = "noModule" in document.createElement("script");
var requestIdleCallback =
@@ -1351,27 +1304,19 @@
return route.replace(/\/$/, "");
}
- function createLink(href, rel, as, link) {
- link = document.createElement("link");
- return [
- link,
- new Promise((res, rej) => {
- // The order of property assignment here is intentional:
- if (as) link.as = as;
- link.rel = rel;
- link.crossOrigin = "anonymous";
- link.onload = res;
- link.onerror = rej; // `href` should always be last:
-
- link.href = href;
- })
- ];
- }
+ function appendLink(href, rel, as, link) {
+ return new Promise((res, rej) => {
+ link = document.createElement("link"); // The order of property assignment here is intentional:
- function appendLink(href, rel, as) {
- var [link, res] = createLink(href, rel, as);
- document.head.appendChild(link);
- return res;
+ if (as) link.as = as;
+ link.rel = rel;
+ link.crossOrigin = "anonymous";
+ link.onload = res;
+ link.onerror = rej; // `href` should always be last:
+
+ link.href = href;
+ document.head.appendChild(link);
+ });
}
function loadScript(url) {
@@ -1617,7 +1562,7 @@
// wait for these to resolve. To prevent an unhandled
// rejection, we swallow the error which is handled later in
// the rendering cycle (this is just a preload optimization).
- appendLink(d, relPreload, "style").catch(() => {
+ appendLink(d, relPreload, relPreloadStyle).catch(() => {
/* ignore preload error */
});
}
@@ -1666,15 +1611,32 @@
var check;
}
+ function fetchStyleSheet(href) {
+ return fetch(href).then(res => {
+ if (!res.ok) throw pageLoadError(href);
+ return res.text().then(text => ({
+ href,
+ text
+ }));
+ });
+ }
+
var promisedDeps = // Shared styles will already be on the page:
route === "/_app" || false // We use `style-loader` in development:
? Promise.resolve([])
: route === this.initialPage
? Promise.resolve(this.initialStyleSheets) // Tests that this does not block hydration:
: // test/integration/css-fixtures/hydrate-without-deps/
- this.getDependencies(route);
+ this.getDependencies(route)
+ .then(deps => deps.filter(d => d.endsWith(".css")))
+ .then((
+ cssFiles // These files should've already been fetched by now, so this
+ ) =>
+ // should resolve pretty much instantly.
+ Promise.all(cssFiles.map(d => fetchStyleSheet(d)))
+ );
promisedDeps.then(
- deps => register(deps.filter(d => d.endsWith(".css"))),
+ deps => register(deps),
error => {
this.pageCache[route] = {
error
@@ -1722,7 +1684,7 @@
appendLink(
url,
relPrefetch,
- url.endsWith(".css") ? "style" : "script"
+ url.endsWith(".css") ? relPreloadStyle : "script"
),
true &&
!isDependency &&Diff for index.html
@@ -4,9 +4,10 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta name="next-head-count" content="2" />
+ <noscript data-n-css="true"></noscript>
<link
rel="preload"
- href="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ href="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
as="script"
crossorigin="anonymous"
/>
@@ -81,13 +82,13 @@
src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
></script>
<script
- src="/_next/static/chunks/main-209a935a087118ae6828.js"
+ src="/_next/static/chunks/main-fe24fe70b35ca4db2791.js"
async=""
crossorigin="anonymous"
nomodule=""
></script>
<script
- src="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ src="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
async=""
crossorigin="anonymous"
type="module"Diff for link.html
@@ -4,9 +4,10 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta name="next-head-count" content="2" />
+ <noscript data-n-css="true"></noscript>
<link
rel="preload"
- href="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ href="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
as="script"
crossorigin="anonymous"
/>
@@ -86,13 +87,13 @@
src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
></script>
<script
- src="/_next/static/chunks/main-209a935a087118ae6828.js"
+ src="/_next/static/chunks/main-fe24fe70b35ca4db2791.js"
async=""
crossorigin="anonymous"
nomodule=""
></script>
<script
- src="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ src="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
async=""
crossorigin="anonymous"
type="module"Diff for withRouter.html
@@ -4,9 +4,10 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta name="next-head-count" content="2" />
+ <noscript data-n-css="true"></noscript>
<link
rel="preload"
- href="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ href="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
as="script"
crossorigin="anonymous"
/>
@@ -81,13 +82,13 @@
src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
></script>
<script
- src="/_next/static/chunks/main-209a935a087118ae6828.js"
+ src="/_next/static/chunks/main-fe24fe70b35ca4db2791.js"
async=""
crossorigin="anonymous"
nomodule=""
></script>
<script
- src="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ src="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
async=""
crossorigin="anonymous"
type="module"Serverless Mode (Increase detected ⚠️ )
General Overall decrease ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| buildDuration | 13.5s | 13.1s | -404ms |
| nodeModulesSize | 57.5 MB | 57.5 MB | -3.18 kB |
Client Bundles (main, webpack, commons) Overall decrease ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| 677f882d2ed8..7f47.js gzip | 10.3 kB | 10.3 kB | ✓ |
| framework.HASH.js gzip | 39 kB | 39 kB | ✓ |
| main-d4bab31..824e.js gzip | 7.34 kB | N/A | N/A |
| webpack-e067..f178.js gzip | 751 B | 751 B | ✓ |
| main-ff68bee..74d0.js gzip | N/A | 7.32 kB | N/A |
| Overall change | 57.4 kB | 57.3 kB | -20 B |
Client Bundles (main, webpack, commons) Modern Overall decrease ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| 677f882d2ed8..dule.js gzip | 6.15 kB | 6.15 kB | ✓ |
| framework.HA..dule.js gzip | 39 kB | 39 kB | ✓ |
| main-438d30a..dule.js gzip | 6.39 kB | N/A | N/A |
| webpack-07c5..dule.js gzip | 751 B | 751 B | ✓ |
| main-91bc16e..dule.js gzip | N/A | 6.39 kB | N/A |
| Overall change | 52.3 kB | 52.3 kB | -4 B |
Legacy Client Bundles (polyfills)
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| polyfills-4b..e242.js gzip | 31 kB | 31 kB | ✓ |
| Overall change | 31 kB | 31 kB | ✓ |
Client Pages
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _app-9a0b9e1..b37e.js gzip | 1.28 kB | 1.28 kB | ✓ |
| _error-28298..e0c9.js gzip | 3.44 kB | 3.44 kB | ✓ |
| hooks-89731c..c609.js gzip | 887 B | 887 B | ✓ |
| index-17468f..5d83.js gzip | 227 B | 227 B | ✓ |
| link-000f151..65d4.js gzip | 1.29 kB | 1.29 kB | ✓ |
| routerDirect..924c.js gzip | 284 B | 284 B | ✓ |
| withRouter-7..c13d.js gzip | 284 B | 284 B | ✓ |
| Overall change | 7.69 kB | 7.69 kB | ✓ |
Client Pages Modern
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _app-75d3a82..dule.js gzip | 625 B | 625 B | ✓ |
| _error-65c8a..dule.js gzip | 2.29 kB | 2.29 kB | ✓ |
| hooks-cbf13f..dule.js gzip | 387 B | 387 B | ✓ |
| index-b9a643..dule.js gzip | 226 B | 226 B | ✓ |
| link-4cfda7a..dule.js gzip | 1.26 kB | 1.26 kB | ✓ |
| routerDirect..dule.js gzip | 284 B | 284 B | ✓ |
| withRouter-f..dule.js gzip | 282 B | 282 B | ✓ |
| Overall change | 5.35 kB | 5.35 kB | ✓ |
Client Build Manifests
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _buildManifest.js gzip | 322 B | 322 B | ✓ |
| _buildManife..dule.js gzip | 330 B | 330 B | ✓ |
| Overall change | 652 B | 652 B | ✓ |
Serverless bundles Overall increase ⚠️
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _error.js | 1.03 MB | 1.03 MB | |
| 404.html | 4.18 kB | 4.22 kB | |
| hooks.html | 3.82 kB | 3.86 kB | |
| index.js | 1.03 MB | 1.03 MB | |
| link.js | 1.07 MB | 1.07 MB | |
| routerDirect.js | 1.07 MB | 1.07 MB | |
| withRouter.js | 1.07 MB | 1.07 MB | |
| Overall change | 5.28 MB | 5.28 MB |
Failing test suitesCommit: 393212f test/integration/css/test/index.test.js
Expand output● CSS Support › CSS Modules Composes Ordering › Production Mode › should have correct CSS injection order ● CSS Support › CSS Modules Composes Ordering › Production Mode › should have correct color on index page (on nav from index) |
Stats from current PRDefault Server Mode (Increase detected
|
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| buildDuration | 12.9s | 13s | |
| nodeModulesSize | 57.5 MB | 57.5 MB | -3.18 kB |
Page Load Tests Overall decrease ⚠️
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| / failed reqs | 0 | 0 | ✓ |
| / total time (seconds) | 2.335 | 2.449 | |
| / avg req/sec | 1070.73 | 1020.92 | |
| /error-in-render failed reqs | 0 | 0 | ✓ |
| /error-in-render total time (seconds) | 1.257 | 1.367 | |
| /error-in-render avg req/sec | 1989.55 | 1829.46 |
Client Bundles (main, webpack, commons) Overall decrease ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| 677f882d2ed8..7f47.js gzip | 10.3 kB | 10.3 kB | ✓ |
| framework.HASH.js gzip | 39 kB | 39 kB | ✓ |
| main-d4bab31..824e.js gzip | 7.34 kB | 7.32 kB | -20 B |
| webpack-e067..f178.js gzip | 751 B | 751 B | ✓ |
| Overall change | 57.4 kB | 57.3 kB | -20 B |
Client Bundles (main, webpack, commons) Modern Overall decrease ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| 677f882d2ed8..dule.js gzip | 6.15 kB | 6.15 kB | ✓ |
| framework.HA..dule.js gzip | 39 kB | 39 kB | ✓ |
| main-438d30a..dule.js gzip | 6.39 kB | 6.39 kB | -4 B |
| webpack-07c5..dule.js gzip | 751 B | 751 B | ✓ |
| Overall change | 52.3 kB | 52.3 kB | -4 B |
Legacy Client Bundles (polyfills)
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| polyfills-4b..e242.js gzip | 31 kB | 31 kB | ✓ |
| Overall change | 31 kB | 31 kB | ✓ |
Client Pages
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _app-9a0b9e1..b37e.js gzip | 1.28 kB | 1.28 kB | ✓ |
| _error-28298..e0c9.js gzip | 3.44 kB | 3.44 kB | ✓ |
| hooks-89731c..c609.js gzip | 887 B | 887 B | ✓ |
| index-17468f..5d83.js gzip | 227 B | 227 B | ✓ |
| link-000f151..65d4.js gzip | 1.29 kB | 1.29 kB | ✓ |
| routerDirect..924c.js gzip | 284 B | 284 B | ✓ |
| withRouter-7..c13d.js gzip | 284 B | 284 B | ✓ |
| Overall change | 7.69 kB | 7.69 kB | ✓ |
Client Pages Modern
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _app-75d3a82..dule.js gzip | 625 B | 625 B | ✓ |
| _error-65c8a..dule.js gzip | 2.29 kB | 2.29 kB | ✓ |
| hooks-cbf13f..dule.js gzip | 387 B | 387 B | ✓ |
| index-b9a643..dule.js gzip | 226 B | 226 B | ✓ |
| link-4cfda7a..dule.js gzip | 1.26 kB | 1.26 kB | ✓ |
| routerDirect..dule.js gzip | 284 B | 284 B | ✓ |
| withRouter-f..dule.js gzip | 282 B | 282 B | ✓ |
| Overall change | 5.35 kB | 5.35 kB | ✓ |
Client Build Manifests
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _buildManifest.js gzip | 322 B | 322 B | ✓ |
| _buildManife..dule.js gzip | 330 B | 330 B | ✓ |
| Overall change | 652 B | 652 B | ✓ |
Rendered Page Sizes Overall increase ⚠️
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| index.html gzip | 948 B | 970 B | |
| link.html gzip | 954 B | 977 B | |
| withRouter.html gzip | 940 B | 963 B | |
| Overall change | 2.84 kB | 2.91 kB |
Diffs
Diff for main-209a935..118ae6828.js
@@ -275,7 +275,7 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var _headManager = _interopRequireDefault(__webpack_require__("DqTX"));
- var _pageLoader = _interopRequireWildcard3(__webpack_require__("zmvN"));
+ var _pageLoader = _interopRequireDefault(__webpack_require__("zmvN"));
var _performanceRelayer = _interopRequireDefault(
__webpack_require__("bGXG")
@@ -319,14 +319,31 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
asPath = (0, _router.delBasePath)(asPath);
}
+ var looseToArray = function looseToArray(input) {
+ return [].slice.call(input);
+ };
+
var pageLoader = new _pageLoader["default"](
buildId,
prefix,
page,
- [].slice
- .call(document.querySelectorAll("link[rel=stylesheet][data-n-p]"))
- .map(function(e) {
- return e.getAttribute("href");
+ looseToArray(document.styleSheets)
+ .filter(function(el) {
+ return (
+ el.ownerNode &&
+ el.ownerNode.tagName === "LINK" &&
+ el.ownerNode.hasAttribute("data-n-p")
+ );
+ })
+ .map(function(sheet) {
+ return {
+ href: sheet.ownerNode.getAttribute("href"),
+ text: looseToArray(sheet.cssRules)
+ .map(function(r) {
+ return r.cssText;
+ })
+ .join("")
+ };
})
);
@@ -967,8 +984,8 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
); // lastAppProps has to be set before ReactDom.render to account for ReactDom throwing an error.
lastAppProps = appProps;
+ var canceled = false;
var resolvePromise;
- var renderPromiseReject;
var renderPromise = new Promise(function(resolve, reject) {
if (_lastRenderReject) {
_lastRenderReject();
@@ -979,17 +996,15 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
resolve();
};
- renderPromiseReject = _lastRenderReject = function lastRenderReject() {
+ _lastRenderReject = function lastRenderReject() {
+ canceled = true;
_lastRenderReject = null;
var error = new Error("Cancel rendering route");
error.cancelled = true;
reject(error);
};
- }); // TODO: consider replacing this with real `<style>` tags that have
- // plain-text CSS content that's provided by RouteInfo. That'd remove the
- // need for the staging `<link>`s and the ability for CSS to be missing at
- // this phase, allowing us to remove the error handling flow that reloads the
- // page.
+ }); // This function has a return type to ensure it doesn't start returning a
+ // Promise. It should remain synchronous.
function onStart() {
if (
@@ -999,82 +1014,30 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
// unless we're in production:
false
) {
- return Promise.resolve([]);
- } // Clean up previous render if canceling:
+ return false;
+ }
- [].slice
- .call(
- document.querySelectorAll(
- "link[data-n-staging], noscript[data-n-staging]"
- )
- )
- .forEach(function(el) {
- el.parentNode.removeChild(el);
- });
- var referenceNodes = [].slice.call(
- document.querySelectorAll("link[data-n-g], link[data-n-p]")
+ var currentStyleTags = looseToArray(
+ document.querySelectorAll("style[data-n-href]")
);
- var referenceHrefs = new Set(
- referenceNodes.map(function(e) {
- return e.getAttribute("href");
+ var currentHrefs = new Set(
+ currentStyleTags.map(function(tag) {
+ return tag.getAttribute("data-n-href");
})
);
- var referenceNode = referenceNodes[referenceNodes.length - 1];
- var required = styleSheets.map(function(href) {
- var newNode, promise;
- var existingLink = referenceHrefs.has(href);
-
- if (existingLink) {
- newNode = document.createElement("noscript");
- newNode.setAttribute("data-n-staging", href);
- promise = true;
- } else {
- var _ref9 = (0, _pageLoader.createLink)(href, "stylesheet"),
- _ref10 = _slicedToArray(_ref9, 2),
- link = _ref10[0],
- onload = _ref10[1];
-
- link.setAttribute("data-n-staging", ""); // Media `none` does not work in Firefox, so `print` is more
- // cross-browser. Since this is so short lived we don't have to worry
- // about style thrashing in a print view (where no routing is going to be
- // happening anyway).
-
- link.setAttribute("media", "print");
- newNode = link;
- promise = onload;
- }
-
- if (referenceNode) {
- referenceNode.parentNode.insertBefore(
- newNode,
- referenceNode.nextSibling
- );
- referenceNode = newNode;
- } else {
- document.head.appendChild(newNode);
+ styleSheets.forEach(function(_ref9) {
+ var href = _ref9.href,
+ text = _ref9.text;
+
+ if (!currentHrefs.has(href)) {
+ var styleTag = document.createElement("style");
+ styleTag.setAttribute("data-n-href", href);
+ styleTag.setAttribute("media", "x");
+ document.head.appendChild(styleTag);
+ styleTag.appendChild(document.createTextNode(text));
}
-
- return promise;
- });
- return Promise.all(required)["catch"](function() {
- // This is too late in the rendering lifecycle to use the existing
- // `PAGE_LOAD_ERROR` flow (via `handleRouteInfoError`).
- // To match that behavior, we request the page to reload with the current
- // asPath. This is already set at this phase since we "committed" to the
- // render.
- // This handles an edge case where a new deployment is rolled during
- // client-side transition and the CSS assets are missing.
- // This prevents:
- // 1. An unstyled page from being rendered (old behavior)
- // 2. The `/_error` page being rendered (we want to reload for the new
- // deployment)
- window.location.href = router.asPath; // Instead of rethrowing the CSS loading error, we give a promise that
- // won't resolve. This pauses the rendering process until the page
- // reloads. Re-throwing the error could result in a flash of error page.
- // throw cssLoadingError
-
- return new Promise(function() {});
});
+ return true;
}
function onCommit() {
@@ -1083,45 +1046,60 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
// unless we're in production:
true && // We can skip this during hydration. Running it wont cause any harm, but
// we may as well save the CPU cycles:
- !isInitialRender && // Ensure this render commit owns the currently staged stylesheets:
- renderPromiseReject === _lastRenderReject
+ !isInitialRender && // Ensure this render was not canceled
+ !canceled
) {
- // Remove or relocate old stylesheets:
- var relocatePlaceholders = [].slice.call(
- document.querySelectorAll("noscript[data-n-staging]")
+ var desiredHrefs = new Set(
+ styleSheets.map(function(s) {
+ return s.href;
+ })
);
- var relocateHrefs = relocatePlaceholders.map(function(e) {
- return e.getAttribute("data-n-staging");
- });
- [].slice
- .call(document.querySelectorAll("link[data-n-p]"))
- .forEach(function(el) {
- var currentHref = el.getAttribute("href");
- var relocateIndex = relocateHrefs.indexOf(currentHref);
-
- if (relocateIndex !== -1) {
- var _placeholderElement$p;
-
- var placeholderElement = relocatePlaceholders[relocateIndex];
- (_placeholderElement$p = placeholderElement.parentNode) ==
- null
- ? void 0
- : _placeholderElement$p.replaceChild(
- el,
- placeholderElement
- );
- } else {
- el.parentNode.removeChild(el);
+ var currentStyleTags = looseToArray(
+ document.querySelectorAll("style[data-n-href]")
+ );
+ var currentHrefs = currentStyleTags.map(function(tag) {
+ return tag.getAttribute("data-n-href");
+ }); // Toggle `<style>` tags on or off depending on if they're needed:
+
+ for (var idx = 0; idx < currentHrefs.length; ++idx) {
+ if (desiredHrefs.has(currentHrefs[idx])) {
+ currentStyleTags[idx].removeAttribute("media");
+ } else {
+ currentStyleTags[idx].setAttribute("media", "x");
+ }
+ } // Reorder styles into intended order:
+
+ var referenceNode = document.querySelector("noscript[data-n-css]");
+
+ if (
+ // This should be an invariant:
+ referenceNode
+ ) {
+ styleSheets.forEach(function(_ref10) {
+ var href = _ref10.href;
+ var targetTag = document.querySelector(
+ 'style[data-n-href="'.concat(href, '"]')
+ );
+
+ if (
+ // This should be an invariant:
+ targetTag
+ ) {
+ referenceNode.parentNode.insertBefore(
+ targetTag,
+ referenceNode.nextSibling
+ );
+ referenceNode = targetTag;
}
- }); // Activate new stylesheets:
- [].slice
- .call(document.querySelectorAll("link[data-n-staging]"))
- .forEach(function(el) {
- el.removeAttribute("data-n-staging");
- el.removeAttribute("media");
- el.setAttribute("data-n-p", "");
- }); // Force browser to recompute layout, which prevents a flash of unstyled
- // content:
+ });
+ } // Finally, clean up server rendered stylesheets:
+
+ looseToArray(document.querySelectorAll("link[data-n-p]")).forEach(
+ function(el) {
+ el.parentNode.removeChild(el);
+ }
+ ); // Force browser to recompute layout, which should prevent a flash of
+ // unstyled content:
getComputedStyle(document.body, "height");
}
@@ -1139,29 +1117,12 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
null,
/*#__PURE__*/ _react["default"].createElement(App, appProps)
)
- ); // We catch runtime errors using componentDidCatch which will trigger renderError
-
- return Promise.race([
- // Download required CSS assets first:
- onStart()
- .then(function() {
- // Ensure a new render has not been started:
- if (renderPromiseReject === _lastRenderReject) {
- // Queue rendering:
- renderReactElement(
- false ? /*#__PURE__*/ undefined : elem,
- appElement
- );
- }
- })
- .then(function() {
- return (
- // Wait for rendering to complete:
- renderPromise
- );
- }), // Bail early on route cancelation (rejection):
- renderPromise
- ]);
+ );
+
+ onStart(); // We catch runtime errors using componentDidCatch which will trigger renderError
+
+ renderReactElement(false ? /*#__PURE__*/ undefined : elem, appElement);
+ return renderPromise;
}
function Root(_ref11) {
@@ -1617,12 +1578,9 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var _createClass = __webpack_require__("W8MJ");
- var _slicedToArray = __webpack_require__("J4zp");
-
var _interopRequireDefault = __webpack_require__("TqRt");
exports.__esModule = true;
- exports.createLink = createLink;
exports["default"] = void 0;
var _mitt = _interopRequireDefault(__webpack_require__("dZ6Y"));
@@ -1667,6 +1625,7 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
: // IE 11, Edge 12+, nearly all evergreen
"prefetch";
var relPreload = hasRel("preload") ? "preload" : relPrefetch;
+ var relPreloadStyle = "fetch";
var hasNoModule = "noModule" in document.createElement("script");
var requestIdleCallback =
@@ -1686,31 +1645,19 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
return route.replace(/\/$/, "");
}
- function createLink(href, rel, as, link) {
- link = document.createElement("link");
- return [
- link,
- new Promise(function(res, rej) {
- // The order of property assignment here is intentional:
- if (as) link.as = as;
- link.rel = rel;
- link.crossOrigin = "anonymous";
- link.onload = res;
- link.onerror = rej; // `href` should always be last:
-
- link.href = href;
- })
- ];
- }
+ function appendLink(href, rel, as, link) {
+ return new Promise(function(res, rej) {
+ link = document.createElement("link"); // The order of property assignment here is intentional:
- function appendLink(href, rel, as) {
- var _createLink = createLink(href, rel, as),
- _createLink2 = _slicedToArray(_createLink, 2),
- link = _createLink2[0],
- res = _createLink2[1];
+ if (as) link.as = as;
+ link.rel = rel;
+ link.crossOrigin = "anonymous";
+ link.onload = res;
+ link.onerror = rej; // `href` should always be last:
- document.head.appendChild(link);
- return res;
+ link.href = href;
+ document.head.appendChild(link);
+ });
}
function loadScript(url) {
@@ -2007,7 +1954,7 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
// wait for these to resolve. To prevent an unhandled
// rejection, we swallow the error which is handled later in
// the rendering cycle (this is just a preload optimization).
- appendLink(d, relPreload, "style")["catch"](
+ appendLink(d, relPreload, relPreloadStyle)["catch"](
function() {
/* ignore preload error */
}
@@ -2064,20 +2011,44 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var check;
}
+ function fetchStyleSheet(href) {
+ return fetch(href).then(function(res) {
+ if (!res.ok) throw pageLoadError(href);
+ return res.text().then(function(text) {
+ return {
+ href: href,
+ text: text
+ };
+ });
+ });
+ }
+
var promisedDeps = // Shared styles will already be on the page:
route === "/_app" || false // We use `style-loader` in development:
? Promise.resolve([])
: route === this.initialPage
? Promise.resolve(this.initialStyleSheets) // Tests that this does not block hydration:
: // test/integration/css-fixtures/hydrate-without-deps/
- this.getDependencies(route);
+ this.getDependencies(route)
+ .then(function(deps) {
+ return deps.filter(function(d) {
+ return d.endsWith(".css");
+ });
+ })
+ .then(function(cssFiles) {
+ return (
+ // These files should've already been fetched by now, so this
+ // should resolve pretty much instantly.
+ Promise.all(
+ cssFiles.map(function(d) {
+ return fetchStyleSheet(d);
+ })
+ )
+ );
+ });
promisedDeps.then(
function(deps) {
- return register(
- deps.filter(function(d) {
- return d.endsWith(".css");
- })
- );
+ return register(deps);
},
function(error) {
_this5.pageCache[route] = {
@@ -2133,7 +2104,7 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
appendLink(
url,
relPrefetch,
- url.endsWith(".css") ? "style" : "script"
+ url.endsWith(".css") ? relPreloadStyle : "script"
),
true &&
!isDependency &&Diff for main-be61079..e7.module.js
@@ -193,7 +193,7 @@
var _headManager = _interopRequireDefault(__webpack_require__("DqTX"));
- var _pageLoader = _interopRequireWildcard3(__webpack_require__("zmvN"));
+ var _pageLoader = _interopRequireDefault(__webpack_require__("zmvN"));
var _performanceRelayer = _interopRequireDefault(
__webpack_require__("bGXG")
@@ -239,13 +239,25 @@
asPath = (0, _router.delBasePath)(asPath);
}
+ var looseToArray = input => [].slice.call(input);
+
var pageLoader = new _pageLoader.default(
buildId,
prefix,
page,
- [].slice
- .call(document.querySelectorAll("link[rel=stylesheet][data-n-p]"))
- .map(e => e.getAttribute("href"))
+ looseToArray(document.styleSheets)
+ .filter(
+ el =>
+ el.ownerNode &&
+ el.ownerNode.tagName === "LINK" &&
+ el.ownerNode.hasAttribute("data-n-p")
+ )
+ .map(sheet => ({
+ href: sheet.ownerNode.getAttribute("href"),
+ text: looseToArray(sheet.cssRules)
+ .map(r => r.cssText)
+ .join("")
+ }))
);
var register = _ref => {
@@ -702,8 +714,8 @@
); // lastAppProps has to be set before ReactDom.render to account for ReactDom throwing an error.
lastAppProps = appProps;
+ var canceled = false;
var resolvePromise;
- var renderPromiseReject;
var renderPromise = new Promise((resolve, reject) => {
if (lastRenderReject) {
lastRenderReject();
@@ -714,17 +726,15 @@
resolve();
};
- renderPromiseReject = lastRenderReject = () => {
+ lastRenderReject = () => {
+ canceled = true;
lastRenderReject = null;
var error = new Error("Cancel rendering route");
error.cancelled = true;
reject(error);
};
- }); // TODO: consider replacing this with real `<style>` tags that have
- // plain-text CSS content that's provided by RouteInfo. That'd remove the
- // need for the staging `<link>`s and the ability for CSS to be missing at
- // this phase, allowing us to remove the error handling flow that reloads the
- // page.
+ }); // This function has a return type to ensure it doesn't start returning a
+ // Promise. It should remain synchronous.
function onStart() {
if (
@@ -734,79 +744,27 @@
// unless we're in production:
false
) {
- return Promise.resolve([]);
- } // Clean up previous render if canceling:
+ return false;
+ }
- [].slice
- .call(
- document.querySelectorAll(
- "link[data-n-staging], noscript[data-n-staging]"
- )
- )
- .forEach(el => {
- el.parentNode.removeChild(el);
- });
- var referenceNodes = [].slice.call(
- document.querySelectorAll("link[data-n-g], link[data-n-p]")
+ var currentStyleTags = looseToArray(
+ document.querySelectorAll("style[data-n-href]")
);
- var referenceHrefs = new Set(
- referenceNodes.map(e => e.getAttribute("href"))
+ var currentHrefs = new Set(
+ currentStyleTags.map(tag => tag.getAttribute("data-n-href"))
);
- var referenceNode = referenceNodes[referenceNodes.length - 1];
- var required = styleSheets.map(href => {
- var newNode, promise;
- var existingLink = referenceHrefs.has(href);
-
- if (existingLink) {
- newNode = document.createElement("noscript");
- newNode.setAttribute("data-n-staging", href);
- promise = true;
- } else {
- var [link, onload] = (0, _pageLoader.createLink)(
- href,
- "stylesheet"
- );
- link.setAttribute("data-n-staging", ""); // Media `none` does not work in Firefox, so `print` is more
- // cross-browser. Since this is so short lived we don't have to worry
- // about style thrashing in a print view (where no routing is going to be
- // happening anyway).
-
- link.setAttribute("media", "print");
- newNode = link;
- promise = onload;
- }
-
- if (referenceNode) {
- referenceNode.parentNode.insertBefore(
- newNode,
- referenceNode.nextSibling
- );
- referenceNode = newNode;
- } else {
- document.head.appendChild(newNode);
+ styleSheets.forEach(_ref7 => {
+ var { href, text } = _ref7;
+
+ if (!currentHrefs.has(href)) {
+ var styleTag = document.createElement("style");
+ styleTag.setAttribute("data-n-href", href);
+ styleTag.setAttribute("media", "x");
+ document.head.appendChild(styleTag);
+ styleTag.appendChild(document.createTextNode(text));
}
-
- return promise;
- });
- return Promise.all(required).catch(() => {
- // This is too late in the rendering lifecycle to use the existing
- // `PAGE_LOAD_ERROR` flow (via `handleRouteInfoError`).
- // To match that behavior, we request the page to reload with the current
- // asPath. This is already set at this phase since we "committed" to the
- // render.
- // This handles an edge case where a new deployment is rolled during
- // client-side transition and the CSS assets are missing.
- // This prevents:
- // 1. An unstyled page from being rendered (old behavior)
- // 2. The `/_error` page being rendered (we want to reload for the new
- // deployment)
- window.location.href = router.asPath; // Instead of rethrowing the CSS loading error, we give a promise that
- // won't resolve. This pauses the rendering process until the page
- // reloads. Re-throwing the error could result in a flash of error page.
- // throw cssLoadingError
-
- return new Promise(() => {});
});
+ return true;
}
function onCommit() {
@@ -815,45 +773,56 @@
// unless we're in production:
true && // We can skip this during hydration. Running it wont cause any harm, but
// we may as well save the CPU cycles:
- !isInitialRender && // Ensure this render commit owns the currently staged stylesheets:
- renderPromiseReject === lastRenderReject
+ !isInitialRender && // Ensure this render was not canceled
+ !canceled
) {
- // Remove or relocate old stylesheets:
- var relocatePlaceholders = [].slice.call(
- document.querySelectorAll("noscript[data-n-staging]")
+ var desiredHrefs = new Set(styleSheets.map(s => s.href));
+ var currentStyleTags = looseToArray(
+ document.querySelectorAll("style[data-n-href]")
);
- var relocateHrefs = relocatePlaceholders.map(e =>
- e.getAttribute("data-n-staging")
- );
- [].slice
- .call(document.querySelectorAll("link[data-n-p]"))
- .forEach(el => {
- var currentHref = el.getAttribute("href");
- var relocateIndex = relocateHrefs.indexOf(currentHref);
-
- if (relocateIndex !== -1) {
- var _placeholderElement$p;
-
- var placeholderElement = relocatePlaceholders[relocateIndex];
- (_placeholderElement$p = placeholderElement.parentNode) ==
- null
- ? void 0
- : _placeholderElement$p.replaceChild(
- el,
- placeholderElement
- );
- } else {
- el.parentNode.removeChild(el);
+ var currentHrefs = currentStyleTags.map(tag =>
+ tag.getAttribute("data-n-href")
+ ); // Toggle `<style>` tags on or off depending on if they're needed:
+
+ for (var idx = 0; idx < currentHrefs.length; ++idx) {
+ if (desiredHrefs.has(currentHrefs[idx])) {
+ currentStyleTags[idx].removeAttribute("media");
+ } else {
+ currentStyleTags[idx].setAttribute("media", "x");
+ }
+ } // Reorder styles into intended order:
+
+ var referenceNode = document.querySelector("noscript[data-n-css]");
+
+ if (
+ // This should be an invariant:
+ referenceNode
+ ) {
+ styleSheets.forEach(_ref8 => {
+ var { href } = _ref8;
+ var targetTag = document.querySelector(
+ 'style[data-n-href="'.concat(href, '"]')
+ );
+
+ if (
+ // This should be an invariant:
+ targetTag
+ ) {
+ referenceNode.parentNode.insertBefore(
+ targetTag,
+ referenceNode.nextSibling
+ );
+ referenceNode = targetTag;
}
- }); // Activate new stylesheets:
- [].slice
- .call(document.querySelectorAll("link[data-n-staging]"))
- .forEach(el => {
- el.removeAttribute("data-n-staging");
- el.removeAttribute("media");
- el.setAttribute("data-n-p", "");
- }); // Force browser to recompute layout, which prevents a flash of unstyled
- // content:
+ });
+ } // Finally, clean up server rendered stylesheets:
+
+ looseToArray(document.querySelectorAll("link[data-n-p]")).forEach(
+ el => {
+ el.parentNode.removeChild(el);
+ }
+ ); // Force browser to recompute layout, which should prevent a flash of
+ // unstyled content:
getComputedStyle(document.body, "height");
}
@@ -871,32 +840,16 @@
null,
/*#__PURE__*/ _react.default.createElement(App, appProps)
)
- ); // We catch runtime errors using componentDidCatch which will trigger renderError
-
- return Promise.race([
- // Download required CSS assets first:
- onStart()
- .then(() => {
- // Ensure a new render has not been started:
- if (renderPromiseReject === lastRenderReject) {
- // Queue rendering:
- renderReactElement(
- false ? /*#__PURE__*/ undefined : elem,
- appElement
- );
- }
- })
- .then(
- () =>
- // Wait for rendering to complete:
- renderPromise
- ), // Bail early on route cancelation (rejection):
- renderPromise
- ]);
+ );
+
+ onStart(); // We catch runtime errors using componentDidCatch which will trigger renderError
+
+ renderReactElement(false ? /*#__PURE__*/ undefined : elem, appElement);
+ return renderPromise;
}
- function Root(_ref7) {
- var { callback, children } = _ref7;
+ function Root(_ref9) {
+ var { callback, children } = _ref9;
// We use `useLayoutEffect` to guarantee the callback is executed
// as soon as React flushes the update.
@@ -1287,7 +1240,6 @@
var _interopRequireDefault = __webpack_require__("TqRt");
exports.__esModule = true;
- exports.createLink = createLink;
exports.default = void 0;
var _mitt = _interopRequireDefault(__webpack_require__("dZ6Y"));
@@ -1332,6 +1284,7 @@
: // IE 11, Edge 12+, nearly all evergreen
"prefetch";
var relPreload = hasRel("preload") ? "preload" : relPrefetch;
+ var relPreloadStyle = "fetch";
var hasNoModule = "noModule" in document.createElement("script");
var requestIdleCallback =
@@ -1351,27 +1304,19 @@
return route.replace(/\/$/, "");
}
- function createLink(href, rel, as, link) {
- link = document.createElement("link");
- return [
- link,
- new Promise((res, rej) => {
- // The order of property assignment here is intentional:
- if (as) link.as = as;
- link.rel = rel;
- link.crossOrigin = "anonymous";
- link.onload = res;
- link.onerror = rej; // `href` should always be last:
-
- link.href = href;
- })
- ];
- }
+ function appendLink(href, rel, as, link) {
+ return new Promise((res, rej) => {
+ link = document.createElement("link"); // The order of property assignment here is intentional:
- function appendLink(href, rel, as) {
- var [link, res] = createLink(href, rel, as);
- document.head.appendChild(link);
- return res;
+ if (as) link.as = as;
+ link.rel = rel;
+ link.crossOrigin = "anonymous";
+ link.onload = res;
+ link.onerror = rej; // `href` should always be last:
+
+ link.href = href;
+ document.head.appendChild(link);
+ });
}
function loadScript(url) {
@@ -1617,7 +1562,7 @@
// wait for these to resolve. To prevent an unhandled
// rejection, we swallow the error which is handled later in
// the rendering cycle (this is just a preload optimization).
- appendLink(d, relPreload, "style").catch(() => {
+ appendLink(d, relPreload, relPreloadStyle).catch(() => {
/* ignore preload error */
});
}
@@ -1666,15 +1611,32 @@
var check;
}
+ function fetchStyleSheet(href) {
+ return fetch(href).then(res => {
+ if (!res.ok) throw pageLoadError(href);
+ return res.text().then(text => ({
+ href,
+ text
+ }));
+ });
+ }
+
var promisedDeps = // Shared styles will already be on the page:
route === "/_app" || false // We use `style-loader` in development:
? Promise.resolve([])
: route === this.initialPage
? Promise.resolve(this.initialStyleSheets) // Tests that this does not block hydration:
: // test/integration/css-fixtures/hydrate-without-deps/
- this.getDependencies(route);
+ this.getDependencies(route)
+ .then(deps => deps.filter(d => d.endsWith(".css")))
+ .then((
+ cssFiles // These files should've already been fetched by now, so this
+ ) =>
+ // should resolve pretty much instantly.
+ Promise.all(cssFiles.map(d => fetchStyleSheet(d)))
+ );
promisedDeps.then(
- deps => register(deps.filter(d => d.endsWith(".css"))),
+ deps => register(deps),
error => {
this.pageCache[route] = {
error
@@ -1722,7 +1684,7 @@
appendLink(
url,
relPrefetch,
- url.endsWith(".css") ? "style" : "script"
+ url.endsWith(".css") ? relPreloadStyle : "script"
),
true &&
!isDependency &&Diff for index.html
@@ -4,9 +4,10 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta name="next-head-count" content="2" />
+ <noscript data-n-css="true"></noscript>
<link
rel="preload"
- href="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ href="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
as="script"
crossorigin="anonymous"
/>
@@ -81,13 +82,13 @@
src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
></script>
<script
- src="/_next/static/chunks/main-209a935a087118ae6828.js"
+ src="/_next/static/chunks/main-fe24fe70b35ca4db2791.js"
async=""
crossorigin="anonymous"
nomodule=""
></script>
<script
- src="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ src="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
async=""
crossorigin="anonymous"
type="module"Diff for link.html
@@ -4,9 +4,10 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta name="next-head-count" content="2" />
+ <noscript data-n-css="true"></noscript>
<link
rel="preload"
- href="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ href="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
as="script"
crossorigin="anonymous"
/>
@@ -86,13 +87,13 @@
src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
></script>
<script
- src="/_next/static/chunks/main-209a935a087118ae6828.js"
+ src="/_next/static/chunks/main-fe24fe70b35ca4db2791.js"
async=""
crossorigin="anonymous"
nomodule=""
></script>
<script
- src="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ src="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
async=""
crossorigin="anonymous"
type="module"Diff for withRouter.html
@@ -4,9 +4,10 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta name="next-head-count" content="2" />
+ <noscript data-n-css="true"></noscript>
<link
rel="preload"
- href="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ href="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
as="script"
crossorigin="anonymous"
/>
@@ -81,13 +82,13 @@
src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
></script>
<script
- src="/_next/static/chunks/main-209a935a087118ae6828.js"
+ src="/_next/static/chunks/main-fe24fe70b35ca4db2791.js"
async=""
crossorigin="anonymous"
nomodule=""
></script>
<script
- src="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ src="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
async=""
crossorigin="anonymous"
type="module"Serverless Mode (Increase detected ⚠️ )
General Overall decrease ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| buildDuration | 14.4s | 14.4s | |
| nodeModulesSize | 57.5 MB | 57.5 MB | -3.18 kB |
Client Bundles (main, webpack, commons) Overall decrease ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| 677f882d2ed8..7f47.js gzip | 10.3 kB | 10.3 kB | ✓ |
| framework.HASH.js gzip | 39 kB | 39 kB | ✓ |
| main-d4bab31..824e.js gzip | 7.34 kB | N/A | N/A |
| webpack-e067..f178.js gzip | 751 B | 751 B | ✓ |
| main-ff68bee..74d0.js gzip | N/A | 7.32 kB | N/A |
| Overall change | 57.4 kB | 57.3 kB | -20 B |
Client Bundles (main, webpack, commons) Modern Overall decrease ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| 677f882d2ed8..dule.js gzip | 6.15 kB | 6.15 kB | ✓ |
| framework.HA..dule.js gzip | 39 kB | 39 kB | ✓ |
| main-438d30a..dule.js gzip | 6.39 kB | N/A | N/A |
| webpack-07c5..dule.js gzip | 751 B | 751 B | ✓ |
| main-91bc16e..dule.js gzip | N/A | 6.39 kB | N/A |
| Overall change | 52.3 kB | 52.3 kB | -4 B |
Legacy Client Bundles (polyfills)
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| polyfills-4b..e242.js gzip | 31 kB | 31 kB | ✓ |
| Overall change | 31 kB | 31 kB | ✓ |
Client Pages
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _app-9a0b9e1..b37e.js gzip | 1.28 kB | 1.28 kB | ✓ |
| _error-28298..e0c9.js gzip | 3.44 kB | 3.44 kB | ✓ |
| hooks-89731c..c609.js gzip | 887 B | 887 B | ✓ |
| index-17468f..5d83.js gzip | 227 B | 227 B | ✓ |
| link-000f151..65d4.js gzip | 1.29 kB | 1.29 kB | ✓ |
| routerDirect..924c.js gzip | 284 B | 284 B | ✓ |
| withRouter-7..c13d.js gzip | 284 B | 284 B | ✓ |
| Overall change | 7.69 kB | 7.69 kB | ✓ |
Client Pages Modern
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _app-75d3a82..dule.js gzip | 625 B | 625 B | ✓ |
| _error-65c8a..dule.js gzip | 2.29 kB | 2.29 kB | ✓ |
| hooks-cbf13f..dule.js gzip | 387 B | 387 B | ✓ |
| index-b9a643..dule.js gzip | 226 B | 226 B | ✓ |
| link-4cfda7a..dule.js gzip | 1.26 kB | 1.26 kB | ✓ |
| routerDirect..dule.js gzip | 284 B | 284 B | ✓ |
| withRouter-f..dule.js gzip | 282 B | 282 B | ✓ |
| Overall change | 5.35 kB | 5.35 kB | ✓ |
Client Build Manifests
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _buildManifest.js gzip | 322 B | 322 B | ✓ |
| _buildManife..dule.js gzip | 330 B | 330 B | ✓ |
| Overall change | 652 B | 652 B | ✓ |
Serverless bundles Overall increase ⚠️
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _error.js | 1.03 MB | 1.03 MB | |
| 404.html | 4.18 kB | 4.22 kB | |
| hooks.html | 3.82 kB | 3.86 kB | |
| index.js | 1.03 MB | 1.03 MB | |
| link.js | 1.07 MB | 1.07 MB | |
| routerDirect.js | 1.07 MB | 1.07 MB | |
| withRouter.js | 1.07 MB | 1.07 MB | |
| Overall change | 5.28 MB | 5.28 MB |
Stats from current PRDefault Server Mode (Increase detected
|
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| buildDuration | 11.7s | 12.6s | |
| nodeModulesSize | 57.5 MB | 57.5 MB | -3.18 kB |
Page Load Tests Overall increase ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| / failed reqs | 0 | 0 | ✓ |
| / total time (seconds) | 2.242 | 2.222 | -0.02 |
| / avg req/sec | 1115.07 | 1125.32 | +10.25 |
| /error-in-render failed reqs | 0 | 0 | ✓ |
| /error-in-render total time (seconds) | 1.201 | 1.186 | -0.02 |
| /error-in-render avg req/sec | 2082.32 | 2108.46 | +26.14 |
Client Bundles (main, webpack, commons) Overall decrease ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| 677f882d2ed8..7f47.js gzip | 10.3 kB | 10.3 kB | ✓ |
| framework.HASH.js gzip | 39 kB | 39 kB | ✓ |
| main-d4bab31..824e.js gzip | 7.34 kB | 7.32 kB | -20 B |
| webpack-e067..f178.js gzip | 751 B | 751 B | ✓ |
| Overall change | 57.4 kB | 57.3 kB | -20 B |
Client Bundles (main, webpack, commons) Modern Overall decrease ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| 677f882d2ed8..dule.js gzip | 6.15 kB | 6.15 kB | ✓ |
| framework.HA..dule.js gzip | 39 kB | 39 kB | ✓ |
| main-438d30a..dule.js gzip | 6.39 kB | 6.39 kB | -4 B |
| webpack-07c5..dule.js gzip | 751 B | 751 B | ✓ |
| Overall change | 52.3 kB | 52.3 kB | -4 B |
Legacy Client Bundles (polyfills)
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| polyfills-4b..e242.js gzip | 31 kB | 31 kB | ✓ |
| Overall change | 31 kB | 31 kB | ✓ |
Client Pages
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _app-9a0b9e1..b37e.js gzip | 1.28 kB | 1.28 kB | ✓ |
| _error-28298..e0c9.js gzip | 3.44 kB | 3.44 kB | ✓ |
| hooks-89731c..c609.js gzip | 887 B | 887 B | ✓ |
| index-17468f..5d83.js gzip | 227 B | 227 B | ✓ |
| link-000f151..65d4.js gzip | 1.29 kB | 1.29 kB | ✓ |
| routerDirect..924c.js gzip | 284 B | 284 B | ✓ |
| withRouter-7..c13d.js gzip | 284 B | 284 B | ✓ |
| Overall change | 7.69 kB | 7.69 kB | ✓ |
Client Pages Modern
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _app-75d3a82..dule.js gzip | 625 B | 625 B | ✓ |
| _error-65c8a..dule.js gzip | 2.29 kB | 2.29 kB | ✓ |
| hooks-cbf13f..dule.js gzip | 387 B | 387 B | ✓ |
| index-b9a643..dule.js gzip | 226 B | 226 B | ✓ |
| link-4cfda7a..dule.js gzip | 1.26 kB | 1.26 kB | ✓ |
| routerDirect..dule.js gzip | 284 B | 284 B | ✓ |
| withRouter-f..dule.js gzip | 282 B | 282 B | ✓ |
| Overall change | 5.35 kB | 5.35 kB | ✓ |
Client Build Manifests
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _buildManifest.js gzip | 322 B | 322 B | ✓ |
| _buildManife..dule.js gzip | 330 B | 330 B | ✓ |
| Overall change | 652 B | 652 B | ✓ |
Rendered Page Sizes Overall increase ⚠️
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| index.html gzip | 948 B | 970 B | |
| link.html gzip | 954 B | 977 B | |
| withRouter.html gzip | 940 B | 963 B | |
| Overall change | 2.84 kB | 2.91 kB |
Diffs
Diff for main-209a935..118ae6828.js
@@ -275,7 +275,7 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var _headManager = _interopRequireDefault(__webpack_require__("DqTX"));
- var _pageLoader = _interopRequireWildcard3(__webpack_require__("zmvN"));
+ var _pageLoader = _interopRequireDefault(__webpack_require__("zmvN"));
var _performanceRelayer = _interopRequireDefault(
__webpack_require__("bGXG")
@@ -319,14 +319,31 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
asPath = (0, _router.delBasePath)(asPath);
}
+ var looseToArray = function looseToArray(input) {
+ return [].slice.call(input);
+ };
+
var pageLoader = new _pageLoader["default"](
buildId,
prefix,
page,
- [].slice
- .call(document.querySelectorAll("link[rel=stylesheet][data-n-p]"))
- .map(function(e) {
- return e.getAttribute("href");
+ looseToArray(document.styleSheets)
+ .filter(function(el) {
+ return (
+ el.ownerNode &&
+ el.ownerNode.tagName === "LINK" &&
+ el.ownerNode.hasAttribute("data-n-p")
+ );
+ })
+ .map(function(sheet) {
+ return {
+ href: sheet.ownerNode.getAttribute("href"),
+ text: looseToArray(sheet.cssRules)
+ .map(function(r) {
+ return r.cssText;
+ })
+ .join("")
+ };
})
);
@@ -967,8 +984,8 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
); // lastAppProps has to be set before ReactDom.render to account for ReactDom throwing an error.
lastAppProps = appProps;
+ var canceled = false;
var resolvePromise;
- var renderPromiseReject;
var renderPromise = new Promise(function(resolve, reject) {
if (_lastRenderReject) {
_lastRenderReject();
@@ -979,17 +996,15 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
resolve();
};
- renderPromiseReject = _lastRenderReject = function lastRenderReject() {
+ _lastRenderReject = function lastRenderReject() {
+ canceled = true;
_lastRenderReject = null;
var error = new Error("Cancel rendering route");
error.cancelled = true;
reject(error);
};
- }); // TODO: consider replacing this with real `<style>` tags that have
- // plain-text CSS content that's provided by RouteInfo. That'd remove the
- // need for the staging `<link>`s and the ability for CSS to be missing at
- // this phase, allowing us to remove the error handling flow that reloads the
- // page.
+ }); // This function has a return type to ensure it doesn't start returning a
+ // Promise. It should remain synchronous.
function onStart() {
if (
@@ -999,82 +1014,30 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
// unless we're in production:
false
) {
- return Promise.resolve([]);
- } // Clean up previous render if canceling:
+ return false;
+ }
- [].slice
- .call(
- document.querySelectorAll(
- "link[data-n-staging], noscript[data-n-staging]"
- )
- )
- .forEach(function(el) {
- el.parentNode.removeChild(el);
- });
- var referenceNodes = [].slice.call(
- document.querySelectorAll("link[data-n-g], link[data-n-p]")
+ var currentStyleTags = looseToArray(
+ document.querySelectorAll("style[data-n-href]")
);
- var referenceHrefs = new Set(
- referenceNodes.map(function(e) {
- return e.getAttribute("href");
+ var currentHrefs = new Set(
+ currentStyleTags.map(function(tag) {
+ return tag.getAttribute("data-n-href");
})
);
- var referenceNode = referenceNodes[referenceNodes.length - 1];
- var required = styleSheets.map(function(href) {
- var newNode, promise;
- var existingLink = referenceHrefs.has(href);
-
- if (existingLink) {
- newNode = document.createElement("noscript");
- newNode.setAttribute("data-n-staging", href);
- promise = true;
- } else {
- var _ref9 = (0, _pageLoader.createLink)(href, "stylesheet"),
- _ref10 = _slicedToArray(_ref9, 2),
- link = _ref10[0],
- onload = _ref10[1];
-
- link.setAttribute("data-n-staging", ""); // Media `none` does not work in Firefox, so `print` is more
- // cross-browser. Since this is so short lived we don't have to worry
- // about style thrashing in a print view (where no routing is going to be
- // happening anyway).
-
- link.setAttribute("media", "print");
- newNode = link;
- promise = onload;
- }
-
- if (referenceNode) {
- referenceNode.parentNode.insertBefore(
- newNode,
- referenceNode.nextSibling
- );
- referenceNode = newNode;
- } else {
- document.head.appendChild(newNode);
+ styleSheets.forEach(function(_ref9) {
+ var href = _ref9.href,
+ text = _ref9.text;
+
+ if (!currentHrefs.has(href)) {
+ var styleTag = document.createElement("style");
+ styleTag.setAttribute("data-n-href", href);
+ styleTag.setAttribute("media", "x");
+ document.head.appendChild(styleTag);
+ styleTag.appendChild(document.createTextNode(text));
}
-
- return promise;
- });
- return Promise.all(required)["catch"](function() {
- // This is too late in the rendering lifecycle to use the existing
- // `PAGE_LOAD_ERROR` flow (via `handleRouteInfoError`).
- // To match that behavior, we request the page to reload with the current
- // asPath. This is already set at this phase since we "committed" to the
- // render.
- // This handles an edge case where a new deployment is rolled during
- // client-side transition and the CSS assets are missing.
- // This prevents:
- // 1. An unstyled page from being rendered (old behavior)
- // 2. The `/_error` page being rendered (we want to reload for the new
- // deployment)
- window.location.href = router.asPath; // Instead of rethrowing the CSS loading error, we give a promise that
- // won't resolve. This pauses the rendering process until the page
- // reloads. Re-throwing the error could result in a flash of error page.
- // throw cssLoadingError
-
- return new Promise(function() {});
});
+ return true;
}
function onCommit() {
@@ -1083,45 +1046,60 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
// unless we're in production:
true && // We can skip this during hydration. Running it wont cause any harm, but
// we may as well save the CPU cycles:
- !isInitialRender && // Ensure this render commit owns the currently staged stylesheets:
- renderPromiseReject === _lastRenderReject
+ !isInitialRender && // Ensure this render was not canceled
+ !canceled
) {
- // Remove or relocate old stylesheets:
- var relocatePlaceholders = [].slice.call(
- document.querySelectorAll("noscript[data-n-staging]")
+ var desiredHrefs = new Set(
+ styleSheets.map(function(s) {
+ return s.href;
+ })
);
- var relocateHrefs = relocatePlaceholders.map(function(e) {
- return e.getAttribute("data-n-staging");
- });
- [].slice
- .call(document.querySelectorAll("link[data-n-p]"))
- .forEach(function(el) {
- var currentHref = el.getAttribute("href");
- var relocateIndex = relocateHrefs.indexOf(currentHref);
-
- if (relocateIndex !== -1) {
- var _placeholderElement$p;
-
- var placeholderElement = relocatePlaceholders[relocateIndex];
- (_placeholderElement$p = placeholderElement.parentNode) ==
- null
- ? void 0
- : _placeholderElement$p.replaceChild(
- el,
- placeholderElement
- );
- } else {
- el.parentNode.removeChild(el);
+ var currentStyleTags = looseToArray(
+ document.querySelectorAll("style[data-n-href]")
+ );
+ var currentHrefs = currentStyleTags.map(function(tag) {
+ return tag.getAttribute("data-n-href");
+ }); // Toggle `<style>` tags on or off depending on if they're needed:
+
+ for (var idx = 0; idx < currentHrefs.length; ++idx) {
+ if (desiredHrefs.has(currentHrefs[idx])) {
+ currentStyleTags[idx].removeAttribute("media");
+ } else {
+ currentStyleTags[idx].setAttribute("media", "x");
+ }
+ } // Reorder styles into intended order:
+
+ var referenceNode = document.querySelector("noscript[data-n-css]");
+
+ if (
+ // This should be an invariant:
+ referenceNode
+ ) {
+ styleSheets.forEach(function(_ref10) {
+ var href = _ref10.href;
+ var targetTag = document.querySelector(
+ 'style[data-n-href="'.concat(href, '"]')
+ );
+
+ if (
+ // This should be an invariant:
+ targetTag
+ ) {
+ referenceNode.parentNode.insertBefore(
+ targetTag,
+ referenceNode.nextSibling
+ );
+ referenceNode = targetTag;
}
- }); // Activate new stylesheets:
- [].slice
- .call(document.querySelectorAll("link[data-n-staging]"))
- .forEach(function(el) {
- el.removeAttribute("data-n-staging");
- el.removeAttribute("media");
- el.setAttribute("data-n-p", "");
- }); // Force browser to recompute layout, which prevents a flash of unstyled
- // content:
+ });
+ } // Finally, clean up server rendered stylesheets:
+
+ looseToArray(document.querySelectorAll("link[data-n-p]")).forEach(
+ function(el) {
+ el.parentNode.removeChild(el);
+ }
+ ); // Force browser to recompute layout, which should prevent a flash of
+ // unstyled content:
getComputedStyle(document.body, "height");
}
@@ -1139,29 +1117,12 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
null,
/*#__PURE__*/ _react["default"].createElement(App, appProps)
)
- ); // We catch runtime errors using componentDidCatch which will trigger renderError
-
- return Promise.race([
- // Download required CSS assets first:
- onStart()
- .then(function() {
- // Ensure a new render has not been started:
- if (renderPromiseReject === _lastRenderReject) {
- // Queue rendering:
- renderReactElement(
- false ? /*#__PURE__*/ undefined : elem,
- appElement
- );
- }
- })
- .then(function() {
- return (
- // Wait for rendering to complete:
- renderPromise
- );
- }), // Bail early on route cancelation (rejection):
- renderPromise
- ]);
+ );
+
+ onStart(); // We catch runtime errors using componentDidCatch which will trigger renderError
+
+ renderReactElement(false ? /*#__PURE__*/ undefined : elem, appElement);
+ return renderPromise;
}
function Root(_ref11) {
@@ -1617,12 +1578,9 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var _createClass = __webpack_require__("W8MJ");
- var _slicedToArray = __webpack_require__("J4zp");
-
var _interopRequireDefault = __webpack_require__("TqRt");
exports.__esModule = true;
- exports.createLink = createLink;
exports["default"] = void 0;
var _mitt = _interopRequireDefault(__webpack_require__("dZ6Y"));
@@ -1667,6 +1625,7 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
: // IE 11, Edge 12+, nearly all evergreen
"prefetch";
var relPreload = hasRel("preload") ? "preload" : relPrefetch;
+ var relPreloadStyle = "fetch";
var hasNoModule = "noModule" in document.createElement("script");
var requestIdleCallback =
@@ -1686,31 +1645,19 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
return route.replace(/\/$/, "");
}
- function createLink(href, rel, as, link) {
- link = document.createElement("link");
- return [
- link,
- new Promise(function(res, rej) {
- // The order of property assignment here is intentional:
- if (as) link.as = as;
- link.rel = rel;
- link.crossOrigin = "anonymous";
- link.onload = res;
- link.onerror = rej; // `href` should always be last:
-
- link.href = href;
- })
- ];
- }
+ function appendLink(href, rel, as, link) {
+ return new Promise(function(res, rej) {
+ link = document.createElement("link"); // The order of property assignment here is intentional:
- function appendLink(href, rel, as) {
- var _createLink = createLink(href, rel, as),
- _createLink2 = _slicedToArray(_createLink, 2),
- link = _createLink2[0],
- res = _createLink2[1];
+ if (as) link.as = as;
+ link.rel = rel;
+ link.crossOrigin = "anonymous";
+ link.onload = res;
+ link.onerror = rej; // `href` should always be last:
- document.head.appendChild(link);
- return res;
+ link.href = href;
+ document.head.appendChild(link);
+ });
}
function loadScript(url) {
@@ -2007,7 +1954,7 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
// wait for these to resolve. To prevent an unhandled
// rejection, we swallow the error which is handled later in
// the rendering cycle (this is just a preload optimization).
- appendLink(d, relPreload, "style")["catch"](
+ appendLink(d, relPreload, relPreloadStyle)["catch"](
function() {
/* ignore preload error */
}
@@ -2064,20 +2011,44 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var check;
}
+ function fetchStyleSheet(href) {
+ return fetch(href).then(function(res) {
+ if (!res.ok) throw pageLoadError(href);
+ return res.text().then(function(text) {
+ return {
+ href: href,
+ text: text
+ };
+ });
+ });
+ }
+
var promisedDeps = // Shared styles will already be on the page:
route === "/_app" || false // We use `style-loader` in development:
? Promise.resolve([])
: route === this.initialPage
? Promise.resolve(this.initialStyleSheets) // Tests that this does not block hydration:
: // test/integration/css-fixtures/hydrate-without-deps/
- this.getDependencies(route);
+ this.getDependencies(route)
+ .then(function(deps) {
+ return deps.filter(function(d) {
+ return d.endsWith(".css");
+ });
+ })
+ .then(function(cssFiles) {
+ return (
+ // These files should've already been fetched by now, so this
+ // should resolve pretty much instantly.
+ Promise.all(
+ cssFiles.map(function(d) {
+ return fetchStyleSheet(d);
+ })
+ )
+ );
+ });
promisedDeps.then(
function(deps) {
- return register(
- deps.filter(function(d) {
- return d.endsWith(".css");
- })
- );
+ return register(deps);
},
function(error) {
_this5.pageCache[route] = {
@@ -2133,7 +2104,7 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
appendLink(
url,
relPrefetch,
- url.endsWith(".css") ? "style" : "script"
+ url.endsWith(".css") ? relPreloadStyle : "script"
),
true &&
!isDependency &&Diff for main-be61079..e7.module.js
@@ -193,7 +193,7 @@
var _headManager = _interopRequireDefault(__webpack_require__("DqTX"));
- var _pageLoader = _interopRequireWildcard3(__webpack_require__("zmvN"));
+ var _pageLoader = _interopRequireDefault(__webpack_require__("zmvN"));
var _performanceRelayer = _interopRequireDefault(
__webpack_require__("bGXG")
@@ -239,13 +239,25 @@
asPath = (0, _router.delBasePath)(asPath);
}
+ var looseToArray = input => [].slice.call(input);
+
var pageLoader = new _pageLoader.default(
buildId,
prefix,
page,
- [].slice
- .call(document.querySelectorAll("link[rel=stylesheet][data-n-p]"))
- .map(e => e.getAttribute("href"))
+ looseToArray(document.styleSheets)
+ .filter(
+ el =>
+ el.ownerNode &&
+ el.ownerNode.tagName === "LINK" &&
+ el.ownerNode.hasAttribute("data-n-p")
+ )
+ .map(sheet => ({
+ href: sheet.ownerNode.getAttribute("href"),
+ text: looseToArray(sheet.cssRules)
+ .map(r => r.cssText)
+ .join("")
+ }))
);
var register = _ref => {
@@ -702,8 +714,8 @@
); // lastAppProps has to be set before ReactDom.render to account for ReactDom throwing an error.
lastAppProps = appProps;
+ var canceled = false;
var resolvePromise;
- var renderPromiseReject;
var renderPromise = new Promise((resolve, reject) => {
if (lastRenderReject) {
lastRenderReject();
@@ -714,17 +726,15 @@
resolve();
};
- renderPromiseReject = lastRenderReject = () => {
+ lastRenderReject = () => {
+ canceled = true;
lastRenderReject = null;
var error = new Error("Cancel rendering route");
error.cancelled = true;
reject(error);
};
- }); // TODO: consider replacing this with real `<style>` tags that have
- // plain-text CSS content that's provided by RouteInfo. That'd remove the
- // need for the staging `<link>`s and the ability for CSS to be missing at
- // this phase, allowing us to remove the error handling flow that reloads the
- // page.
+ }); // This function has a return type to ensure it doesn't start returning a
+ // Promise. It should remain synchronous.
function onStart() {
if (
@@ -734,79 +744,27 @@
// unless we're in production:
false
) {
- return Promise.resolve([]);
- } // Clean up previous render if canceling:
+ return false;
+ }
- [].slice
- .call(
- document.querySelectorAll(
- "link[data-n-staging], noscript[data-n-staging]"
- )
- )
- .forEach(el => {
- el.parentNode.removeChild(el);
- });
- var referenceNodes = [].slice.call(
- document.querySelectorAll("link[data-n-g], link[data-n-p]")
+ var currentStyleTags = looseToArray(
+ document.querySelectorAll("style[data-n-href]")
);
- var referenceHrefs = new Set(
- referenceNodes.map(e => e.getAttribute("href"))
+ var currentHrefs = new Set(
+ currentStyleTags.map(tag => tag.getAttribute("data-n-href"))
);
- var referenceNode = referenceNodes[referenceNodes.length - 1];
- var required = styleSheets.map(href => {
- var newNode, promise;
- var existingLink = referenceHrefs.has(href);
-
- if (existingLink) {
- newNode = document.createElement("noscript");
- newNode.setAttribute("data-n-staging", href);
- promise = true;
- } else {
- var [link, onload] = (0, _pageLoader.createLink)(
- href,
- "stylesheet"
- );
- link.setAttribute("data-n-staging", ""); // Media `none` does not work in Firefox, so `print` is more
- // cross-browser. Since this is so short lived we don't have to worry
- // about style thrashing in a print view (where no routing is going to be
- // happening anyway).
-
- link.setAttribute("media", "print");
- newNode = link;
- promise = onload;
- }
-
- if (referenceNode) {
- referenceNode.parentNode.insertBefore(
- newNode,
- referenceNode.nextSibling
- );
- referenceNode = newNode;
- } else {
- document.head.appendChild(newNode);
+ styleSheets.forEach(_ref7 => {
+ var { href, text } = _ref7;
+
+ if (!currentHrefs.has(href)) {
+ var styleTag = document.createElement("style");
+ styleTag.setAttribute("data-n-href", href);
+ styleTag.setAttribute("media", "x");
+ document.head.appendChild(styleTag);
+ styleTag.appendChild(document.createTextNode(text));
}
-
- return promise;
- });
- return Promise.all(required).catch(() => {
- // This is too late in the rendering lifecycle to use the existing
- // `PAGE_LOAD_ERROR` flow (via `handleRouteInfoError`).
- // To match that behavior, we request the page to reload with the current
- // asPath. This is already set at this phase since we "committed" to the
- // render.
- // This handles an edge case where a new deployment is rolled during
- // client-side transition and the CSS assets are missing.
- // This prevents:
- // 1. An unstyled page from being rendered (old behavior)
- // 2. The `/_error` page being rendered (we want to reload for the new
- // deployment)
- window.location.href = router.asPath; // Instead of rethrowing the CSS loading error, we give a promise that
- // won't resolve. This pauses the rendering process until the page
- // reloads. Re-throwing the error could result in a flash of error page.
- // throw cssLoadingError
-
- return new Promise(() => {});
});
+ return true;
}
function onCommit() {
@@ -815,45 +773,56 @@
// unless we're in production:
true && // We can skip this during hydration. Running it wont cause any harm, but
// we may as well save the CPU cycles:
- !isInitialRender && // Ensure this render commit owns the currently staged stylesheets:
- renderPromiseReject === lastRenderReject
+ !isInitialRender && // Ensure this render was not canceled
+ !canceled
) {
- // Remove or relocate old stylesheets:
- var relocatePlaceholders = [].slice.call(
- document.querySelectorAll("noscript[data-n-staging]")
+ var desiredHrefs = new Set(styleSheets.map(s => s.href));
+ var currentStyleTags = looseToArray(
+ document.querySelectorAll("style[data-n-href]")
);
- var relocateHrefs = relocatePlaceholders.map(e =>
- e.getAttribute("data-n-staging")
- );
- [].slice
- .call(document.querySelectorAll("link[data-n-p]"))
- .forEach(el => {
- var currentHref = el.getAttribute("href");
- var relocateIndex = relocateHrefs.indexOf(currentHref);
-
- if (relocateIndex !== -1) {
- var _placeholderElement$p;
-
- var placeholderElement = relocatePlaceholders[relocateIndex];
- (_placeholderElement$p = placeholderElement.parentNode) ==
- null
- ? void 0
- : _placeholderElement$p.replaceChild(
- el,
- placeholderElement
- );
- } else {
- el.parentNode.removeChild(el);
+ var currentHrefs = currentStyleTags.map(tag =>
+ tag.getAttribute("data-n-href")
+ ); // Toggle `<style>` tags on or off depending on if they're needed:
+
+ for (var idx = 0; idx < currentHrefs.length; ++idx) {
+ if (desiredHrefs.has(currentHrefs[idx])) {
+ currentStyleTags[idx].removeAttribute("media");
+ } else {
+ currentStyleTags[idx].setAttribute("media", "x");
+ }
+ } // Reorder styles into intended order:
+
+ var referenceNode = document.querySelector("noscript[data-n-css]");
+
+ if (
+ // This should be an invariant:
+ referenceNode
+ ) {
+ styleSheets.forEach(_ref8 => {
+ var { href } = _ref8;
+ var targetTag = document.querySelector(
+ 'style[data-n-href="'.concat(href, '"]')
+ );
+
+ if (
+ // This should be an invariant:
+ targetTag
+ ) {
+ referenceNode.parentNode.insertBefore(
+ targetTag,
+ referenceNode.nextSibling
+ );
+ referenceNode = targetTag;
}
- }); // Activate new stylesheets:
- [].slice
- .call(document.querySelectorAll("link[data-n-staging]"))
- .forEach(el => {
- el.removeAttribute("data-n-staging");
- el.removeAttribute("media");
- el.setAttribute("data-n-p", "");
- }); // Force browser to recompute layout, which prevents a flash of unstyled
- // content:
+ });
+ } // Finally, clean up server rendered stylesheets:
+
+ looseToArray(document.querySelectorAll("link[data-n-p]")).forEach(
+ el => {
+ el.parentNode.removeChild(el);
+ }
+ ); // Force browser to recompute layout, which should prevent a flash of
+ // unstyled content:
getComputedStyle(document.body, "height");
}
@@ -871,32 +840,16 @@
null,
/*#__PURE__*/ _react.default.createElement(App, appProps)
)
- ); // We catch runtime errors using componentDidCatch which will trigger renderError
-
- return Promise.race([
- // Download required CSS assets first:
- onStart()
- .then(() => {
- // Ensure a new render has not been started:
- if (renderPromiseReject === lastRenderReject) {
- // Queue rendering:
- renderReactElement(
- false ? /*#__PURE__*/ undefined : elem,
- appElement
- );
- }
- })
- .then(
- () =>
- // Wait for rendering to complete:
- renderPromise
- ), // Bail early on route cancelation (rejection):
- renderPromise
- ]);
+ );
+
+ onStart(); // We catch runtime errors using componentDidCatch which will trigger renderError
+
+ renderReactElement(false ? /*#__PURE__*/ undefined : elem, appElement);
+ return renderPromise;
}
- function Root(_ref7) {
- var { callback, children } = _ref7;
+ function Root(_ref9) {
+ var { callback, children } = _ref9;
// We use `useLayoutEffect` to guarantee the callback is executed
// as soon as React flushes the update.
@@ -1287,7 +1240,6 @@
var _interopRequireDefault = __webpack_require__("TqRt");
exports.__esModule = true;
- exports.createLink = createLink;
exports.default = void 0;
var _mitt = _interopRequireDefault(__webpack_require__("dZ6Y"));
@@ -1332,6 +1284,7 @@
: // IE 11, Edge 12+, nearly all evergreen
"prefetch";
var relPreload = hasRel("preload") ? "preload" : relPrefetch;
+ var relPreloadStyle = "fetch";
var hasNoModule = "noModule" in document.createElement("script");
var requestIdleCallback =
@@ -1351,27 +1304,19 @@
return route.replace(/\/$/, "");
}
- function createLink(href, rel, as, link) {
- link = document.createElement("link");
- return [
- link,
- new Promise((res, rej) => {
- // The order of property assignment here is intentional:
- if (as) link.as = as;
- link.rel = rel;
- link.crossOrigin = "anonymous";
- link.onload = res;
- link.onerror = rej; // `href` should always be last:
-
- link.href = href;
- })
- ];
- }
+ function appendLink(href, rel, as, link) {
+ return new Promise((res, rej) => {
+ link = document.createElement("link"); // The order of property assignment here is intentional:
- function appendLink(href, rel, as) {
- var [link, res] = createLink(href, rel, as);
- document.head.appendChild(link);
- return res;
+ if (as) link.as = as;
+ link.rel = rel;
+ link.crossOrigin = "anonymous";
+ link.onload = res;
+ link.onerror = rej; // `href` should always be last:
+
+ link.href = href;
+ document.head.appendChild(link);
+ });
}
function loadScript(url) {
@@ -1617,7 +1562,7 @@
// wait for these to resolve. To prevent an unhandled
// rejection, we swallow the error which is handled later in
// the rendering cycle (this is just a preload optimization).
- appendLink(d, relPreload, "style").catch(() => {
+ appendLink(d, relPreload, relPreloadStyle).catch(() => {
/* ignore preload error */
});
}
@@ -1666,15 +1611,32 @@
var check;
}
+ function fetchStyleSheet(href) {
+ return fetch(href).then(res => {
+ if (!res.ok) throw pageLoadError(href);
+ return res.text().then(text => ({
+ href,
+ text
+ }));
+ });
+ }
+
var promisedDeps = // Shared styles will already be on the page:
route === "/_app" || false // We use `style-loader` in development:
? Promise.resolve([])
: route === this.initialPage
? Promise.resolve(this.initialStyleSheets) // Tests that this does not block hydration:
: // test/integration/css-fixtures/hydrate-without-deps/
- this.getDependencies(route);
+ this.getDependencies(route)
+ .then(deps => deps.filter(d => d.endsWith(".css")))
+ .then((
+ cssFiles // These files should've already been fetched by now, so this
+ ) =>
+ // should resolve pretty much instantly.
+ Promise.all(cssFiles.map(d => fetchStyleSheet(d)))
+ );
promisedDeps.then(
- deps => register(deps.filter(d => d.endsWith(".css"))),
+ deps => register(deps),
error => {
this.pageCache[route] = {
error
@@ -1722,7 +1684,7 @@
appendLink(
url,
relPrefetch,
- url.endsWith(".css") ? "style" : "script"
+ url.endsWith(".css") ? relPreloadStyle : "script"
),
true &&
!isDependency &&Diff for index.html
@@ -4,9 +4,10 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta name="next-head-count" content="2" />
+ <noscript data-n-css="true"></noscript>
<link
rel="preload"
- href="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ href="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
as="script"
crossorigin="anonymous"
/>
@@ -81,13 +82,13 @@
src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
></script>
<script
- src="/_next/static/chunks/main-209a935a087118ae6828.js"
+ src="/_next/static/chunks/main-fe24fe70b35ca4db2791.js"
async=""
crossorigin="anonymous"
nomodule=""
></script>
<script
- src="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ src="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
async=""
crossorigin="anonymous"
type="module"Diff for link.html
@@ -4,9 +4,10 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta name="next-head-count" content="2" />
+ <noscript data-n-css="true"></noscript>
<link
rel="preload"
- href="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ href="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
as="script"
crossorigin="anonymous"
/>
@@ -86,13 +87,13 @@
src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
></script>
<script
- src="/_next/static/chunks/main-209a935a087118ae6828.js"
+ src="/_next/static/chunks/main-fe24fe70b35ca4db2791.js"
async=""
crossorigin="anonymous"
nomodule=""
></script>
<script
- src="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ src="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
async=""
crossorigin="anonymous"
type="module"Diff for withRouter.html
@@ -4,9 +4,10 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta name="next-head-count" content="2" />
+ <noscript data-n-css="true"></noscript>
<link
rel="preload"
- href="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ href="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
as="script"
crossorigin="anonymous"
/>
@@ -81,13 +82,13 @@
src="/_next/static/chunks/polyfills-f73ba3fc145972ef83e9.js"
></script>
<script
- src="/_next/static/chunks/main-209a935a087118ae6828.js"
+ src="/_next/static/chunks/main-fe24fe70b35ca4db2791.js"
async=""
crossorigin="anonymous"
nomodule=""
></script>
<script
- src="/_next/static/chunks/main-be610799d99109ebb1e7.module.js"
+ src="/_next/static/chunks/main-8203add16da23ec45de4.module.js"
async=""
crossorigin="anonymous"
type="module"Serverless Mode (Increase detected ⚠️ )
General Overall decrease ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| buildDuration | 13.7s | 13.6s | -94ms |
| nodeModulesSize | 57.5 MB | 57.5 MB | -3.18 kB |
Client Bundles (main, webpack, commons) Overall decrease ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| 677f882d2ed8..7f47.js gzip | 10.3 kB | 10.3 kB | ✓ |
| framework.HASH.js gzip | 39 kB | 39 kB | ✓ |
| main-d4bab31..824e.js gzip | 7.34 kB | N/A | N/A |
| webpack-e067..f178.js gzip | 751 B | 751 B | ✓ |
| main-ff68bee..74d0.js gzip | N/A | 7.32 kB | N/A |
| Overall change | 57.4 kB | 57.3 kB | -20 B |
Client Bundles (main, webpack, commons) Modern Overall decrease ✓
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| 677f882d2ed8..dule.js gzip | 6.15 kB | 6.15 kB | ✓ |
| framework.HA..dule.js gzip | 39 kB | 39 kB | ✓ |
| main-438d30a..dule.js gzip | 6.39 kB | N/A | N/A |
| webpack-07c5..dule.js gzip | 751 B | 751 B | ✓ |
| main-91bc16e..dule.js gzip | N/A | 6.39 kB | N/A |
| Overall change | 52.3 kB | 52.3 kB | -4 B |
Legacy Client Bundles (polyfills)
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| polyfills-4b..e242.js gzip | 31 kB | 31 kB | ✓ |
| Overall change | 31 kB | 31 kB | ✓ |
Client Pages
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _app-9a0b9e1..b37e.js gzip | 1.28 kB | 1.28 kB | ✓ |
| _error-28298..e0c9.js gzip | 3.44 kB | 3.44 kB | ✓ |
| hooks-89731c..c609.js gzip | 887 B | 887 B | ✓ |
| index-17468f..5d83.js gzip | 227 B | 227 B | ✓ |
| link-000f151..65d4.js gzip | 1.29 kB | 1.29 kB | ✓ |
| routerDirect..924c.js gzip | 284 B | 284 B | ✓ |
| withRouter-7..c13d.js gzip | 284 B | 284 B | ✓ |
| Overall change | 7.69 kB | 7.69 kB | ✓ |
Client Pages Modern
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _app-75d3a82..dule.js gzip | 625 B | 625 B | ✓ |
| _error-65c8a..dule.js gzip | 2.29 kB | 2.29 kB | ✓ |
| hooks-cbf13f..dule.js gzip | 387 B | 387 B | ✓ |
| index-b9a643..dule.js gzip | 226 B | 226 B | ✓ |
| link-4cfda7a..dule.js gzip | 1.26 kB | 1.26 kB | ✓ |
| routerDirect..dule.js gzip | 284 B | 284 B | ✓ |
| withRouter-f..dule.js gzip | 282 B | 282 B | ✓ |
| Overall change | 5.35 kB | 5.35 kB | ✓ |
Client Build Manifests
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _buildManifest.js gzip | 322 B | 322 B | ✓ |
| _buildManife..dule.js gzip | 330 B | 330 B | ✓ |
| Overall change | 652 B | 652 B | ✓ |
Serverless bundles Overall increase ⚠️
| vercel/next.js canary | Timer/next.js wip/style-tags | Change | |
|---|---|---|---|
| _error.js | 1.03 MB | 1.03 MB | |
| 404.html | 4.18 kB | 4.22 kB | |
| hooks.html | 3.82 kB | 3.86 kB | |
| index.js | 1.03 MB | 1.03 MB | |
| link.js | 1.07 MB | 1.07 MB | |
| routerDirect.js | 1.07 MB | 1.07 MB | |
| withRouter.js | 1.07 MB | 1.07 MB | |
| Overall change | 5.28 MB | 5.28 MB |
|
@Timer i think we're seeing some CORS issues loading external CSS because of this change on We use the specifically i think this is the culprit: |
This pull request replaces our client-side style transitions with
<style>tags over async<link rel=stylesheet>tags. This should fix some edge cases users see with Chrome accidentally causing a FOUC.This also removes the need to perform an async operation before starting the render, which should remove any perceivable navigation delay.
Fixes #16289