-
Notifications
You must be signed in to change notification settings - Fork 27.6k
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
Control <Image /> prefetching with React #18904
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
styfle
reviewed
Nov 6, 2020
Stats from current PRDefault Server Mode (Increase detected
|
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
buildDuration | 11.7s | 11.6s | -93ms |
nodeModulesSize | 84.9 MB | 84.9 MB | -911 B |
Page Load Tests Overall increase ✓
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
/ failed reqs | 0 | 0 | ✓ |
/ total time (seconds) | 2.172 | 2.149 | -0.02 |
/ avg req/sec | 1151.16 | 1163.21 | +12.05 |
/error-in-render failed reqs | 0 | 0 | ✓ |
/error-in-render total time (seconds) | 1.168 | 1.158 | -0.01 |
/error-in-render avg req/sec | 2140.66 | 2158.05 | +17.39 |
Client Bundles (main, webpack, commons)
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
677f882d2ed8..7d3b.js gzip | 11.3 kB | 11.3 kB | ✓ |
framework.HASH.js gzip | 39 kB | 39 kB | ✓ |
main-d942eb5..343f.js gzip | 7.4 kB | 7.4 kB | ✓ |
webpack-e067..f178.js gzip | 751 B | 751 B | ✓ |
Overall change | 58.4 kB | 58.4 kB | ✓ |
Client Bundles (main, webpack, commons) Modern
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
677f882d2ed8..dule.js gzip | 7.04 kB | 7.04 kB | ✓ |
framework.HA..dule.js gzip | 39 kB | 39 kB | ✓ |
main-34e64ff..dule.js gzip | 6.39 kB | 6.39 kB | ✓ |
webpack-07c5..dule.js gzip | 751 B | 751 B | ✓ |
Overall change | 53.1 kB | 53.1 kB | ✓ |
Legacy Client Bundles (polyfills)
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
polyfills-4b..e242.js gzip | 31 kB | 31 kB | ✓ |
Overall change | 31 kB | 31 kB | ✓ |
Client Pages Overall increase ⚠️
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
_app-7231d4b..5856.js gzip | 1.28 kB | 1.28 kB | ✓ |
_error-fca3d..2eb1.js gzip | 3.44 kB | 3.44 kB | ✓ |
hooks-d4591d..e7c2.js gzip | 887 B | 887 B | ✓ |
index-17468f..5d83.js gzip | 227 B | 227 B | ✓ |
link-03d24c6..d1c7.js gzip | 1.35 kB | N/A | N/A |
routerDirect..924c.js gzip | 284 B | 284 B | ✓ |
withRouter-7..c13d.js gzip | 284 B | 284 B | ✓ |
link-8a9d104..0e42.js gzip | N/A | 1.55 kB | N/A |
Overall change | 7.75 kB | 7.96 kB |
Client Pages Modern Overall increase ⚠️
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
_app-75d3a82..dule.js gzip | 625 B | 625 B | ✓ |
_error-4469a..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-dfbbfbd..dule.js gzip | 1.32 kB | N/A | N/A |
routerDirect..dule.js gzip | 284 B | 284 B | ✓ |
withRouter-f..dule.js gzip | 282 B | 282 B | ✓ |
link-d1cfb87..dule.js gzip | N/A | 1.49 kB | N/A |
Overall change | 5.41 kB | 5.59 kB |
Client Build Manifests
vercel/next.js canary | Timer/next.js hotfix/link-updating | 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 hotfix/link-updating | Change | |
---|---|---|---|
index.html gzip | 1 kB | 1 kB | ✓ |
link.html gzip | 1.01 kB | 1.01 kB | |
withRouter.html gzip | 995 B | 995 B | ✓ |
Overall change | 3 kB | 3.01 kB |
Diffs
Diff for _buildManifest.js
@@ -7,7 +7,7 @@ self.__BUILD_MANIFEST = {
"/hooks": [
"static\u002Fchunks\u002Fpages\u002Fhooks-bdd2cad07648acf22380.js"
],
- "/link": ["static\u002Fchunks\u002Fpages\u002Flink-17a206ac5f5df2421f5d.js"],
+ "/link": ["static\u002Fchunks\u002Fpages\u002Flink-fcaf825022c62b02057c.js"],
"/routerDirect": [
"static\u002Fchunks\u002Fpages\u002FrouterDirect-2e9bfd441bd88cd3382e.js"
],
Diff for _buildManifest.module.js
@@ -10,7 +10,7 @@ self.__BUILD_MANIFEST = {
"static\u002Fchunks\u002Fpages\u002Fhooks-56fa58a6f0993d7d36d7.module.js"
],
"/link": [
- "static\u002Fchunks\u002Fpages\u002Flink-16d8635e170e01799dc1.module.js"
+ "static\u002Fchunks\u002Fpages\u002Flink-ec1fbf762c0209fe4b72.module.js"
],
"/routerDirect": [
"static\u002Fchunks\u002Fpages\u002FrouterDirect-368af3dfef3c9cd99dc3.module.js"
Diff for link-16d8635..c1.module.js
@@ -76,62 +76,9 @@
var _router2 = __webpack_require__("nOHt");
- var cachedObserver;
- var listeners = new Map();
- var IntersectionObserver = true ? window.IntersectionObserver : undefined;
- var prefetched = {};
-
- function getObserver() {
- // Return shared instance of IntersectionObserver if already created
- if (cachedObserver) {
- return cachedObserver;
- } // Only create shared IntersectionObserver if supported in browser
-
- if (!IntersectionObserver) {
- return undefined;
- }
-
- return (cachedObserver = new IntersectionObserver(
- entries => {
- entries.forEach(entry => {
- if (!listeners.has(entry.target)) {
- return;
- }
-
- var cb = listeners.get(entry.target);
-
- if (entry.isIntersecting || entry.intersectionRatio > 0) {
- cachedObserver.unobserve(entry.target);
- listeners.delete(entry.target);
- cb();
- }
- });
- },
- {
- rootMargin: "200px"
- }
- ));
- }
-
- var listenToIntersections = (el, cb) => {
- var observer = getObserver();
-
- if (!observer) {
- return () => {};
- }
+ var _useIntersection = __webpack_require__("vNVm");
- observer.observe(el);
- listeners.set(el, cb);
- return () => {
- try {
- observer.unobserve(el);
- } catch (err) {
- console.error(err);
- }
-
- listeners.delete(el);
- };
- };
+ var prefetched = {};
function prefetch(router, href, as, options) {
if (false) {
@@ -240,38 +187,14 @@
var child = _react.Children.only(children);
var childRef = child && typeof child === "object" && child.ref;
-
- var cleanup = _react.default.useRef();
+ var [setIntersectionRef, isVisible] = (0,
+ _useIntersection.useIntersection)({
+ rootMargin: "200px"
+ });
var setRef = _react.default.useCallback(
el => {
- // cleanup previous event handlers
- if (cleanup.current) {
- cleanup.current();
- cleanup.current = undefined;
- }
-
- if (
- p &&
- IntersectionObserver &&
- el &&
- el.tagName &&
- (0, _router.isLocalURL)(href)
- ) {
- // Join on an invalid URI character
- var isPrefetched = prefetched[href + "%" + as];
-
- if (!isPrefetched) {
- cleanup.current = listenToIntersections(el, () => {
- prefetch(router, href, as, {
- locale:
- typeof locale !== "undefined"
- ? locale
- : router && router.locale
- });
- });
- }
- }
+ setIntersectionRef(el);
if (childRef) {
if (typeof childRef === "function") childRef(el);
@@ -280,9 +203,20 @@
}
}
},
- [p, childRef, href, as, router, locale]
+ [childRef, setIntersectionRef]
);
+ (0, _react.useEffect)(() => {
+ var shouldPrefetch = isVisible && p && (0, _router.isLocalURL)(href);
+ var isPrefetched = prefetched[href + "%" + as];
+
+ if (shouldPrefetch && !isPrefetched) {
+ prefetch(router, href, as, {
+ locale:
+ typeof locale !== "undefined" ? locale : router && router.locale
+ });
+ }
+ }, [as, href, isVisible, locale, p, router]);
var childProps = {
ref: setRef,
onClick: e => {
@@ -337,6 +271,99 @@
var _default = Link;
exports.default = _default;
+ /***/
+ },
+
+ /***/ vNVm: /***/ function(module, exports, __webpack_require__) {
+ "use strict";
+
+ exports.__esModule = true;
+ exports.useIntersection = useIntersection;
+
+ var _react = __webpack_require__("q1tI");
+
+ var hasIntersectionObserver = typeof IntersectionObserver !== "undefined";
+
+ function useIntersection(_ref) {
+ var { rootMargin, disabled } = _ref;
+ var isDisabled = disabled || !hasIntersectionObserver;
+ var unobserve = (0, _react.useRef)();
+ var [visible, setVisible] = (0, _react.useState)(false);
+ var setRef = (0, _react.useCallback)(
+ el => {
+ if (unobserve.current) {
+ unobserve.current();
+ unobserve.current = undefined;
+ }
+
+ if (isDisabled || visible) return;
+
+ if (el && el.tagName) {
+ unobserve.current = observe(
+ el,
+ isVisible => isVisible && setVisible(isVisible),
+ {
+ rootMargin
+ }
+ );
+ }
+ },
+ [isDisabled, rootMargin, visible]
+ );
+ (0, _react.useEffect)(() => {
+ if (!hasIntersectionObserver) {
+ if (!visible) setVisible(true);
+ }
+ }, [visible]);
+ return [setRef, visible];
+ }
+
+ function observe(element, callback, options) {
+ var { id, observer, elements } = createObserver(options);
+ elements.set(element, callback);
+ observer.observe(element);
+ return function unobserve() {
+ observer.unobserve(element); // Destroy observer when there's nothing left to watch:
+
+ if (elements.size === 0) {
+ observer.disconnect();
+ observers.delete(id);
+ }
+ };
+ }
+
+ var observers = new Map();
+
+ function createObserver(options) {
+ var id = options.rootMargin || "";
+ var instance = observers.get(id);
+
+ if (instance) {
+ return instance;
+ }
+
+ var elements = new Map();
+ var observer = new IntersectionObserver(entries => {
+ entries.forEach(entry => {
+ var callback = elements.get(entry.target);
+ var isVisible = entry.isIntersecting || entry.intersectionRatio > 0;
+
+ if (callback && isVisible) {
+ callback(isVisible);
+ }
+ });
+ }, options);
+ observers.set(
+ id,
+ (instance = {
+ id,
+ observer,
+ elements
+ })
+ );
+ return instance;
+ }
+
/***/
}
},
Diff for link-17a206a..df2421f5d.js
@@ -80,62 +80,9 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var _router2 = __webpack_require__("nOHt");
- var cachedObserver;
- var listeners = new Map();
- var IntersectionObserver = true ? window.IntersectionObserver : undefined;
- var prefetched = {};
-
- function getObserver() {
- // Return shared instance of IntersectionObserver if already created
- if (cachedObserver) {
- return cachedObserver;
- } // Only create shared IntersectionObserver if supported in browser
-
- if (!IntersectionObserver) {
- return undefined;
- }
-
- return (cachedObserver = new IntersectionObserver(
- function(entries) {
- entries.forEach(function(entry) {
- if (!listeners.has(entry.target)) {
- return;
- }
-
- var cb = listeners.get(entry.target);
-
- if (entry.isIntersecting || entry.intersectionRatio > 0) {
- cachedObserver.unobserve(entry.target);
- listeners["delete"](entry.target);
- cb();
- }
- });
- },
- {
- rootMargin: "200px"
- }
- ));
- }
-
- var listenToIntersections = function listenToIntersections(el, cb) {
- var observer = getObserver();
-
- if (!observer) {
- return function() {};
- }
-
- observer.observe(el);
- listeners.set(el, cb);
- return function() {
- try {
- observer.unobserve(el);
- } catch (err) {
- console.error(err);
- }
+ var _useIntersection = __webpack_require__("vNVm");
- listeners["delete"](el);
- };
- };
+ var prefetched = {};
function prefetch(router, href, as, options) {
if (false) {
@@ -255,37 +202,16 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var childRef = child && typeof child === "object" && child.ref;
- var cleanup = _react["default"].useRef();
+ var _ref3 = (0, _useIntersection.useIntersection)({
+ rootMargin: "200px"
+ }),
+ _ref4 = _slicedToArray(_ref3, 2),
+ setIntersectionRef = _ref4[0],
+ isVisible = _ref4[1];
var setRef = _react["default"].useCallback(
function(el) {
- // cleanup previous event handlers
- if (cleanup.current) {
- cleanup.current();
- cleanup.current = undefined;
- }
-
- if (
- p &&
- IntersectionObserver &&
- el &&
- el.tagName &&
- (0, _router.isLocalURL)(href)
- ) {
- // Join on an invalid URI character
- var isPrefetched = prefetched[href + "%" + as];
-
- if (!isPrefetched) {
- cleanup.current = listenToIntersections(el, function() {
- prefetch(router, href, as, {
- locale:
- typeof locale !== "undefined"
- ? locale
- : router && router.locale
- });
- });
- }
- }
+ setIntersectionRef(el);
if (childRef) {
if (typeof childRef === "function") childRef(el);
@@ -294,9 +220,26 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
}
}
},
- [p, childRef, href, as, router, locale]
+ [childRef, setIntersectionRef]
);
+ (0, _react.useEffect)(
+ function() {
+ var shouldPrefetch =
+ isVisible && p && (0, _router.isLocalURL)(href);
+ var isPrefetched = prefetched[href + "%" + as];
+
+ if (shouldPrefetch && !isPrefetched) {
+ prefetch(router, href, as, {
+ locale:
+ typeof locale !== "undefined"
+ ? locale
+ : router && router.locale
+ });
+ }
+ },
+ [as, href, isVisible, locale, p, router]
+ );
var childProps = {
ref: setRef,
onClick: function onClick(e) {
@@ -351,6 +294,116 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var _default = Link;
exports["default"] = _default;
+ /***/
+ },
+
+ /***/ vNVm: /***/ function(module, exports, __webpack_require__) {
+ "use strict";
+
+ var _slicedToArray = __webpack_require__("J4zp");
+
+ exports.__esModule = true;
+ exports.useIntersection = useIntersection;
+
+ var _react = __webpack_require__("q1tI");
+
+ var hasIntersectionObserver = typeof IntersectionObserver !== "undefined";
+
+ function useIntersection(_ref) {
+ var rootMargin = _ref.rootMargin,
+ disabled = _ref.disabled;
+ var isDisabled = disabled || !hasIntersectionObserver;
+ var unobserve = (0, _react.useRef)();
+
+ var _ref2 = (0, _react.useState)(false),
+ _ref3 = _slicedToArray(_ref2, 2),
+ visible = _ref3[0],
+ setVisible = _ref3[1];
+
+ var setRef = (0, _react.useCallback)(
+ function(el) {
+ if (unobserve.current) {
+ unobserve.current();
+ unobserve.current = undefined;
+ }
+
+ if (isDisabled || visible) return;
+
+ if (el && el.tagName) {
+ unobserve.current = observe(
+ el,
+ function(isVisible) {
+ return isVisible && setVisible(isVisible);
+ },
+ {
+ rootMargin: rootMargin
+ }
+ );
+ }
+ },
+ [isDisabled, rootMargin, visible]
+ );
+ (0, _react.useEffect)(
+ function() {
+ if (!hasIntersectionObserver) {
+ if (!visible) setVisible(true);
+ }
+ },
+ [visible]
+ );
+ return [setRef, visible];
+ }
+
+ function observe(element, callback, options) {
+ var _createObserver = createObserver(options),
+ id = _createObserver.id,
+ observer = _createObserver.observer,
+ elements = _createObserver.elements;
+
+ elements.set(element, callback);
+ observer.observe(element);
+ return function unobserve() {
+ observer.unobserve(element); // Destroy observer when there's nothing left to watch:
+
+ if (elements.size === 0) {
+ observer.disconnect();
+ observers["delete"](id);
+ }
+ };
+ }
+
+ var observers = new Map();
+
+ function createObserver(options) {
+ var id = options.rootMargin || "";
+ var instance = observers.get(id);
+
+ if (instance) {
+ return instance;
+ }
+
+ var elements = new Map();
+ var observer = new IntersectionObserver(function(entries) {
+ entries.forEach(function(entry) {
+ var callback = elements.get(entry.target);
+ var isVisible = entry.isIntersecting || entry.intersectionRatio > 0;
+
+ if (callback && isVisible) {
+ callback(isVisible);
+ }
+ });
+ }, options);
+ observers.set(
+ id,
+ (instance = {
+ id: id,
+ observer: observer,
+ elements: elements
+ })
+ );
+ return instance;
+ }
+
/***/
}
},
Diff for link.html
@@ -36,7 +36,7 @@
/>
<link
rel="preload"
- href="/_next/static/chunks/pages/link-16d8635e170e01799dc1.module.js"
+ href="/_next/static/chunks/pages/link-ec1fbf762c0209fe4b72.module.js"
as="script"
crossorigin="anonymous"
/>
@@ -150,13 +150,13 @@
type="module"
></script>
<script
- src="/_next/static/chunks/pages/link-17a206ac5f5df2421f5d.js"
+ src="/_next/static/chunks/pages/link-fcaf825022c62b02057c.js"
async=""
crossorigin="anonymous"
nomodule=""
></script>
<script
- src="/_next/static/chunks/pages/link-16d8635e170e01799dc1.module.js"
+ src="/_next/static/chunks/pages/link-ec1fbf762c0209fe4b72.module.js"
async=""
crossorigin="anonymous"
type="module"
Serverless Mode (Increase detected ⚠️ )
General Overall decrease ✓
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
buildDuration | 12.6s | 13.1s | |
nodeModulesSize | 84.9 MB | 84.9 MB | -911 B |
Client Bundles (main, webpack, commons)
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
677f882d2ed8..7d3b.js gzip | 11.3 kB | 11.3 kB | ✓ |
framework.HASH.js gzip | 39 kB | 39 kB | ✓ |
main-d942eb5..343f.js gzip | 7.4 kB | 7.4 kB | ✓ |
webpack-e067..f178.js gzip | 751 B | 751 B | ✓ |
Overall change | 58.4 kB | 58.4 kB | ✓ |
Client Bundles (main, webpack, commons) Modern
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
677f882d2ed8..dule.js gzip | 7.04 kB | 7.04 kB | ✓ |
framework.HA..dule.js gzip | 39 kB | 39 kB | ✓ |
main-34e64ff..dule.js gzip | 6.39 kB | 6.39 kB | ✓ |
webpack-07c5..dule.js gzip | 751 B | 751 B | ✓ |
Overall change | 53.1 kB | 53.1 kB | ✓ |
Legacy Client Bundles (polyfills)
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
polyfills-4b..e242.js gzip | 31 kB | 31 kB | ✓ |
Overall change | 31 kB | 31 kB | ✓ |
Client Pages Overall increase ⚠️
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
_app-7231d4b..5856.js gzip | 1.28 kB | 1.28 kB | ✓ |
_error-fca3d..2eb1.js gzip | 3.44 kB | 3.44 kB | ✓ |
hooks-d4591d..e7c2.js gzip | 887 B | 887 B | ✓ |
index-17468f..5d83.js gzip | 227 B | 227 B | ✓ |
link-03d24c6..d1c7.js gzip | 1.35 kB | N/A | N/A |
routerDirect..924c.js gzip | 284 B | 284 B | ✓ |
withRouter-7..c13d.js gzip | 284 B | 284 B | ✓ |
link-8a9d104..0e42.js gzip | N/A | 1.55 kB | N/A |
Overall change | 7.75 kB | 7.96 kB |
Client Pages Modern Overall increase ⚠️
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
_app-75d3a82..dule.js gzip | 625 B | 625 B | ✓ |
_error-4469a..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-dfbbfbd..dule.js gzip | 1.32 kB | N/A | N/A |
routerDirect..dule.js gzip | 284 B | 284 B | ✓ |
withRouter-f..dule.js gzip | 282 B | 282 B | ✓ |
link-d1cfb87..dule.js gzip | N/A | 1.49 kB | N/A |
Overall change | 5.41 kB | 5.59 kB |
Client Build Manifests
vercel/next.js canary | Timer/next.js hotfix/link-updating | 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 hotfix/link-updating | Change | |
---|---|---|---|
_error.js | 914 kB | 914 kB | ✓ |
404.html | 4.73 kB | 4.73 kB | ✓ |
hooks.html | 3.92 kB | 3.92 kB | ✓ |
index.js | 914 kB | 914 kB | ✓ |
link.js | 962 kB | 963 kB | |
routerDirect.js | 956 kB | 956 kB | ✓ |
withRouter.js | 956 kB | 956 kB | ✓ |
Overall change | 4.71 MB | 4.71 MB |
Stats from current PRDefault Server Mode (Increase detected
|
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
buildDuration | 12.8s | 12.8s | -37ms |
nodeModulesSize | 84.9 MB | 84.9 MB | -1.11 kB |
Page Load Tests Overall increase ✓
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
/ failed reqs | 0 | 0 | ✓ |
/ total time (seconds) | 2.429 | 2.408 | -0.02 |
/ avg req/sec | 1029.24 | 1038.37 | +9.13 |
/error-in-render failed reqs | 0 | 0 | ✓ |
/error-in-render total time (seconds) | 1.339 | 1.28 | -0.06 |
/error-in-render avg req/sec | 1867.29 | 1953.83 | +86.54 |
Client Bundles (main, webpack, commons)
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
677f882d2ed8..7d3b.js gzip | 11.3 kB | 11.3 kB | ✓ |
framework.HASH.js gzip | 39 kB | 39 kB | ✓ |
main-d942eb5..343f.js gzip | 7.4 kB | 7.4 kB | ✓ |
webpack-e067..f178.js gzip | 751 B | 751 B | ✓ |
Overall change | 58.4 kB | 58.4 kB | ✓ |
Client Bundles (main, webpack, commons) Modern
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
677f882d2ed8..dule.js gzip | 7.04 kB | 7.04 kB | ✓ |
framework.HA..dule.js gzip | 39 kB | 39 kB | ✓ |
main-34e64ff..dule.js gzip | 6.39 kB | 6.39 kB | ✓ |
webpack-07c5..dule.js gzip | 751 B | 751 B | ✓ |
Overall change | 53.1 kB | 53.1 kB | ✓ |
Legacy Client Bundles (polyfills)
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
polyfills-4b..e242.js gzip | 31 kB | 31 kB | ✓ |
Overall change | 31 kB | 31 kB | ✓ |
Client Pages Overall increase ⚠️
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
_app-7231d4b..5856.js gzip | 1.28 kB | 1.28 kB | ✓ |
_error-fca3d..2eb1.js gzip | 3.44 kB | 3.44 kB | ✓ |
hooks-d4591d..e7c2.js gzip | 887 B | 887 B | ✓ |
index-17468f..5d83.js gzip | 227 B | 227 B | ✓ |
link-03d24c6..d1c7.js gzip | 1.35 kB | N/A | N/A |
routerDirect..924c.js gzip | 284 B | 284 B | ✓ |
withRouter-7..c13d.js gzip | 284 B | 284 B | ✓ |
link-8a9d104..0e42.js gzip | N/A | 1.55 kB | N/A |
Overall change | 7.75 kB | 7.96 kB |
Client Pages Modern Overall increase ⚠️
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
_app-75d3a82..dule.js gzip | 625 B | 625 B | ✓ |
_error-4469a..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-dfbbfbd..dule.js gzip | 1.32 kB | N/A | N/A |
routerDirect..dule.js gzip | 284 B | 284 B | ✓ |
withRouter-f..dule.js gzip | 282 B | 282 B | ✓ |
link-d1cfb87..dule.js gzip | N/A | 1.49 kB | N/A |
Overall change | 5.41 kB | 5.59 kB |
Client Build Manifests
vercel/next.js canary | Timer/next.js hotfix/link-updating | 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 hotfix/link-updating | Change | |
---|---|---|---|
index.html gzip | 1 kB | 1 kB | ✓ |
link.html gzip | 1.01 kB | 1.01 kB | |
withRouter.html gzip | 995 B | 995 B | ✓ |
Overall change | 3 kB | 3.01 kB |
Diffs
Diff for _buildManifest.js
@@ -7,7 +7,7 @@ self.__BUILD_MANIFEST = {
"/hooks": [
"static\u002Fchunks\u002Fpages\u002Fhooks-bdd2cad07648acf22380.js"
],
- "/link": ["static\u002Fchunks\u002Fpages\u002Flink-17a206ac5f5df2421f5d.js"],
+ "/link": ["static\u002Fchunks\u002Fpages\u002Flink-fcaf825022c62b02057c.js"],
"/routerDirect": [
"static\u002Fchunks\u002Fpages\u002FrouterDirect-2e9bfd441bd88cd3382e.js"
],
Diff for _buildManifest.module.js
@@ -10,7 +10,7 @@ self.__BUILD_MANIFEST = {
"static\u002Fchunks\u002Fpages\u002Fhooks-56fa58a6f0993d7d36d7.module.js"
],
"/link": [
- "static\u002Fchunks\u002Fpages\u002Flink-16d8635e170e01799dc1.module.js"
+ "static\u002Fchunks\u002Fpages\u002Flink-ec1fbf762c0209fe4b72.module.js"
],
"/routerDirect": [
"static\u002Fchunks\u002Fpages\u002FrouterDirect-368af3dfef3c9cd99dc3.module.js"
Diff for link-16d8635..c1.module.js
@@ -76,62 +76,9 @@
var _router2 = __webpack_require__("nOHt");
- var cachedObserver;
- var listeners = new Map();
- var IntersectionObserver = true ? window.IntersectionObserver : undefined;
- var prefetched = {};
-
- function getObserver() {
- // Return shared instance of IntersectionObserver if already created
- if (cachedObserver) {
- return cachedObserver;
- } // Only create shared IntersectionObserver if supported in browser
-
- if (!IntersectionObserver) {
- return undefined;
- }
-
- return (cachedObserver = new IntersectionObserver(
- entries => {
- entries.forEach(entry => {
- if (!listeners.has(entry.target)) {
- return;
- }
-
- var cb = listeners.get(entry.target);
-
- if (entry.isIntersecting || entry.intersectionRatio > 0) {
- cachedObserver.unobserve(entry.target);
- listeners.delete(entry.target);
- cb();
- }
- });
- },
- {
- rootMargin: "200px"
- }
- ));
- }
-
- var listenToIntersections = (el, cb) => {
- var observer = getObserver();
-
- if (!observer) {
- return () => {};
- }
+ var _useIntersection = __webpack_require__("vNVm");
- observer.observe(el);
- listeners.set(el, cb);
- return () => {
- try {
- observer.unobserve(el);
- } catch (err) {
- console.error(err);
- }
-
- listeners.delete(el);
- };
- };
+ var prefetched = {};
function prefetch(router, href, as, options) {
if (false) {
@@ -240,38 +187,14 @@
var child = _react.Children.only(children);
var childRef = child && typeof child === "object" && child.ref;
-
- var cleanup = _react.default.useRef();
+ var [setIntersectionRef, isVisible] = (0,
+ _useIntersection.useIntersection)({
+ rootMargin: "200px"
+ });
var setRef = _react.default.useCallback(
el => {
- // cleanup previous event handlers
- if (cleanup.current) {
- cleanup.current();
- cleanup.current = undefined;
- }
-
- if (
- p &&
- IntersectionObserver &&
- el &&
- el.tagName &&
- (0, _router.isLocalURL)(href)
- ) {
- // Join on an invalid URI character
- var isPrefetched = prefetched[href + "%" + as];
-
- if (!isPrefetched) {
- cleanup.current = listenToIntersections(el, () => {
- prefetch(router, href, as, {
- locale:
- typeof locale !== "undefined"
- ? locale
- : router && router.locale
- });
- });
- }
- }
+ setIntersectionRef(el);
if (childRef) {
if (typeof childRef === "function") childRef(el);
@@ -280,9 +203,20 @@
}
}
},
- [p, childRef, href, as, router, locale]
+ [childRef, setIntersectionRef]
);
+ (0, _react.useEffect)(() => {
+ var shouldPrefetch = isVisible && p && (0, _router.isLocalURL)(href);
+ var isPrefetched = prefetched[href + "%" + as];
+
+ if (shouldPrefetch && !isPrefetched) {
+ prefetch(router, href, as, {
+ locale:
+ typeof locale !== "undefined" ? locale : router && router.locale
+ });
+ }
+ }, [as, href, isVisible, locale, p, router]);
var childProps = {
ref: setRef,
onClick: e => {
@@ -337,6 +271,99 @@
var _default = Link;
exports.default = _default;
+ /***/
+ },
+
+ /***/ vNVm: /***/ function(module, exports, __webpack_require__) {
+ "use strict";
+
+ exports.__esModule = true;
+ exports.useIntersection = useIntersection;
+
+ var _react = __webpack_require__("q1tI");
+
+ var hasIntersectionObserver = typeof IntersectionObserver !== "undefined";
+
+ function useIntersection(_ref) {
+ var { rootMargin, disabled } = _ref;
+ var isDisabled = disabled || !hasIntersectionObserver;
+ var unobserve = (0, _react.useRef)();
+ var [visible, setVisible] = (0, _react.useState)(false);
+ var setRef = (0, _react.useCallback)(
+ el => {
+ if (unobserve.current) {
+ unobserve.current();
+ unobserve.current = undefined;
+ }
+
+ if (isDisabled || visible) return;
+
+ if (el && el.tagName) {
+ unobserve.current = observe(
+ el,
+ isVisible => isVisible && setVisible(isVisible),
+ {
+ rootMargin
+ }
+ );
+ }
+ },
+ [isDisabled, rootMargin, visible]
+ );
+ (0, _react.useEffect)(() => {
+ if (!hasIntersectionObserver) {
+ if (!visible) setVisible(true);
+ }
+ }, [visible]);
+ return [setRef, visible];
+ }
+
+ function observe(element, callback, options) {
+ var { id, observer, elements } = createObserver(options);
+ elements.set(element, callback);
+ observer.observe(element);
+ return function unobserve() {
+ observer.unobserve(element); // Destroy observer when there's nothing left to watch:
+
+ if (elements.size === 0) {
+ observer.disconnect();
+ observers.delete(id);
+ }
+ };
+ }
+
+ var observers = new Map();
+
+ function createObserver(options) {
+ var id = options.rootMargin || "";
+ var instance = observers.get(id);
+
+ if (instance) {
+ return instance;
+ }
+
+ var elements = new Map();
+ var observer = new IntersectionObserver(entries => {
+ entries.forEach(entry => {
+ var callback = elements.get(entry.target);
+ var isVisible = entry.isIntersecting || entry.intersectionRatio > 0;
+
+ if (callback && isVisible) {
+ callback(isVisible);
+ }
+ });
+ }, options);
+ observers.set(
+ id,
+ (instance = {
+ id,
+ observer,
+ elements
+ })
+ );
+ return instance;
+ }
+
/***/
}
},
Diff for link-17a206a..df2421f5d.js
@@ -80,62 +80,9 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var _router2 = __webpack_require__("nOHt");
- var cachedObserver;
- var listeners = new Map();
- var IntersectionObserver = true ? window.IntersectionObserver : undefined;
- var prefetched = {};
-
- function getObserver() {
- // Return shared instance of IntersectionObserver if already created
- if (cachedObserver) {
- return cachedObserver;
- } // Only create shared IntersectionObserver if supported in browser
-
- if (!IntersectionObserver) {
- return undefined;
- }
-
- return (cachedObserver = new IntersectionObserver(
- function(entries) {
- entries.forEach(function(entry) {
- if (!listeners.has(entry.target)) {
- return;
- }
-
- var cb = listeners.get(entry.target);
-
- if (entry.isIntersecting || entry.intersectionRatio > 0) {
- cachedObserver.unobserve(entry.target);
- listeners["delete"](entry.target);
- cb();
- }
- });
- },
- {
- rootMargin: "200px"
- }
- ));
- }
-
- var listenToIntersections = function listenToIntersections(el, cb) {
- var observer = getObserver();
-
- if (!observer) {
- return function() {};
- }
-
- observer.observe(el);
- listeners.set(el, cb);
- return function() {
- try {
- observer.unobserve(el);
- } catch (err) {
- console.error(err);
- }
+ var _useIntersection = __webpack_require__("vNVm");
- listeners["delete"](el);
- };
- };
+ var prefetched = {};
function prefetch(router, href, as, options) {
if (false) {
@@ -255,37 +202,16 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var childRef = child && typeof child === "object" && child.ref;
- var cleanup = _react["default"].useRef();
+ var _ref3 = (0, _useIntersection.useIntersection)({
+ rootMargin: "200px"
+ }),
+ _ref4 = _slicedToArray(_ref3, 2),
+ setIntersectionRef = _ref4[0],
+ isVisible = _ref4[1];
var setRef = _react["default"].useCallback(
function(el) {
- // cleanup previous event handlers
- if (cleanup.current) {
- cleanup.current();
- cleanup.current = undefined;
- }
-
- if (
- p &&
- IntersectionObserver &&
- el &&
- el.tagName &&
- (0, _router.isLocalURL)(href)
- ) {
- // Join on an invalid URI character
- var isPrefetched = prefetched[href + "%" + as];
-
- if (!isPrefetched) {
- cleanup.current = listenToIntersections(el, function() {
- prefetch(router, href, as, {
- locale:
- typeof locale !== "undefined"
- ? locale
- : router && router.locale
- });
- });
- }
- }
+ setIntersectionRef(el);
if (childRef) {
if (typeof childRef === "function") childRef(el);
@@ -294,9 +220,26 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
}
}
},
- [p, childRef, href, as, router, locale]
+ [childRef, setIntersectionRef]
);
+ (0, _react.useEffect)(
+ function() {
+ var shouldPrefetch =
+ isVisible && p && (0, _router.isLocalURL)(href);
+ var isPrefetched = prefetched[href + "%" + as];
+
+ if (shouldPrefetch && !isPrefetched) {
+ prefetch(router, href, as, {
+ locale:
+ typeof locale !== "undefined"
+ ? locale
+ : router && router.locale
+ });
+ }
+ },
+ [as, href, isVisible, locale, p, router]
+ );
var childProps = {
ref: setRef,
onClick: function onClick(e) {
@@ -351,6 +294,116 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var _default = Link;
exports["default"] = _default;
+ /***/
+ },
+
+ /***/ vNVm: /***/ function(module, exports, __webpack_require__) {
+ "use strict";
+
+ var _slicedToArray = __webpack_require__("J4zp");
+
+ exports.__esModule = true;
+ exports.useIntersection = useIntersection;
+
+ var _react = __webpack_require__("q1tI");
+
+ var hasIntersectionObserver = typeof IntersectionObserver !== "undefined";
+
+ function useIntersection(_ref) {
+ var rootMargin = _ref.rootMargin,
+ disabled = _ref.disabled;
+ var isDisabled = disabled || !hasIntersectionObserver;
+ var unobserve = (0, _react.useRef)();
+
+ var _ref2 = (0, _react.useState)(false),
+ _ref3 = _slicedToArray(_ref2, 2),
+ visible = _ref3[0],
+ setVisible = _ref3[1];
+
+ var setRef = (0, _react.useCallback)(
+ function(el) {
+ if (unobserve.current) {
+ unobserve.current();
+ unobserve.current = undefined;
+ }
+
+ if (isDisabled || visible) return;
+
+ if (el && el.tagName) {
+ unobserve.current = observe(
+ el,
+ function(isVisible) {
+ return isVisible && setVisible(isVisible);
+ },
+ {
+ rootMargin: rootMargin
+ }
+ );
+ }
+ },
+ [isDisabled, rootMargin, visible]
+ );
+ (0, _react.useEffect)(
+ function() {
+ if (!hasIntersectionObserver) {
+ if (!visible) setVisible(true);
+ }
+ },
+ [visible]
+ );
+ return [setRef, visible];
+ }
+
+ function observe(element, callback, options) {
+ var _createObserver = createObserver(options),
+ id = _createObserver.id,
+ observer = _createObserver.observer,
+ elements = _createObserver.elements;
+
+ elements.set(element, callback);
+ observer.observe(element);
+ return function unobserve() {
+ observer.unobserve(element); // Destroy observer when there's nothing left to watch:
+
+ if (elements.size === 0) {
+ observer.disconnect();
+ observers["delete"](id);
+ }
+ };
+ }
+
+ var observers = new Map();
+
+ function createObserver(options) {
+ var id = options.rootMargin || "";
+ var instance = observers.get(id);
+
+ if (instance) {
+ return instance;
+ }
+
+ var elements = new Map();
+ var observer = new IntersectionObserver(function(entries) {
+ entries.forEach(function(entry) {
+ var callback = elements.get(entry.target);
+ var isVisible = entry.isIntersecting || entry.intersectionRatio > 0;
+
+ if (callback && isVisible) {
+ callback(isVisible);
+ }
+ });
+ }, options);
+ observers.set(
+ id,
+ (instance = {
+ id: id,
+ observer: observer,
+ elements: elements
+ })
+ );
+ return instance;
+ }
+
/***/
}
},
Diff for link.html
@@ -36,7 +36,7 @@
/>
<link
rel="preload"
- href="/_next/static/chunks/pages/link-16d8635e170e01799dc1.module.js"
+ href="/_next/static/chunks/pages/link-ec1fbf762c0209fe4b72.module.js"
as="script"
crossorigin="anonymous"
/>
@@ -150,13 +150,13 @@
type="module"
></script>
<script
- src="/_next/static/chunks/pages/link-17a206ac5f5df2421f5d.js"
+ src="/_next/static/chunks/pages/link-fcaf825022c62b02057c.js"
async=""
crossorigin="anonymous"
nomodule=""
></script>
<script
- src="/_next/static/chunks/pages/link-16d8635e170e01799dc1.module.js"
+ src="/_next/static/chunks/pages/link-ec1fbf762c0209fe4b72.module.js"
async=""
crossorigin="anonymous"
type="module"
Serverless Mode (Increase detected ⚠️ )
General Overall decrease ✓
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
buildDuration | 14.1s | 14.4s | |
nodeModulesSize | 84.9 MB | 84.9 MB | -1.11 kB |
Client Bundles (main, webpack, commons)
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
677f882d2ed8..7d3b.js gzip | 11.3 kB | 11.3 kB | ✓ |
framework.HASH.js gzip | 39 kB | 39 kB | ✓ |
main-d942eb5..343f.js gzip | 7.4 kB | 7.4 kB | ✓ |
webpack-e067..f178.js gzip | 751 B | 751 B | ✓ |
Overall change | 58.4 kB | 58.4 kB | ✓ |
Client Bundles (main, webpack, commons) Modern
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
677f882d2ed8..dule.js gzip | 7.04 kB | 7.04 kB | ✓ |
framework.HA..dule.js gzip | 39 kB | 39 kB | ✓ |
main-34e64ff..dule.js gzip | 6.39 kB | 6.39 kB | ✓ |
webpack-07c5..dule.js gzip | 751 B | 751 B | ✓ |
Overall change | 53.1 kB | 53.1 kB | ✓ |
Legacy Client Bundles (polyfills)
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
polyfills-4b..e242.js gzip | 31 kB | 31 kB | ✓ |
Overall change | 31 kB | 31 kB | ✓ |
Client Pages Overall increase ⚠️
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
_app-7231d4b..5856.js gzip | 1.28 kB | 1.28 kB | ✓ |
_error-fca3d..2eb1.js gzip | 3.44 kB | 3.44 kB | ✓ |
hooks-d4591d..e7c2.js gzip | 887 B | 887 B | ✓ |
index-17468f..5d83.js gzip | 227 B | 227 B | ✓ |
link-03d24c6..d1c7.js gzip | 1.35 kB | N/A | N/A |
routerDirect..924c.js gzip | 284 B | 284 B | ✓ |
withRouter-7..c13d.js gzip | 284 B | 284 B | ✓ |
link-8a9d104..0e42.js gzip | N/A | 1.55 kB | N/A |
Overall change | 7.75 kB | 7.96 kB |
Client Pages Modern Overall increase ⚠️
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
_app-75d3a82..dule.js gzip | 625 B | 625 B | ✓ |
_error-4469a..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-dfbbfbd..dule.js gzip | 1.32 kB | N/A | N/A |
routerDirect..dule.js gzip | 284 B | 284 B | ✓ |
withRouter-f..dule.js gzip | 282 B | 282 B | ✓ |
link-d1cfb87..dule.js gzip | N/A | 1.49 kB | N/A |
Overall change | 5.41 kB | 5.59 kB |
Client Build Manifests
vercel/next.js canary | Timer/next.js hotfix/link-updating | 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 hotfix/link-updating | Change | |
---|---|---|---|
_error.js | 914 kB | 914 kB | ✓ |
404.html | 4.73 kB | 4.73 kB | ✓ |
hooks.html | 3.92 kB | 3.92 kB | ✓ |
index.js | 914 kB | 914 kB | ✓ |
link.js | 962 kB | 963 kB | |
routerDirect.js | 956 kB | 956 kB | ✓ |
withRouter.js | 956 kB | 956 kB | ✓ |
Overall change | 4.71 MB | 4.71 MB |
styfle
approved these changes
Nov 6, 2020
ijjk
approved these changes
Nov 6, 2020
Stats from current PRDefault Server Mode (Increase detected
|
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
buildDuration | 14.7s | 15.1s | |
nodeModulesSize | 84.9 MB | 84.9 MB | -1.11 kB |
Page Load Tests Overall decrease ⚠️
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
/ failed reqs | 0 | 0 | ✓ |
/ total time (seconds) | 2.865 | 2.91 | |
/ avg req/sec | 872.73 | 859 | |
/error-in-render failed reqs | 0 | 0 | ✓ |
/error-in-render total time (seconds) | 1.75 | 1.746 | 0 |
/error-in-render avg req/sec | 1428.88 | 1432.1 | +3.22 |
Client Bundles (main, webpack, commons)
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
677f882d2ed8..7d3b.js gzip | 11.3 kB | 11.3 kB | ✓ |
framework.HASH.js gzip | 39 kB | 39 kB | ✓ |
main-d942eb5..343f.js gzip | 7.4 kB | 7.4 kB | ✓ |
webpack-e067..f178.js gzip | 751 B | 751 B | ✓ |
Overall change | 58.4 kB | 58.4 kB | ✓ |
Client Bundles (main, webpack, commons) Modern
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
677f882d2ed8..dule.js gzip | 7.04 kB | 7.04 kB | ✓ |
framework.HA..dule.js gzip | 39 kB | 39 kB | ✓ |
main-34e64ff..dule.js gzip | 6.39 kB | 6.39 kB | ✓ |
webpack-07c5..dule.js gzip | 751 B | 751 B | ✓ |
Overall change | 53.1 kB | 53.1 kB | ✓ |
Legacy Client Bundles (polyfills)
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
polyfills-4b..e242.js gzip | 31 kB | 31 kB | ✓ |
Overall change | 31 kB | 31 kB | ✓ |
Client Pages Overall increase ⚠️
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
_app-7231d4b..5856.js gzip | 1.28 kB | 1.28 kB | ✓ |
_error-fca3d..2eb1.js gzip | 3.44 kB | 3.44 kB | ✓ |
hooks-d4591d..e7c2.js gzip | 887 B | 887 B | ✓ |
index-17468f..5d83.js gzip | 227 B | 227 B | ✓ |
link-03d24c6..d1c7.js gzip | 1.35 kB | N/A | N/A |
routerDirect..924c.js gzip | 284 B | 284 B | ✓ |
withRouter-7..c13d.js gzip | 284 B | 284 B | ✓ |
link-8a9d104..0e42.js gzip | N/A | 1.55 kB | N/A |
Overall change | 7.75 kB | 7.96 kB |
Client Pages Modern Overall increase ⚠️
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
_app-75d3a82..dule.js gzip | 625 B | 625 B | ✓ |
_error-4469a..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-dfbbfbd..dule.js gzip | 1.32 kB | N/A | N/A |
routerDirect..dule.js gzip | 284 B | 284 B | ✓ |
withRouter-f..dule.js gzip | 282 B | 282 B | ✓ |
link-d1cfb87..dule.js gzip | N/A | 1.49 kB | N/A |
Overall change | 5.41 kB | 5.59 kB |
Client Build Manifests
vercel/next.js canary | Timer/next.js hotfix/link-updating | 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 hotfix/link-updating | Change | |
---|---|---|---|
index.html gzip | 1 kB | 1 kB | ✓ |
link.html gzip | 1.01 kB | 1.01 kB | |
withRouter.html gzip | 995 B | 995 B | ✓ |
Overall change | 3 kB | 3.01 kB |
Diffs
Diff for _buildManifest.js
@@ -7,7 +7,7 @@ self.__BUILD_MANIFEST = {
"/hooks": [
"static\u002Fchunks\u002Fpages\u002Fhooks-bdd2cad07648acf22380.js"
],
- "/link": ["static\u002Fchunks\u002Fpages\u002Flink-17a206ac5f5df2421f5d.js"],
+ "/link": ["static\u002Fchunks\u002Fpages\u002Flink-fcaf825022c62b02057c.js"],
"/routerDirect": [
"static\u002Fchunks\u002Fpages\u002FrouterDirect-2e9bfd441bd88cd3382e.js"
],
Diff for _buildManifest.module.js
@@ -10,7 +10,7 @@ self.__BUILD_MANIFEST = {
"static\u002Fchunks\u002Fpages\u002Fhooks-56fa58a6f0993d7d36d7.module.js"
],
"/link": [
- "static\u002Fchunks\u002Fpages\u002Flink-16d8635e170e01799dc1.module.js"
+ "static\u002Fchunks\u002Fpages\u002Flink-ec1fbf762c0209fe4b72.module.js"
],
"/routerDirect": [
"static\u002Fchunks\u002Fpages\u002FrouterDirect-368af3dfef3c9cd99dc3.module.js"
Diff for link-16d8635..c1.module.js
@@ -76,62 +76,9 @@
var _router2 = __webpack_require__("nOHt");
- var cachedObserver;
- var listeners = new Map();
- var IntersectionObserver = true ? window.IntersectionObserver : undefined;
- var prefetched = {};
-
- function getObserver() {
- // Return shared instance of IntersectionObserver if already created
- if (cachedObserver) {
- return cachedObserver;
- } // Only create shared IntersectionObserver if supported in browser
-
- if (!IntersectionObserver) {
- return undefined;
- }
-
- return (cachedObserver = new IntersectionObserver(
- entries => {
- entries.forEach(entry => {
- if (!listeners.has(entry.target)) {
- return;
- }
-
- var cb = listeners.get(entry.target);
-
- if (entry.isIntersecting || entry.intersectionRatio > 0) {
- cachedObserver.unobserve(entry.target);
- listeners.delete(entry.target);
- cb();
- }
- });
- },
- {
- rootMargin: "200px"
- }
- ));
- }
-
- var listenToIntersections = (el, cb) => {
- var observer = getObserver();
-
- if (!observer) {
- return () => {};
- }
+ var _useIntersection = __webpack_require__("vNVm");
- observer.observe(el);
- listeners.set(el, cb);
- return () => {
- try {
- observer.unobserve(el);
- } catch (err) {
- console.error(err);
- }
-
- listeners.delete(el);
- };
- };
+ var prefetched = {};
function prefetch(router, href, as, options) {
if (false) {
@@ -240,38 +187,14 @@
var child = _react.Children.only(children);
var childRef = child && typeof child === "object" && child.ref;
-
- var cleanup = _react.default.useRef();
+ var [setIntersectionRef, isVisible] = (0,
+ _useIntersection.useIntersection)({
+ rootMargin: "200px"
+ });
var setRef = _react.default.useCallback(
el => {
- // cleanup previous event handlers
- if (cleanup.current) {
- cleanup.current();
- cleanup.current = undefined;
- }
-
- if (
- p &&
- IntersectionObserver &&
- el &&
- el.tagName &&
- (0, _router.isLocalURL)(href)
- ) {
- // Join on an invalid URI character
- var isPrefetched = prefetched[href + "%" + as];
-
- if (!isPrefetched) {
- cleanup.current = listenToIntersections(el, () => {
- prefetch(router, href, as, {
- locale:
- typeof locale !== "undefined"
- ? locale
- : router && router.locale
- });
- });
- }
- }
+ setIntersectionRef(el);
if (childRef) {
if (typeof childRef === "function") childRef(el);
@@ -280,9 +203,20 @@
}
}
},
- [p, childRef, href, as, router, locale]
+ [childRef, setIntersectionRef]
);
+ (0, _react.useEffect)(() => {
+ var shouldPrefetch = isVisible && p && (0, _router.isLocalURL)(href);
+ var isPrefetched = prefetched[href + "%" + as];
+
+ if (shouldPrefetch && !isPrefetched) {
+ prefetch(router, href, as, {
+ locale:
+ typeof locale !== "undefined" ? locale : router && router.locale
+ });
+ }
+ }, [as, href, isVisible, locale, p, router]);
var childProps = {
ref: setRef,
onClick: e => {
@@ -337,6 +271,99 @@
var _default = Link;
exports.default = _default;
+ /***/
+ },
+
+ /***/ vNVm: /***/ function(module, exports, __webpack_require__) {
+ "use strict";
+
+ exports.__esModule = true;
+ exports.useIntersection = useIntersection;
+
+ var _react = __webpack_require__("q1tI");
+
+ var hasIntersectionObserver = typeof IntersectionObserver !== "undefined";
+
+ function useIntersection(_ref) {
+ var { rootMargin, disabled } = _ref;
+ var isDisabled = disabled || !hasIntersectionObserver;
+ var unobserve = (0, _react.useRef)();
+ var [visible, setVisible] = (0, _react.useState)(false);
+ var setRef = (0, _react.useCallback)(
+ el => {
+ if (unobserve.current) {
+ unobserve.current();
+ unobserve.current = undefined;
+ }
+
+ if (isDisabled || visible) return;
+
+ if (el && el.tagName) {
+ unobserve.current = observe(
+ el,
+ isVisible => isVisible && setVisible(isVisible),
+ {
+ rootMargin
+ }
+ );
+ }
+ },
+ [isDisabled, rootMargin, visible]
+ );
+ (0, _react.useEffect)(() => {
+ if (!hasIntersectionObserver) {
+ if (!visible) setVisible(true);
+ }
+ }, [visible]);
+ return [setRef, visible];
+ }
+
+ function observe(element, callback, options) {
+ var { id, observer, elements } = createObserver(options);
+ elements.set(element, callback);
+ observer.observe(element);
+ return function unobserve() {
+ observer.unobserve(element); // Destroy observer when there's nothing left to watch:
+
+ if (elements.size === 0) {
+ observer.disconnect();
+ observers.delete(id);
+ }
+ };
+ }
+
+ var observers = new Map();
+
+ function createObserver(options) {
+ var id = options.rootMargin || "";
+ var instance = observers.get(id);
+
+ if (instance) {
+ return instance;
+ }
+
+ var elements = new Map();
+ var observer = new IntersectionObserver(entries => {
+ entries.forEach(entry => {
+ var callback = elements.get(entry.target);
+ var isVisible = entry.isIntersecting || entry.intersectionRatio > 0;
+
+ if (callback && isVisible) {
+ callback(isVisible);
+ }
+ });
+ }, options);
+ observers.set(
+ id,
+ (instance = {
+ id,
+ observer,
+ elements
+ })
+ );
+ return instance;
+ }
+
/***/
}
},
Diff for link-17a206a..df2421f5d.js
@@ -80,62 +80,9 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var _router2 = __webpack_require__("nOHt");
- var cachedObserver;
- var listeners = new Map();
- var IntersectionObserver = true ? window.IntersectionObserver : undefined;
- var prefetched = {};
-
- function getObserver() {
- // Return shared instance of IntersectionObserver if already created
- if (cachedObserver) {
- return cachedObserver;
- } // Only create shared IntersectionObserver if supported in browser
-
- if (!IntersectionObserver) {
- return undefined;
- }
-
- return (cachedObserver = new IntersectionObserver(
- function(entries) {
- entries.forEach(function(entry) {
- if (!listeners.has(entry.target)) {
- return;
- }
-
- var cb = listeners.get(entry.target);
-
- if (entry.isIntersecting || entry.intersectionRatio > 0) {
- cachedObserver.unobserve(entry.target);
- listeners["delete"](entry.target);
- cb();
- }
- });
- },
- {
- rootMargin: "200px"
- }
- ));
- }
-
- var listenToIntersections = function listenToIntersections(el, cb) {
- var observer = getObserver();
-
- if (!observer) {
- return function() {};
- }
-
- observer.observe(el);
- listeners.set(el, cb);
- return function() {
- try {
- observer.unobserve(el);
- } catch (err) {
- console.error(err);
- }
+ var _useIntersection = __webpack_require__("vNVm");
- listeners["delete"](el);
- };
- };
+ var prefetched = {};
function prefetch(router, href, as, options) {
if (false) {
@@ -255,37 +202,16 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var childRef = child && typeof child === "object" && child.ref;
- var cleanup = _react["default"].useRef();
+ var _ref3 = (0, _useIntersection.useIntersection)({
+ rootMargin: "200px"
+ }),
+ _ref4 = _slicedToArray(_ref3, 2),
+ setIntersectionRef = _ref4[0],
+ isVisible = _ref4[1];
var setRef = _react["default"].useCallback(
function(el) {
- // cleanup previous event handlers
- if (cleanup.current) {
- cleanup.current();
- cleanup.current = undefined;
- }
-
- if (
- p &&
- IntersectionObserver &&
- el &&
- el.tagName &&
- (0, _router.isLocalURL)(href)
- ) {
- // Join on an invalid URI character
- var isPrefetched = prefetched[href + "%" + as];
-
- if (!isPrefetched) {
- cleanup.current = listenToIntersections(el, function() {
- prefetch(router, href, as, {
- locale:
- typeof locale !== "undefined"
- ? locale
- : router && router.locale
- });
- });
- }
- }
+ setIntersectionRef(el);
if (childRef) {
if (typeof childRef === "function") childRef(el);
@@ -294,9 +220,26 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
}
}
},
- [p, childRef, href, as, router, locale]
+ [childRef, setIntersectionRef]
);
+ (0, _react.useEffect)(
+ function() {
+ var shouldPrefetch =
+ isVisible && p && (0, _router.isLocalURL)(href);
+ var isPrefetched = prefetched[href + "%" + as];
+
+ if (shouldPrefetch && !isPrefetched) {
+ prefetch(router, href, as, {
+ locale:
+ typeof locale !== "undefined"
+ ? locale
+ : router && router.locale
+ });
+ }
+ },
+ [as, href, isVisible, locale, p, router]
+ );
var childProps = {
ref: setRef,
onClick: function onClick(e) {
@@ -351,6 +294,116 @@ _N_E = (window["webpackJsonp_N_E"] = window["webpackJsonp_N_E"] || []).push([
var _default = Link;
exports["default"] = _default;
+ /***/
+ },
+
+ /***/ vNVm: /***/ function(module, exports, __webpack_require__) {
+ "use strict";
+
+ var _slicedToArray = __webpack_require__("J4zp");
+
+ exports.__esModule = true;
+ exports.useIntersection = useIntersection;
+
+ var _react = __webpack_require__("q1tI");
+
+ var hasIntersectionObserver = typeof IntersectionObserver !== "undefined";
+
+ function useIntersection(_ref) {
+ var rootMargin = _ref.rootMargin,
+ disabled = _ref.disabled;
+ var isDisabled = disabled || !hasIntersectionObserver;
+ var unobserve = (0, _react.useRef)();
+
+ var _ref2 = (0, _react.useState)(false),
+ _ref3 = _slicedToArray(_ref2, 2),
+ visible = _ref3[0],
+ setVisible = _ref3[1];
+
+ var setRef = (0, _react.useCallback)(
+ function(el) {
+ if (unobserve.current) {
+ unobserve.current();
+ unobserve.current = undefined;
+ }
+
+ if (isDisabled || visible) return;
+
+ if (el && el.tagName) {
+ unobserve.current = observe(
+ el,
+ function(isVisible) {
+ return isVisible && setVisible(isVisible);
+ },
+ {
+ rootMargin: rootMargin
+ }
+ );
+ }
+ },
+ [isDisabled, rootMargin, visible]
+ );
+ (0, _react.useEffect)(
+ function() {
+ if (!hasIntersectionObserver) {
+ if (!visible) setVisible(true);
+ }
+ },
+ [visible]
+ );
+ return [setRef, visible];
+ }
+
+ function observe(element, callback, options) {
+ var _createObserver = createObserver(options),
+ id = _createObserver.id,
+ observer = _createObserver.observer,
+ elements = _createObserver.elements;
+
+ elements.set(element, callback);
+ observer.observe(element);
+ return function unobserve() {
+ observer.unobserve(element); // Destroy observer when there's nothing left to watch:
+
+ if (elements.size === 0) {
+ observer.disconnect();
+ observers["delete"](id);
+ }
+ };
+ }
+
+ var observers = new Map();
+
+ function createObserver(options) {
+ var id = options.rootMargin || "";
+ var instance = observers.get(id);
+
+ if (instance) {
+ return instance;
+ }
+
+ var elements = new Map();
+ var observer = new IntersectionObserver(function(entries) {
+ entries.forEach(function(entry) {
+ var callback = elements.get(entry.target);
+ var isVisible = entry.isIntersecting || entry.intersectionRatio > 0;
+
+ if (callback && isVisible) {
+ callback(isVisible);
+ }
+ });
+ }, options);
+ observers.set(
+ id,
+ (instance = {
+ id: id,
+ observer: observer,
+ elements: elements
+ })
+ );
+ return instance;
+ }
+
/***/
}
},
Diff for link.html
@@ -36,7 +36,7 @@
/>
<link
rel="preload"
- href="/_next/static/chunks/pages/link-16d8635e170e01799dc1.module.js"
+ href="/_next/static/chunks/pages/link-ec1fbf762c0209fe4b72.module.js"
as="script"
crossorigin="anonymous"
/>
@@ -150,13 +150,13 @@
type="module"
></script>
<script
- src="/_next/static/chunks/pages/link-17a206ac5f5df2421f5d.js"
+ src="/_next/static/chunks/pages/link-fcaf825022c62b02057c.js"
async=""
crossorigin="anonymous"
nomodule=""
></script>
<script
- src="/_next/static/chunks/pages/link-16d8635e170e01799dc1.module.js"
+ src="/_next/static/chunks/pages/link-ec1fbf762c0209fe4b72.module.js"
async=""
crossorigin="anonymous"
type="module"
Serverless Mode (Increase detected ⚠️ )
General Overall decrease ✓
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
buildDuration | 16.8s | 16.8s | -22ms |
nodeModulesSize | 84.9 MB | 84.9 MB | -1.11 kB |
Client Bundles (main, webpack, commons)
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
677f882d2ed8..7d3b.js gzip | 11.3 kB | 11.3 kB | ✓ |
framework.HASH.js gzip | 39 kB | 39 kB | ✓ |
main-d942eb5..343f.js gzip | 7.4 kB | 7.4 kB | ✓ |
webpack-e067..f178.js gzip | 751 B | 751 B | ✓ |
Overall change | 58.4 kB | 58.4 kB | ✓ |
Client Bundles (main, webpack, commons) Modern
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
677f882d2ed8..dule.js gzip | 7.04 kB | 7.04 kB | ✓ |
framework.HA..dule.js gzip | 39 kB | 39 kB | ✓ |
main-34e64ff..dule.js gzip | 6.39 kB | 6.39 kB | ✓ |
webpack-07c5..dule.js gzip | 751 B | 751 B | ✓ |
Overall change | 53.1 kB | 53.1 kB | ✓ |
Legacy Client Bundles (polyfills)
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
polyfills-4b..e242.js gzip | 31 kB | 31 kB | ✓ |
Overall change | 31 kB | 31 kB | ✓ |
Client Pages Overall increase ⚠️
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
_app-7231d4b..5856.js gzip | 1.28 kB | 1.28 kB | ✓ |
_error-fca3d..2eb1.js gzip | 3.44 kB | 3.44 kB | ✓ |
hooks-d4591d..e7c2.js gzip | 887 B | 887 B | ✓ |
index-17468f..5d83.js gzip | 227 B | 227 B | ✓ |
link-03d24c6..d1c7.js gzip | 1.35 kB | N/A | N/A |
routerDirect..924c.js gzip | 284 B | 284 B | ✓ |
withRouter-7..c13d.js gzip | 284 B | 284 B | ✓ |
link-8a9d104..0e42.js gzip | N/A | 1.55 kB | N/A |
Overall change | 7.75 kB | 7.96 kB |
Client Pages Modern Overall increase ⚠️
vercel/next.js canary | Timer/next.js hotfix/link-updating | Change | |
---|---|---|---|
_app-75d3a82..dule.js gzip | 625 B | 625 B | ✓ |
_error-4469a..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-dfbbfbd..dule.js gzip | 1.32 kB | N/A | N/A |
routerDirect..dule.js gzip | 284 B | 284 B | ✓ |
withRouter-f..dule.js gzip | 282 B | 282 B | ✓ |
link-d1cfb87..dule.js gzip | N/A | 1.49 kB | N/A |
Overall change | 5.41 kB | 5.59 kB |
Client Build Manifests
vercel/next.js canary | Timer/next.js hotfix/link-updating | 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 hotfix/link-updating | Change | |
---|---|---|---|
_error.js | 914 kB | 914 kB | ✓ |
404.html | 4.73 kB | 4.73 kB | ✓ |
hooks.html | 3.92 kB | 3.92 kB | ✓ |
index.js | 914 kB | 914 kB | ✓ |
link.js | 962 kB | 963 kB | |
routerDirect.js | 956 kB | 956 kB | ✓ |
withRouter.js | 956 kB | 956 kB | ✓ |
Overall change | 4.71 MB | 4.71 MB |
@Timer would it be possible to make use of |
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This pull request fixes
<Image />
not updating when new props are passed by removing external DOM mutations and relying on React to do it instead.As an added bonus, I've extracted the intersection observer from both the
<Image />
and<Link />
component, as their instance can be shared!The increase in size is minor (+3B), and actually a decrease for apps using both
<Image />
and<Link />
.Fixes #18698
Fixes #18369