Skip to content

Commit

Permalink
Add experimental config for basePath testing (#36843)
Browse files Browse the repository at this point in the history
This adds an experimental config for testing `basePath` handling on the client. 

x-ref: [slack thread](https://vercel.slack.com/archives/CLDDX2Y0G/p1652221605742559)

## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have helpful link attached, see `contributing.md`

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `yarn lint`
  • Loading branch information
ijjk committed May 12, 2022
1 parent 66d98e2 commit 03d00e2
Show file tree
Hide file tree
Showing 9 changed files with 368 additions and 4 deletions.
3 changes: 3 additions & 0 deletions packages/next/build/webpack-config.ts
Expand Up @@ -1408,6 +1408,9 @@ export default async function getBaseWebpackConfig(
isEdgeServer ? 'edge' : 'nodejs'
),
}),
'process.env.__NEXT_MANUAL_CLIENT_BASE_PATH': JSON.stringify(
config.experimental.manualClientBasePath
),
'process.env.__NEXT_NEW_LINK_BEHAVIOR': JSON.stringify(
config.experimental.newNextLinkBehavior
),
Expand Down
3 changes: 2 additions & 1 deletion packages/next/client/page-loader.ts
Expand Up @@ -156,7 +156,8 @@ export default class PageLoader {
'.json'
)
return addBasePath(
`/_next/data/${this.buildId}${dataRoute}${ssg ? '' : search}`
`/_next/data/${this.buildId}${dataRoute}${ssg ? '' : search}`,
true
)
}

Expand Down
1 change: 1 addition & 0 deletions packages/next/server/config-shared.ts
Expand Up @@ -79,6 +79,7 @@ export interface NextJsWebpackConfig {
}

export interface ExperimentalConfig {
manualClientBasePath?: boolean
newNextLinkBehavior?: boolean
disablePostcssPresetEnv?: boolean
swcMinify?: boolean
Expand Down
17 changes: 14 additions & 3 deletions packages/next/shared/lib/router/router.ts
Expand Up @@ -205,12 +205,23 @@ export function hasBasePath(path: string): boolean {
return hasPathPrefix(path, basePath)
}

export function addBasePath(path: string): string {
export function addBasePath(path: string, required?: boolean): string {
if (process.env.__NEXT_MANUAL_CLIENT_BASE_PATH) {
if (!required) {
return path
}
}
// we only add the basepath on relative urls
return addPathPrefix(path, basePath)
}

export function delBasePath(path: string): string {
if (process.env.__NEXT_MANUAL_CLIENT_BASE_PATH) {
if (!hasBasePath(path)) {
return path
}
}

path = path.slice(basePath.length)
if (!path.startsWith('/')) path = `/${path}`
return path
Expand Down Expand Up @@ -1120,7 +1131,7 @@ export default class Router implements BaseRouter {

if (process.env.__NEXT_HAS_REWRITES && as.startsWith('/')) {
const rewritesResult = resolveRewrites(
addBasePath(addLocale(cleanedAs, nextState.locale)),
addBasePath(addLocale(cleanedAs, nextState.locale), true),
pages,
rewrites,
query,
Expand Down Expand Up @@ -1747,7 +1758,7 @@ export default class Router implements BaseRouter {
;({ __rewrites: rewrites } = await getClientBuildManifest())

const rewritesResult = resolveRewrites(
addBasePath(addLocale(asPath, this.locale)),
addBasePath(addLocale(asPath, this.locale), true),
pages,
rewrites,
parsed.query,
Expand Down
6 changes: 6 additions & 0 deletions test/e2e/manual-client-base-path/app/next.config.js
@@ -0,0 +1,6 @@
module.exports = {
basePath: '/docs-proxy',
experimental: {
manualClientBasePath: true,
},
}
50 changes: 50 additions & 0 deletions test/e2e/manual-client-base-path/app/pages/another.js
@@ -0,0 +1,50 @@
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'

export default function Page(props) {
const router = useRouter()
const [mounted, setMounted] = useState(false)

useEffect(() => {
setMounted(true)
}, [])

return (
<>
<p id="page">another page</p>
<p id="props">{JSON.stringify(props)}</p>
<p id="router">
{JSON.stringify(
mounted
? {
basePath: router.basePath,
pathname: router.pathname,
asPath: router.asPath,
query: router.query,
}
: {}
)}
</p>

<Link href="/">
<a id="to-index">to /index</a>
</Link>
<br />

<Link href="/dynamic/first">
<a id="to-dynamic">to /dynamic/first</a>
</Link>
<br />
</>
)
}

export function getServerSideProps() {
return {
props: {
hello: 'world',
now: Date.now(),
},
}
}
58 changes: 58 additions & 0 deletions test/e2e/manual-client-base-path/app/pages/dynamic/[slug].js
@@ -0,0 +1,58 @@
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'

export default function Page(props) {
const router = useRouter()
const [mounted, setMounted] = useState(false)

useEffect(() => {
setMounted(true)
}, [])

return (
<>
<p id="page">dynamic page</p>
<p id="props">{JSON.stringify(props)}</p>
<p id="router">
{JSON.stringify(
mounted
? {
basePath: router.basePath,
pathname: router.pathname,
asPath: router.asPath,
query: router.query,
}
: {}
)}
</p>

<Link href="/">
<a id="to-index">to /index</a>
</Link>
<br />

<Link href="/dynamic/second">
<a id="to-dynamic">to /dynamic/second</a>
</Link>
<br />
</>
)
}

export function getStaticPaths() {
return {
paths: ['/dynamic/first'],
fallback: true,
}
}

export function getStaticProps({ params }) {
return {
props: {
params,
hello: 'world',
now: Date.now(),
},
}
}
41 changes: 41 additions & 0 deletions test/e2e/manual-client-base-path/app/pages/index.js
@@ -0,0 +1,41 @@
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'

export default function Page(props) {
const router = useRouter()
const [mounted, setMounted] = useState(false)

useEffect(() => {
setMounted(true)
}, [])

return (
<>
<p id="page">index page</p>
<p id="props">{JSON.stringify(props)}</p>
<p id="router">
{JSON.stringify(
mounted
? {
basePath: router.basePath,
pathname: router.pathname,
asPath: router.asPath,
query: router.query,
}
: {}
)}
</p>

<Link href="/another">
<a id="to-another">to /another</a>
</Link>
<br />

<Link href="/dynamic/first">
<a id="to-dynamic">to /dynamic/first</a>
</Link>
<br />
</>
)
}

0 comments on commit 03d00e2

Please sign in to comment.