Skip to content
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

Merged

Conversation

giuseppeg
Copy link
Contributor

Fixes #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 () => {
const $ = await get$('/')
$('script, link[rel=preload]').each((index, element) => {
Copy link
Contributor Author

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.

Copy link
Member

@timneutkens timneutkens left a 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

@giuseppeg
Copy link
Contributor Author

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.

@giuseppeg
Copy link
Contributor Author

giuseppeg commented Jan 31, 2019

@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?

@giuseppeg
Copy link
Contributor Author

alright it should be better now :)

@timneutkens
Copy link
Member

@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 👍

@giuseppeg
Copy link
Contributor Author

oh yeah definitely! Sorry I am not that familiar with the codebase yet 😅

@timneutkens
Copy link
Member

@giuseppeg no worries 🙌 This would actually be the correct solution on older versions of Next.js, that bundle rendering was added in v6

<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} />
Copy link
Contributor Author

@giuseppeg giuseppeg Feb 1, 2019

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.

Copy link
Contributor Author

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.

Copy link
Member

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()}
Copy link
Contributor Author

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?

Copy link
Member

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

Copy link
Member

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

Copy link
Contributor Author

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?

Copy link
Member

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.

@@ -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() }
Copy link
Member

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.

Copy link
Contributor Author

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 () => {
Copy link
Member

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.

// 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()
Copy link
Contributor Author

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 😅

@giuseppeg giuseppeg force-pushed the fix-dev-safari-caching-issues branch from b396437 to da0cf2f Compare February 1, 2019 19:45
@giuseppeg giuseppeg force-pushed the fix-dev-safari-caching-issues branch from da0cf2f to e8b53a0 Compare February 1, 2019 19:48
@@ -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,
Copy link
Member

@timneutkens timneutkens Feb 3, 2019

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?

Copy link
Member

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

Copy link
Contributor Author

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.

@timneutkens timneutkens merged commit 5a4176c into vercel:canary Feb 3, 2019
rajendraarora16 added a commit to rajendraarora16/next.js that referenced this pull request Feb 3, 2019
Invalidate cache for link[preload] in DEV (vercel#6183)
@lock lock bot locked as resolved and limited conversation to collaborators Feb 3, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Safari cache on dev
2 participants