Skip to content

Commit

Permalink
Merge branch 'canary' into remove-some-ts-ignores
Browse files Browse the repository at this point in the history
  • Loading branch information
Timer authored Feb 17, 2020
2 parents 80a99cf + f4c5a95 commit c62cd23
Show file tree
Hide file tree
Showing 13 changed files with 92 additions and 36 deletions.
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@
"registry": "https://registry.npmjs.org/"
}
},
"version": "9.2.2-canary.21"
"version": "9.2.2-canary.22"
}
2 changes: 1 addition & 1 deletion packages/create-next-app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "create-next-app",
"version": "9.2.2-canary.21",
"version": "9.2.2-canary.22",
"keywords": [
"react",
"next",
Expand Down
2 changes: 1 addition & 1 deletion packages/next-bundle-analyzer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/bundle-analyzer",
"version": "9.2.2-canary.21",
"version": "9.2.2-canary.22",
"main": "index.js",
"license": "MIT",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/next-mdx/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/mdx",
"version": "9.2.2-canary.21",
"version": "9.2.2-canary.22",
"main": "index.js",
"license": "MIT",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/next-plugin-google-analytics/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/plugin-google-analytics",
"version": "9.2.2-canary.21",
"version": "9.2.2-canary.22",
"nextjs": {
"name": "Google Analytics",
"required-env": [
Expand Down
2 changes: 1 addition & 1 deletion packages/next-plugin-material-ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/plugin-material-ui",
"version": "9.2.2-canary.21",
"version": "9.2.2-canary.22",
"nextjs": {
"name": "Material UI",
"required-env": []
Expand Down
2 changes: 1 addition & 1 deletion packages/next-plugin-sentry/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/plugin-sentry",
"version": "9.2.2-canary.21",
"version": "9.2.2-canary.22",
"nextjs": {
"name": "Sentry",
"required-env": [
Expand Down
2 changes: 1 addition & 1 deletion packages/next-polyfill-nomodule/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/polyfill-nomodule",
"version": "9.2.2-canary.21",
"version": "9.2.2-canary.22",
"description": "A polyfill for non-dead, nomodule browsers.",
"main": "dist/polyfill-nomodule.js",
"license": "MIT",
Expand Down
27 changes: 16 additions & 11 deletions packages/next/client/link.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
declare const __NEXT_DATA__: any

import { resolve, parse, UrlObject } from 'url'
import React, { Component, Children } from 'react'
import Router from './router'
import React, { Children, Component } from 'react'
import { parse, resolve, UrlObject } from 'url'
import { PrefetchOptions } from '../next-server/lib/router/router'
import {
execOnce,
formatWithValidation,
getLocationOrigin,
} from '../next-server/lib/utils'
import Router from './router'

function isLocal(href: string) {
const url = parse(href, false, true)
Expand Down Expand Up @@ -127,14 +128,18 @@ class Link extends Component<LinkProps> {
this.cleanUpListeners()
}

getHref() {
getPaths() {
const { pathname } = window.location
const { href: parsedHref } = this.formatUrls(this.props.href, this.props.as)
return resolve(pathname, parsedHref)
const { href: parsedHref, as: parsedAs } = this.formatUrls(
this.props.href,
this.props.as
)
const resolvedHref = resolve(pathname, parsedHref)
return [resolvedHref, parsedAs ? resolve(pathname, parsedAs) : resolvedHref]
}

handleRef(ref: Element) {
const isPrefetched = prefetched[this.getHref()]
const isPrefetched = prefetched[this.getPaths()[0]]
if (this.p && IntersectionObserver && ref && ref.tagName) {
this.cleanUpListeners()

Expand Down Expand Up @@ -200,11 +205,11 @@ class Link extends Component<LinkProps> {
})
}

prefetch() {
prefetch(options?: PrefetchOptions) {
if (!this.p || typeof window === 'undefined') return
// Prefetch the JSON page if asked (only in the client)
const href = this.getHref()
Router.prefetch(href)
const [href, asPath] = this.getPaths()
Router.prefetch(href, asPath, options)
prefetched[href] = true
}

Expand Down Expand Up @@ -238,7 +243,7 @@ class Link extends Component<LinkProps> {
if (child.props && typeof child.props.onMouseEnter === 'function') {
child.props.onMouseEnter(e)
}
this.prefetch()
this.prefetch({ priority: true })
},
onClick: (e: React.MouseEvent) => {
if (child.props && typeof child.props.onClick === 'function') {
Expand Down
21 changes: 15 additions & 6 deletions packages/next/next-server/lib/router/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import { ParsedUrlQuery } from 'querystring'
import { ComponentType } from 'react'
import { parse, UrlObject } from 'url'

import mitt, { MittEmitter } from '../mitt'
import {
AppContextType,
Expand Down Expand Up @@ -52,6 +51,10 @@ export type NextRouter = BaseRouter &
| 'isFallback'
>

export type PrefetchOptions = {
priority?: boolean
}

type RouteInfo = {
Component: ComponentType
props?: any
Expand Down Expand Up @@ -666,11 +669,16 @@ export default class Router implements BaseRouter {
}

/**
* Prefetch `page` code, you may wait for the data during `page` rendering.
* Prefetch page code, you may wait for the data during page rendering.
* This feature only works in production!
* @param url of prefetched `page`
* @param url the href of prefetched page
* @param asPath the as path of the prefetched page
*/
prefetch(url: string): Promise<void> {
prefetch(
url: string,
asPath: string = url,
options: PrefetchOptions = {}
): Promise<void> {
return new Promise((resolve, reject) => {
const { pathname, protocol } = parse(url)

Expand All @@ -688,8 +696,9 @@ export default class Router implements BaseRouter {
return
}

const route = toRoute(pathname)
this.pageLoader.prefetch(route).then(resolve, reject)
this.pageLoader[options.priority ? 'loadPage' : 'prefetch'](
toRoute(pathname)
).then(() => resolve(), reject)
})
}

Expand Down
4 changes: 2 additions & 2 deletions packages/next/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "next",
"version": "9.2.2-canary.21",
"version": "9.2.2-canary.22",
"description": "The React Framework",
"main": "./dist/server/next.js",
"license": "MIT",
Expand Down Expand Up @@ -73,7 +73,7 @@
"@babel/preset-typescript": "7.7.2",
"@babel/runtime": "7.7.2",
"@babel/runtime-corejs2": "7.7.2",
"@next/polyfill-nomodule": "9.2.2-canary.21",
"@next/polyfill-nomodule": "9.2.2-canary.22",
"amphtml-validator": "1.0.23",
"async-retry": "1.2.3",
"async-sema": "3.0.0",
Expand Down
2 changes: 1 addition & 1 deletion test/integration/preload-viewport/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default () => {
/>
<p id="scroll-to-me">Hi 👋</p>
<Link href="/another">
<a>to /another</a>
<a id="link-another">to /another</a>
</Link>
</div>
)
Expand Down
58 changes: 50 additions & 8 deletions test/integration/preload-viewport/test/index.test.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
/* eslint-env jest */
/* global jasmine */
import webdriver from 'next-webdriver'
import { join } from 'path'
import {
nextServer,
runNextCommand,
startApp,
stopApp,
waitFor,
} from 'next-test-utils'
import webdriver from 'next-webdriver'
import { join } from 'path'

jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 5

Expand Down Expand Up @@ -98,24 +98,66 @@ describe('Prefetching Links in viewport', () => {
}
})

it('should fallback to prefetching onMouseEnter with invalid ref', async () => {
it('should prefetch with link in viewport and inject script on hover', async () => {
let browser
try {
browser = await webdriver(appPort, '/invalid-ref')
await browser.elementByCss('#btn-link').moveTo()
browser = await webdriver(appPort, '/')
await browser.elementByCss('#scroll-to-another').click()
await waitFor(2 * 1000)

const links = await browser.elementsByCss('link[rel=prefetch]')
let found = false
let foundLink = false

for (const link of links) {
const href = await link.getAttribute('href')
if (href.includes('another')) {
found = true
foundLink = true
break
}
}
expect(found).toBe(true)
expect(foundLink).toBe(true)

await browser.elementByCss('#link-another').moveTo()
await waitFor(2 * 1000)

const scripts = await browser.elementsByCss(
// Mouse hover is a high-priority fetch
'script:not([async])'
)
let scriptFound = false
for (const aScript of scripts) {
const href = await aScript.getAttribute('src')
if (href.includes('another')) {
scriptFound = true
break
}
}
expect(scriptFound).toBe(true)
} finally {
if (browser) await browser.close()
}
})

it('should inject a <script> tag when onMouseEnter (even with invalid ref)', async () => {
let browser
try {
browser = await webdriver(appPort, '/invalid-ref')
await browser.elementByCss('#btn-link').moveTo()
await waitFor(2 * 1000)

const scripts = await browser.elementsByCss(
// Mouse hover is a high-priority fetch
'script:not([async])'
)
let scriptFound = false
for (const aScript of scripts) {
const href = await aScript.getAttribute('src')
if (href.includes('another')) {
scriptFound = true
break
}
}
expect(scriptFound).toBe(true)
} finally {
if (browser) await browser.close()
}
Expand Down

0 comments on commit c62cd23

Please sign in to comment.