From f9f0a99fa97b5d2821ea3dde25eb8c59e465494e Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Tue, 18 Feb 2020 14:49:48 -0600 Subject: [PATCH 1/3] Make sure to handle rejection when prefetching pages --- packages/next/client/link.tsx | 5 ++++- .../preload-viewport/pages/invalid-prefetch.js | 9 +++++++++ .../preload-viewport/test/index.test.js | 15 +++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 test/integration/preload-viewport/pages/invalid-prefetch.js diff --git a/packages/next/client/link.tsx b/packages/next/client/link.tsx index d45531791a95f30..ae938044b51f70c 100644 --- a/packages/next/client/link.tsx +++ b/packages/next/client/link.tsx @@ -209,7 +209,10 @@ class Link extends Component { if (!this.p || typeof window === 'undefined') return // Prefetch the JSON page if asked (only in the client) const [href, asPath] = this.getPaths() - Router.prefetch(href, asPath, options) + // make sure to catch here since we should have an unhandledRejection + // since we're doing this automatically and we don't want to reload the + // page while automatically prefetching for the user + Router.prefetch(href, asPath, options).catch(() => {}) prefetched[href] = true } diff --git a/test/integration/preload-viewport/pages/invalid-prefetch.js b/test/integration/preload-viewport/pages/invalid-prefetch.js new file mode 100644 index 000000000000000..a01f7638d841d1e --- /dev/null +++ b/test/integration/preload-viewport/pages/invalid-prefetch.js @@ -0,0 +1,9 @@ +import Link from 'next/link' + +export default () => ( + <> + + I'm broken... + + +) diff --git a/test/integration/preload-viewport/test/index.test.js b/test/integration/preload-viewport/test/index.test.js index 81b035e2dbe8541..0df30ea2464f50e 100644 --- a/test/integration/preload-viewport/test/index.test.js +++ b/test/integration/preload-viewport/test/index.test.js @@ -163,6 +163,21 @@ describe('Prefetching Links in viewport', () => { } }) + it('should not have unhandledRejection when failing to prefetch on link', async () => { + const browser = await webdriver(appPort, '/') + await browser.eval(`(function() { + window.addEventListener('unhandledrejection', function (err) { + window.hadUnhandledReject = true; + }) + window.next.router.push('/invalid-prefetch'); + })()`) + + expect(await browser.eval('window.hadUnhandledReject')).toBeFalsy() + + await browser.elementByCss('#invalid-link').moveTo() + expect(await browser.eval('window.hadUnhandledReject')).toBeFalsy() + }) + it('should not prefetch when prefetch is explicitly set to false', async () => { const browser = await webdriver(appPort, '/opt-out') From c5508c4f997ac33074b71c97a14c9427f2a79546 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Tue, 18 Feb 2020 14:52:42 -0600 Subject: [PATCH 2/3] Update comment --- packages/next/client/link.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/next/client/link.tsx b/packages/next/client/link.tsx index ae938044b51f70c..0abf7018cb5877d 100644 --- a/packages/next/client/link.tsx +++ b/packages/next/client/link.tsx @@ -209,9 +209,10 @@ class Link extends Component { if (!this.p || typeof window === 'undefined') return // Prefetch the JSON page if asked (only in the client) const [href, asPath] = this.getPaths() - // make sure to catch here since we should have an unhandledRejection + // make sure to catch here since we should handle an unhandledRejection // since we're doing this automatically and we don't want to reload the - // page while automatically prefetching for the user + // page while automatically prefetching for the user and this only occurs + // when doing an actual navigation Router.prefetch(href, asPath, options).catch(() => {}) prefetched[href] = true } From a5f13f2234bb6f611a83a7846755c16dddcda1ff Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Tue, 18 Feb 2020 15:10:58 -0600 Subject: [PATCH 3/3] Make sure to show prefetch error in development still --- packages/next/client/link.tsx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/next/client/link.tsx b/packages/next/client/link.tsx index 0abf7018cb5877d..9f846681accb0d1 100644 --- a/packages/next/client/link.tsx +++ b/packages/next/client/link.tsx @@ -209,11 +209,15 @@ class Link extends Component { if (!this.p || typeof window === 'undefined') return // Prefetch the JSON page if asked (only in the client) const [href, asPath] = this.getPaths() - // make sure to catch here since we should handle an unhandledRejection - // since we're doing this automatically and we don't want to reload the - // page while automatically prefetching for the user and this only occurs - // when doing an actual navigation - Router.prefetch(href, asPath, options).catch(() => {}) + // We need to handle a prefetch error here since we may be + // loading with priority which can reject but we don't + // want to force navigation since this is only a prefetch + Router.prefetch(href, asPath, options).catch(err => { + if (process.env.NODE_ENV !== 'production') { + // rethrow to show invalid URL errors + throw err + } + }) prefetched[href] = true }