-
Notifications
You must be signed in to change notification settings - Fork 26.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Invalidate cache for link[preload] in DEV #6183
Invalidate cache for link[preload] in DEV #6183
Conversation
// TODO: remove this workaround when https://bugs.webkit.org/show_bug.cgi?id=187726 is fixed. | ||
test('It adds a timestamp to link tags with preload attribute to invalidate the cache (DEV only)', async () => { | ||
const $ = await get$('/') | ||
$('script, link[rel=preload]').each((index, element) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I am not setting that on script tags as adding the timestamp to the link tags only seems to be fine. That said probably it makes sense to add the timestamp to the script tags as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually only adding it to preload defeats the purpose of preload right 🤔 as it would be 2 unique requests
yes I think so, I'll try to get the npm link-ing work later and try it out. |
@timneutkens would it make sense to map over the head and body children, look for links with preload tags and then add the timestamp to both them and the matching script tags? Or do you prefer the hardcoded version? |
alright it should be better now :) |
@giuseppeg I actually think you could add the timestamp on the renderer level, next-server/server/render.tsx, as then you don't even have to manage adding it in multiple places 👍 |
oh yeah definitely! Sorry I am not that familiar with the codebase yet 😅 |
@giuseppeg no worries 🙌 This would actually be the correct solution on older versions of Next.js, that bundle rendering was added in v6 |
packages/next/pages/_document.js
Outdated
<link rel='preload' href={`${assetPrefix}/_next/static/${buildId}/pages/_app.js`} as='script' nonce={this.props.nonce} crossOrigin={this.props.crossOrigin || process.crossOrigin} /> | ||
<link rel='preload' href={`${assetPrefix}/_next/static/${buildId}/pages/_error.js`} as='script' nonce={this.props.nonce} crossOrigin={this.props.crossOrigin || process.crossOrigin} /> | ||
{page !== '/_error' && <link rel='preload' href={`${assetPrefix}/_next/static/${buildId}/pages${pagePathname}${this.preloadLinkTagInvalidate}`} as='script' nonce={this.props.nonce} crossOrigin={this.props.crossOrigin || process.crossOrigin} />} | ||
<link rel='preload' href={`${assetPrefix}/_next/static/${buildId}/pages/_app.js${this.preloadLinkTagInvalidate}`} as='script' nonce={this.props.nonce} crossOrigin={this.props.crossOrigin || process.crossOrigin} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@timneutkens I just realized that these are hardcoded paths so I can't add the timestamp in next-server/server/render.tsx
.
Either we add these there or keep this latest revision. I can cleanup by doing the string concatenation with a function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@timneutkens what is your preference here? Should we stick to the current revision or should I move (hardcode) these files in next-server/server/render.tsx
and go for your suggestion? There are pro and cons with both but I don't have a strong preference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's keep it like this
<link rel='preload' href={`${assetPrefix}/_next/static/${buildId}/pages/_error.js`} as='script' nonce={this.props.nonce} crossOrigin={this.props.crossOrigin || process.crossOrigin} /> | ||
{page !== '/_error' && <link rel='preload' href={`${assetPrefix}/_next/static/${buildId}/pages${pagePathname}${this.preloadLinkTagInvalidate}`} as='script' nonce={this.props.nonce} crossOrigin={this.props.crossOrigin || process.crossOrigin} />} | ||
<link rel='preload' href={`${assetPrefix}/_next/static/${buildId}/pages/_app.js${this.preloadLinkTagInvalidate}`} as='script' nonce={this.props.nonce} crossOrigin={this.props.crossOrigin || process.crossOrigin} /> | ||
<link rel='preload' href={`${assetPrefix}/_next/static/${buildId}/pages/_error.js${this.preloadLinkTagInvalidate}`} as='script' nonce={this.props.nonce} crossOrigin={this.props.crossOrigin || process.crossOrigin} /> | ||
{this.getPreloadDynamicChunks()} | ||
{this.getPreloadMainLinks()} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
out of curiosity why the main links are after the dynamic ones?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The dynamic ones here are actually needed for hydration anyway, so the other isn't important as we'd wait for these to load before doing anything else anyway currently
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note these are only the dynamic components that have been rendered not all
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah sure, is that the case for client side rendering too though?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@giuseppeg those are handled by webpack's dynamic loading mechanism.
packages/next/pages/_document.js
Outdated
@@ -16,7 +16,7 @@ export default class Document extends Component { | |||
static getInitialProps ({ renderPage }) { | |||
const { html, head } = renderPage() | |||
const styles = flush() | |||
return { html, head, styles } | |||
return { html, head, styles, timestamp: Date.now() } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we disable this in prod, probably not too heavy but still not useful to have Date.now
running on every request.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
totally
|
||
// This is a workaround to fix https://github.com/zeit/next.js/issues/5860 | ||
// TODO: remove this workaround when https://bugs.webkit.org/show_bug.cgi?id=187726 is fixed. | ||
test('It adds a timestamp to link tags with preload attribute to invalidate the cache (DEV only)', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also add a test to integration/production
to make sure we don't regress there in the future.
packages/next/pages/_document.js
Outdated
// This is a workaround to fix https://github.com/zeit/next.js/issues/5860 | ||
// TODO: remove this workaround when https://bugs.webkit.org/show_bug.cgi?id=187726 is fixed. | ||
if (process.env.NODE_ENV !== 'production') { | ||
initialProps.timestamp = Date.now() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a type checker would yell at me so badly here 😅
b396437
to
da0cf2f
Compare
da0cf2f
to
e8b53a0
Compare
@@ -10,7 +10,8 @@ const Fragment = React.Fragment || function Fragment ({ children }) { | |||
|
|||
export default class Document extends Component { | |||
static childContextTypes = { | |||
_documentProps: PropTypes.any | |||
_documentProps: PropTypes.any, | |||
_devOnlyInvalidateCacheQueryString: PropTypes.string, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this use React 16.3 context instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentProps one is kinda tricky but your new one might make sense
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will think of some way to refactor this. With the current implementation I think that we would need to add the provider in next-server as the Document render
method could be overridden.
After all probably your idea of adding the timestamp in next-server was better - we could define all the files to render there (also the hardcoded ones) and have this component just render them.
Invalidate cache for link[preload] in DEV (vercel#6183)
Fixes #5860