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

Code changes saved are not reflected unless a hard refresh is made #7546

Closed
ShaCP opened this issue Jan 10, 2022 · 12 comments · Fixed by #8166
Closed

Code changes saved are not reflected unless a hard refresh is made #7546

ShaCP opened this issue Jan 10, 2022 · 12 comments · Fixed by #8166

Comments

@ShaCP
Copy link

ShaCP commented Jan 10, 2022

After making updates to the code and saving, a cached version without the changes is loaded. I have to press ctrl + shift + r to see changes. How to fix this?

If I change, for example, the CSS, the changes are immediately reflected. However if I refresh after, the old version without the changes is loaded.

I'm on Windows, parcel 2.1.1.

@mischnic
Copy link
Member

What browser are you using? Seems to work fine with Chrome, Safari & Firefox on macOS.

I usually always have the devtools open with "Disable Cache" enabled.

@paharvey
Copy link

I have run into the same problem when "Disable Cache" is disabled:

  1. I make a change in some JS code
  2. Files are changed on-disk by "parcel serve" and Chrome is updated via HMR
  3. I press F5 in Chrome
  4. Chrome loads the old version of the JS code from an in-memory cache

I've noticed that "parcel serve" does not specify any cache control headers, and so Chrome is presumably correct to use an in-memory cache. Is there a way to tell "parcel serve" to add cache control headers so that Chrome will never use its in-memory cache of the out-of-date JS file?

This discussion also seemed relevant: #7705

@mischnic
Copy link
Member

Is there a way to tell "parcel serve" to add cache control headers so that Chrome will never use its in-memory cache of the out-of-date JS file?

Yes, I don't see why we shouldn't do that. Relevant code:

function setHeaders(res: Response) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader(
'Access-Control-Allow-Methods',
'GET, HEAD, PUT, PATCH, POST, DELETE',
);
res.setHeader(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept, Content-Type',
);
}

Maybe someone could investigate whether Webpack/Vite/... set these caching headers

@paharvey
Copy link

As a workaround I've modified my .proxyrc.js to contain this. It seems to work:

  app.use(function (req, res, next) {
    // Prevent browser caching of all URLs (except /api and /ws because we proxy those)
    if (!req.path || !req.path.startsWith('/api') && !req.path.startsWith('/ws')) {
      res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
    }
    next();
  })

@hubol
Copy link

hubol commented Apr 20, 2022

Thank you so much @paharvey ! I am still very curious why this is not the default for parcel serve. I assume I am missing something.

@devongovett
Copy link
Member

It just hasn't been done yet. Can someone send a PR for this?

@hubol
Copy link

hubol commented Apr 21, 2022

@devongovett I would happily make a PR addressing the lines that @mischnic indicated. However, I am concerned about breaking things if parcel users depend on this header not being set...

I found this related issue for the vite project:
vitejs/vite#4736
It seems they went with a configuration option for the cache-control header.

I did not find a related issue nor indication that webpack sets the header. However, I only naively searched the repository, I did not make a webpack project to test it (it seems complicated, which is why I am grateful that parcel exists!)

@devongovett
Copy link
Member

I think no-cache should be a fairly safe default. Unlike Vite, Parcel apps don't typically load hundreds of files at once during development, so I'm less worried about performance. If it causes problems, we can change it again or make it configurable then.

@michaelKurowski
Copy link

I've faced similiar issue in #8157, I think there's nothing wrong with caching CSS files in principle, since I've noticed that the styles file has a hash attached to its name to avoid pulling cached version. My guess is that parcel has some issue that makes it reuse the same hash for CSS file over and over instead of getting a new one every time the content changes. The interesting part is that it works flawlessly after rebuild.

@mischnic
Copy link
Member

These hashes intentionally don't change when making changes in development builds.

@michaelKurowski
Copy link

michaelKurowski commented May 29, 2022

@mischnic At first I were to suggest that there has to be some other error in parcel, since I've thought that the hash has to change for rebuild for it to avoid the cache, but no.

Apperently what helps the rebuilt CSS to avoid cache hit is a unique query parameter that exists on rebuilt CSS files but is absent on the initial CSS.

2022-05-29-123159_282x89_scrot
First file is one built initially, following one is fetched upon rebuild

The outcome is that when the app is built at first the file is always named the same way. Because of that it'll be cached and then always served from there.

Once it's rebuilt though it gets a new, unique query patameter so it misses the cache in subsequential rebuilds.

@mischnic
Copy link
Member

So Webpack (or at least create-react-app) handles this by using sending an ETag header, then subsequent responses are 304 or 200 depending on whether they changed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants