Skip to content

Commit

Permalink
Fix edge workers being re-used unexpectedly (#41402)
Browse files Browse the repository at this point in the history
This ensures we don't re-use edge workers locally as they are meant to
be isolated.

## Bug

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

Fixes: [slack
thread](https://vercel.slack.com/archives/C035J346QQL/p1665708744315109)
  • Loading branch information
ijjk authored Oct 14, 2022
1 parent 241195d commit 889af9f
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 35 deletions.
4 changes: 2 additions & 2 deletions packages/next/server/next-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1800,7 +1800,7 @@ export default class NextNodeServer extends BaseServer {
page: page,
body: getRequestMeta(params.request, '__NEXT_CLONABLE_BODY'),
},
useCache: !this.nextConfig.experimental.runtime,
useCache: false,
onWarning: params.onWarning,
})

Expand Down Expand Up @@ -2126,7 +2126,7 @@ export default class NextNodeServer extends BaseServer {
},
body: getRequestMeta(params.req, '__NEXT_CLONABLE_BODY'),
},
useCache: !this.nextConfig.experimental.runtime,
useCache: false,
onWarning: params.onWarning,
})

Expand Down
9 changes: 1 addition & 8 deletions packages/next/server/web/sandbox/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,15 +314,8 @@ interface ModuleContextOptions {
edgeFunctionEntry: Pick<EdgeFunctionDefinition, 'assets' | 'wasm'>
}

const pendingModuleCaches = new Map<string, Promise<ModuleContext>>()

function getModuleContextShared(options: ModuleContextOptions) {
let deferredModuleContext = pendingModuleCaches.get(options.moduleName)
if (!deferredModuleContext) {
deferredModuleContext = createModuleContext(options)
pendingModuleCaches.set(options.moduleName, deferredModuleContext)
}
return deferredModuleContext
return createModuleContext(options)
}

/**
Expand Down
18 changes: 18 additions & 0 deletions test/e2e/app-dir/app/app/slow-page-no-loading/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { experimental_use as use } from 'react'

async function getData() {
await new Promise((resolve) => setTimeout(resolve, 5000))
return {
message: 'hello from slow page',
}
}

export default function SlowPage(props) {
const data = use(getData())

return <h1 id="slow-page-message">{data.message}</h1>
}

export const config = {
runtime: 'experimental-edge',
}
29 changes: 29 additions & 0 deletions test/e2e/app-dir/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,35 @@ describe('app dir', () => {
})
afterAll(() => next.destroy())

it('should not share edge workers', async () => {
const controller1 = new AbortController()
const controller2 = new AbortController()
fetchViaHTTP(next.url, '/slow-page-no-loading', undefined, {
signal: controller1.signal,
}).catch(() => {})
fetchViaHTTP(next.url, '/slow-page-no-loading', undefined, {
signal: controller2.signal,
}).catch(() => {})

await waitFor(1000)
controller1.abort()

const controller3 = new AbortController()
fetchViaHTTP(next.url, '/slow-page-no-loading', undefined, {
signal: controller3.signal,
}).catch(() => {})
await waitFor(1000)
controller2.abort()
controller3.abort()

const res = await fetchViaHTTP(next.url, '/slow-page-no-loading')
expect(res.status).toBe(200)
expect(await res.text()).toContain('hello from slow page')
expect(next.cliOutput).not.toContain(
'A separate worker must be used for each render'
)
})

if ((global as any).isNextStart) {
it('should generate build traces correctly', async () => {
const trace = JSON.parse(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
import Link from 'next/link'
import { useRouter } from 'next/router'

export default function Page(props) {
if (useRouter().isFallback) {
return <p>Loading...</p>
}

return <p id="props">{JSON.stringify(props)}</p>
return (
<>
<p id="props">{JSON.stringify(props)}</p>
<Link href="/fallback-true-blog/first?hello=world" shallow>
<a id="to-query-shallow">to /fallback-true-blog/first?hello=world</a>
</Link>
<br />
<Link href="/fallback-true-blog/second" shallow>
<a id="to-no-query-shallow">to /fallback-true-blog/second</a>
</Link>
<br />
</>
)
}

export function getStaticPaths() {
Expand Down
29 changes: 5 additions & 24 deletions test/e2e/middleware-rewrites/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -419,29 +419,12 @@ describe('Middleware Rewrite', () => {
})

it('should handle shallow navigation correctly (dynamic page)', async () => {
const browser = await webdriver(next.url, '/fallback-true-blog/first', {
waitHydration: false,
})
let requests = []
const browser = await webdriver(next.url, '/fallback-true-blog/first')

browser.on('request', (req) => {
const url = req.url()
if (url.includes('_next/data')) requests.push(url)
})

// wait for initial query update request
await check(async () => {
const didReq = await browser.eval('next.router.isReady')
if (didReq || requests.length > 0) {
requests = []
return 'yup'
}
}, 'yup')

await browser.eval(
`next.router.push('/fallback-true-blog/first?hello=world', undefined, { shallow: true })`
)
await check(() => browser.eval(`next.router.query.hello`), 'world')
await browser.elementByCss('#to-query-shallow').click()
return browser.eval('location.search')
}, '?hello=world')

expect(await browser.eval(`next.router.pathname`)).toBe(
'/fallback-true-blog/[slug]'
Expand All @@ -454,9 +437,7 @@ describe('Middleware Rewrite', () => {
)
expect(await browser.eval('location.search')).toBe('?hello=world')

await browser.eval(
`next.router.push('/fallback-true-blog/second', undefined, { shallow: true })`
)
await browser.elementByCss('#to-no-query-shallow').click()
await check(() => browser.eval(`next.router.query.slug`), 'second')

expect(await browser.eval(`next.router.pathname`)).toBe(
Expand Down

0 comments on commit 889af9f

Please sign in to comment.