Skip to content

Commit

Permalink
Use proxy to ensure Flight is referencing to the latest module during…
Browse files Browse the repository at this point in the history
… development (#43823)

As @timneutkens pointed out [here](#43819 (comment)), changing the key will make Flight's module cache grow indefinitely. While I've thought about updating Flight's logic to clean the cache at some point, but that's tricky to do correctly as everything is asynchronous and we have to trigger clean up from outside (Webpack).

So currently, a better way I can think of is to just give Flight a proxied object as `moduleExports`. Even if Flight is getting the same object from cache, it will always require the latest module from Webpack.

## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/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`
- [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md)

## Documentation / Examples

- [ ] Make sure the linting passes by running `pnpm build && pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
  • Loading branch information
shuding committed Dec 8, 2022
1 parent d4a8edf commit 013a58d
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 29 deletions.
21 changes: 17 additions & 4 deletions packages/next/client/app-index.tsx
Expand Up @@ -30,10 +30,23 @@ __webpack_require__.u = (chunkId: any) => {
// Ignore the module ID transform in client.
// eslint-disable-next-line no-undef
// @ts-expect-error TODO: fix type
self.__next_require__ = (id: string) => {
const modId = id.replace(/\?.+$/, '')
return __webpack_require__(modId)
}
self.__next_require__ =
process.env.NODE_ENV !== 'production'
? (id: string) => {
const mod = __webpack_require__(id)
if (typeof mod === 'object') {
// Return a proxy to flight client to make sure it's always getting
// the latest module, instead of being cached.
return new Proxy(mod, {
get(_target, prop) {
return __webpack_require__(id)[prop]
},
})
}

return mod
}
: __webpack_require__

// eslint-disable-next-line no-undef
;(self as any).__next_chunk_load__ = (chunk: string) => {
Expand Down
26 changes: 1 addition & 25 deletions packages/next/server/app-render.tsx
Expand Up @@ -1601,35 +1601,11 @@ export async function renderToHTMLOrFlight(
).slice(1),
]

const serverComponentManifestWithHMR = dev
? new Proxy(serverComponentManifest, {
get: (target, prop) => {
if (
typeof prop === 'string' &&
!prop.startsWith('_') &&
target[prop]
) {
// Attach TS (timestamp) query param to IDs to get rid of flight client's module cache on HMR.
const namedExports: any = {}
const ts = Date.now()
for (let key in target[prop]) {
namedExports[key] = {
...target[prop][key],
id: `${target[prop][key].id}?ts=${ts}`,
}
}
return namedExports
}
return target[prop]
},
})
: serverComponentManifest

// For app dir, use the bundled version of Fizz renderer (renderToReadableStream)
// which contains the subset React.
const readable = ComponentMod.renderToReadableStream(
flightData,
serverComponentManifestWithHMR,
serverComponentManifest,
{
context: serverContexts,
onError: flightDataRendererErrorHandler,
Expand Down

0 comments on commit 013a58d

Please sign in to comment.