Skip to content

Commit

Permalink
Merge branch 'canary' into trailing-slash-files
Browse files Browse the repository at this point in the history
  • Loading branch information
Janpot authored Jun 29, 2020
2 parents dc0c7aa + f12a9f9 commit a152267
Show file tree
Hide file tree
Showing 18 changed files with 107 additions and 69 deletions.
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@
"registry": "https://registry.npmjs.org/"
}
},
"version": "9.4.5-canary.22"
"version": "9.4.5-canary.23"
}
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.4.5-canary.22",
"version": "9.4.5-canary.23",
"keywords": [
"react",
"next",
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin-next/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/eslint-plugin-next",
"version": "9.4.5-canary.22",
"version": "9.4.5-canary.23",
"description": "ESLint plugin for NextJS.",
"main": "lib/index.js",
"license": "MIT",
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.4.5-canary.22",
"version": "9.4.5-canary.23",
"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.4.5-canary.22",
"version": "9.4.5-canary.23",
"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.4.5-canary.22",
"version": "9.4.5-canary.23",
"repository": {
"url": "vercel/next.js",
"directory": "packages/next-plugin-google-analytics"
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.4.5-canary.22",
"version": "9.4.5-canary.23",
"repository": {
"url": "vercel/next.js",
"directory": "packages/next-plugin-sentry"
Expand Down
2 changes: 1 addition & 1 deletion packages/next-plugin-storybook/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/plugin-storybook",
"version": "9.4.5-canary.22",
"version": "9.4.5-canary.23",
"repository": {
"url": "vercel/next.js",
"directory": "packages/next-plugin-storybook"
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.4.5-canary.22",
"version": "9.4.5-canary.23",
"description": "A polyfill for non-dead, nomodule browsers.",
"main": "dist/polyfill-nomodule.js",
"license": "MIT",
Expand Down
25 changes: 13 additions & 12 deletions packages/next/client/page-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,17 +109,18 @@ export default class PageLoader {
* @param {string} href the route href (file-system path)
* @param {string} asPath the URL as shown in browser (virtual path); used for dynamic routes
*/
getDataHref(href, asPath) {
getDataHref(href, asPath, ssg) {
const { pathname: hrefPathname, query, search } = parse(href, true)
const { pathname: asPathname } = parse(asPath)
const route = normalizeRoute(hrefPathname)

const getHrefForSlug = (/** @type string */ path) => {
const dataRoute = getAssetPathFromRoute(path, '.json')
return `${this.assetPrefix}/_next/data/${this.buildId}${dataRoute}`
return `${this.assetPrefix}/_next/data/${this.buildId}${dataRoute}${
ssg ? '' : search || ''
}`
}

const { pathname: hrefPathname, query } = parse(href, true)
const { pathname: asPathname } = parse(asPath)

const route = normalizeRoute(hrefPathname)

let isDynamic = isDynamicRoute(route),
interpolatedRoute
if (isDynamic) {
Expand All @@ -135,19 +136,19 @@ export default class PageLoader {
interpolatedRoute = route
if (
!Object.keys(dynamicGroups).every((param) => {
let value = dynamicMatches[param]
let value = dynamicMatches[param] || ''
const { repeat, optional } = dynamicGroups[param]

// support single-level catch-all
// TODO: more robust handling for user-error (passing `/`)
if (repeat && !Array.isArray(value)) value = [value]
let replaced = `[${repeat ? '...' : ''}${param}]`
if (optional) {
replaced = `[${replaced}]`
replaced = `${!value ? '/' : ''}[${replaced}]`
}
if (repeat && !Array.isArray(value)) value = [value]

return (
param in dynamicMatches &&
(optional || param in dynamicMatches) &&
// Interpolate group into data URL if present
(interpolatedRoute = interpolatedRoute.replace(
replaced,
Expand Down Expand Up @@ -182,7 +183,7 @@ export default class PageLoader {
// Check if the route requires a data file
s.has(route) &&
// Try to generate data href, noop when falsy
(_dataHref = this.getDataHref(href, asPath)) &&
(_dataHref = this.getDataHref(href, asPath, true)) &&
// noop when data has already been prefetched (dedupe)
!document.querySelector(
`link[rel="${relPrefetch}"][href^="${_dataHref}"]`
Expand Down
73 changes: 33 additions & 40 deletions packages/next/next-server/lib/router/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { isDynamicRoute } from './utils/is-dynamic'
import { getRouteMatcher } from './utils/route-matcher'
import { getRouteRegex } from './utils/route-regex'
import { normalizeTrailingSlash } from './normalize-trailing-slash'
import getAssetPathFromRoute from './utils/get-asset-path-from-route'

const basePath = (process.env.__NEXT_ROUTER_BASEPATH as string) || ''

Expand Down Expand Up @@ -108,39 +107,26 @@ type ComponentLoadCancel = (() => void) | null
type HistoryMethod = 'replaceState' | 'pushState'

function fetchNextData(
pathname: string,
query: ParsedUrlQuery | null,
dataHref: string,
isServerRender: boolean,
cb?: (...args: any) => any
) {
let attempts = isServerRender ? 3 : 1
function getResponse(): Promise<any> {
return fetch(
formatWithValidation({
pathname: addBasePath(
// @ts-ignore __NEXT_DATA__
`/_next/data/${__NEXT_DATA__.buildId}${getAssetPathFromRoute(
pathname,
'.json'
)}`
),
query,
}),
{
// Cookies are required to be present for Next.js' SSG "Preview Mode".
// Cookies may also be required for `getServerSideProps`.
//
// > `fetch` won’t send cookies, unless you set the credentials init
// > option.
// https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
//
// > For maximum browser compatibility when it comes to sending &
// > receiving cookies, always supply the `credentials: 'same-origin'`
// > option instead of relying on the default.
// https://github.com/github/fetch#caveats
credentials: 'same-origin',
}
).then((res) => {
return fetch(dataHref, {
// Cookies are required to be present for Next.js' SSG "Preview Mode".
// Cookies may also be required for `getServerSideProps`.
//
// > `fetch` won’t send cookies, unless you set the credentials init
// > option.
// https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
//
// > For maximum browser compatibility when it comes to sending &
// > receiving cookies, always supply the `credentials: 'same-origin'`
// > option instead of relying on the default.
// https://github.com/github/fetch#caveats
credentials: 'same-origin',
}).then((res) => {
if (!res.ok) {
if (--attempts > 0 && res.status >= 500) {
return getResponse()
Expand Down Expand Up @@ -669,11 +655,21 @@ export default class Router implements BaseRouter {
}
}

let dataHref: string | undefined

if (__N_SSG || __N_SSP) {
dataHref = this.pageLoader.getDataHref(
formatWithValidation({ pathname, query }),
as,
__N_SSG
)
}

return this._getData<RouteInfo>(() =>
__N_SSG
? this._getStaticData(as)
? this._getStaticData(dataHref!)
: __N_SSP
? this._getServerData(as)
? this._getServerData(dataHref!)
: this.getInitialProps(
Component,
// we provide AppTree later so this needs to be `any`
Expand Down Expand Up @@ -843,23 +839,20 @@ export default class Router implements BaseRouter {
})
}

_getStaticData = (asPath: string): Promise<object> => {
const pathname = prepareRoute(parse(asPath).pathname!)
_getStaticData = (dataHref: string): Promise<object> => {
const pathname = prepareRoute(parse(dataHref).pathname!)

return process.env.NODE_ENV === 'production' && this.sdc[pathname]
? Promise.resolve(this.sdc[pathname])
? Promise.resolve(this.sdc[dataHref])
: fetchNextData(
pathname,
null,
dataHref,
this.isSsr,
(data) => (this.sdc[pathname] = data)
)
}

_getServerData = (asPath: string): Promise<object> => {
let { pathname, query } = parse(asPath, true)
pathname = prepareRoute(pathname!)
return fetchNextData(pathname, query, this.isSsr)
_getServerData = (dataHref: string): Promise<object> => {
return fetchNextData(dataHref, this.isSsr)
}

getInitialProps(
Expand Down
8 changes: 4 additions & 4 deletions packages/next/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "next",
"version": "9.4.5-canary.22",
"version": "9.4.5-canary.23",
"description": "The React Framework",
"main": "./dist/server/next.js",
"license": "MIT",
Expand Down Expand Up @@ -76,8 +76,8 @@
"@babel/preset-typescript": "7.9.0",
"@babel/runtime": "7.9.6",
"@babel/types": "7.9.6",
"@next/react-dev-overlay": "9.4.5-canary.22",
"@next/react-refresh-utils": "9.4.5-canary.22",
"@next/react-dev-overlay": "9.4.5-canary.23",
"@next/react-refresh-utils": "9.4.5-canary.23",
"babel-plugin-syntax-jsx": "6.18.0",
"babel-plugin-transform-define": "2.0.0",
"babel-plugin-transform-react-remove-prop-types": "0.4.24",
Expand Down Expand Up @@ -114,7 +114,7 @@
"react-dom": "^16.6.0"
},
"devDependencies": {
"@next/polyfill-nomodule": "9.4.5-canary.22",
"@next/polyfill-nomodule": "9.4.5-canary.23",
"@taskr/clear": "1.1.0",
"@taskr/esnext": "1.1.0",
"@taskr/watch": "1.1.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/react-dev-overlay/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/react-dev-overlay",
"version": "9.4.5-canary.22",
"version": "9.4.5-canary.23",
"description": "A development-only overlay for developing React applications.",
"repository": {
"url": "vercel/next.js",
Expand Down
2 changes: 1 addition & 1 deletion packages/react-refresh-utils/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/react-refresh-utils",
"version": "9.4.5-canary.22",
"version": "9.4.5-canary.23",
"description": "An experimental package providing utilities for React Refresh.",
"repository": {
"url": "vercel/next.js",
Expand Down
2 changes: 1 addition & 1 deletion test/integration/build-output/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ describe('Build Output', () => {
expect(parseFloat(webpackSize) - 775).toBeLessThanOrEqual(0)
expect(webpackSize.endsWith('B')).toBe(true)

expect(parseFloat(mainSize) - 6.3).toBeLessThanOrEqual(0)
expect(parseFloat(mainSize) - 6.4).toBeLessThanOrEqual(0)
expect(mainSize.endsWith('kB')).toBe(true)

expect(parseFloat(frameworkSize) - 41).toBeLessThanOrEqual(0)
Expand Down
4 changes: 4 additions & 0 deletions test/integration/prerender/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ const Page = ({ world, time }) => {
<a id="to-nested-index">to nested index</a>
</Link>
<br />
<Link href="/lang/[lang]/about?lang=en" as="/about">
<a id="to-rewritten-ssg">to rewritten static path page</a>
</Link>
<br />
<Link href="/catchall-optional/[[...slug]]" as="/catchall-optional">
<a id="catchall-optional-root">to optional catchall root</a>
</Link>
Expand Down
2 changes: 1 addition & 1 deletion test/integration/prerender/pages/lang/[lang]/about.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default ({ lang }) => <p>About: {lang}</p>
export default ({ lang }) => <p id="about">About: {lang}</p>

export const getStaticProps = ({ params: { lang } }) => ({
props: {
Expand Down
40 changes: 40 additions & 0 deletions test/integration/prerender/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
} from 'next-test-utils'
import webdriver from 'next-webdriver'
import { dirname, join } from 'path'
import url from 'url'

jest.setTimeout(1000 * 60 * 2)
const appDir = join(__dirname, '..')
Expand Down Expand Up @@ -601,6 +602,45 @@ const runTests = (dev = false, isEmulatedServerless = false) => {
const html = await renderViaHTTP(appPort, '/about')
expect(html).toMatch(/About:.*?en/)
})

it('should fetch /_next/data correctly with mismatched href and as', async () => {
const browser = await webdriver(appPort, '/')

if (!dev) {
await browser.eval(() =>
document.querySelector('#to-rewritten-ssg').scrollIntoView()
)

await check(
async () => {
const links = await browser.elementsByCss('link[rel=prefetch]')
let found = false

for (const link of links) {
const href = await link.getAttribute('href')
const { pathname } = url.parse(href)

if (pathname.endsWith('/lang/en/about.json')) {
found = true
break
}
}
return found
},
{
test(result) {
return result === true
},
}
)
}
await browser.eval('window.beforeNav = "hi"')
await browser.elementByCss('#to-rewritten-ssg').click()
await browser.waitForElementByCss('#about')

expect(await browser.eval('window.beforeNav')).toBe('hi')
expect(await browser.elementByCss('#about').text()).toBe('About: en')
})
}

if (dev) {
Expand Down

0 comments on commit a152267

Please sign in to comment.