facebook / create-react-app

Set up a modern web app by running one command.
https://create-react-app.dev
MIT License
102.56k stars 26.79k forks source link

Problem with new builds #3574

Closed RohovDmytro closed 5 years ago

RohovDmytro commented 6 years ago

After each new build I have this error in production:

Uncaught SyntaxError: Unexpected token <

And I cannot understand the exact reasoning behind this. And this error disappers after couple of page refreshes.

More formaly

Conclusion

Somehow because of service worker chrome is loading previous js build. Thus server cannot serve it so I have a parsing error in console. After service worker updates now chrome is loading last build and everything is working fine.

Maybe, maybe service worker also cached index.html? Is t

Questions

What is messed up? How to force chrome load latest build after updates? Is it a good idea to cache index.html? (if that is true)

Info

andr11111 commented 6 years ago

I have the same issue. I believe the reason is that the service-worker caches index.html with the old .js script file name (different hash). Both index.html and service-worker.js files have cache-control: public, must-revalidate, proxy-revalidate, max-age=0. Is there a way for the service worker to refetch index.html?

RohovDmytro commented 6 years ago

@andrei-anisimov

the only way I see to fix this problem is to store several builds, not only the latest one. But it is hard to believe that this is the best practice or the best defaults. So I am leaning to an option that I am missing something.

But what am I missing?

andr11111 commented 6 years ago

sw-precache has useful info:

  • sw-precache uses a cache-first strategy, which results in a copy of any cached content being returned without consulting the network. A useful pattern to adopt with this strategy is to display a toast/alert to your users when there's new content available, and give them an opportunity to reload the page to pick up that new content (which the service worker will have added to the cache, and will be available at the next page load). The sample service-worker-registration.js file illustrates the service worker lifecycle event you can listen for to trigger this message.
RohovDmytro commented 6 years ago

@andrei-anisimov, yeap, but in order to display that notification i need serve some checker.js (or make it a part of build.js) from index.html and that is what I cannot do. :|

RohovDmytro commented 6 years ago

Maybe I can ask like this: is this an expected behaviour of PWA? Otherwise it is a mistake on my side.

gaearon commented 6 years ago

@jeffposnick can answer this, but in the meantime you can opt out of caching if it causes issues.

jeffposnick commented 6 years ago

As @gaearon mentions, you can opt-out of caching, but I'd obviously like to help get to the bottom of any problems you're having!

Maybe I can ask like this: is this an expected behaviour of PWA? Otherwise it is a mistake on my side.

Serving index.html cache-first on browsers that support service workers is the expected default behavior.

yeap, but in order to display that notification i need serve some checker.js (or make it a part of build.js) from index.html and that is what I cannot do. :|

The service worker lifecycle automatically handles checking for updates, and by default, there's a very basic example of logging a message in the JS console when updated resources are detected:

https://github.com/facebookincubator/create-react-app/blob/72b6eb8c3c65e6ed0f2413708069287311a386c2/packages/react-scripts/template/src/registerServiceWorker.js#L61-L74

This message isn't part of the UX, but you could replace the console.log() statements with something more visible. Alternatively, https://github.com/facebookincubator/create-react-app/pull/2426 is an open PR that makes a visible message appear by default.

the only way I see to fix this problem is to store several builds, not only the latest one. But it is hard to believe that this is the best practice or the best defaults. So I am leaning to an option that I am missing something.

I'm curious as to how you're loading the JavaScript files that show up as missing. Are they lazy-loaded after certain actions have taken place? Or are they loaded immediately as part of the initial HTML's parsing?

RohovDmytro commented 6 years ago

Or are they loaded immediately as part of the initial HTML's parsing?

I believe it is immidiately. I am using default index.html from CRA.

What I end up is outing out from cache-first strategy. This made me sad, but I did not manage to wrap my head why the bug took place.

Recently I had another idea. Can you validate it and maybe if it's true we can add some thing do README.md

Here is an idea. Maybe in order to have a proper service-worker workflow I must serve cached index.html? I believe in order to turn cache off I remove caching index.html. And what happened than was:

And this somehow conflicted with what was already cached on a client.

I am not sure if I am clear enough just trying to figure out what was happening.

If my idea is right we can add some info about cache index.html file. For me this situations can be described and ultra tricky. :)

P. S. Thanks for taking time and care on CRA.

airqb commented 6 years ago
jeffposnick commented 6 years ago

Here is an idea. Maybe in order to have a proper service-worker workflow I must serve cached index.html? I believe in order to turn cache off I remove caching index.html. And what happened than was:

Do you mean that you explicitly went into the browser's DevTools and cleared out the Cache Storage API entry for index.html? Yes, if you took that manual approach, I'd imagine that you could run into mismatches between index.html and the versioned subresources that it needs to load.

BlakeWilliams commented 6 years ago

We're running into this issue and it's seemingly because the JS bundle isn't included in the generated build/service-worker.js file in this project and I'm not entirely sure why that's happening.

jeffposnick commented 6 years ago

This sounds like https://github.com/facebook/create-react-app/issues/3882#issuecomment-359880716. Probably best to consolidate the discussion there.

antoinerousseau commented 6 years ago

I have the same issue and I'm not using the service worker at all.

My project is hosted on Firebase Hosting and uses an error reporting tool that allows me to see that when I build and deploy a new version, some users get that SyntaxError because their index.html is trying to load a main.[hash].js that no longer exists... which means there is something wrong with the cache control (I'm not an expert on this...) because if the browser can load the old index.html, why can't it load the old JS bundle too?

It happened on various browsers like Firefox mobile 59 for Android, Chrome mobile 65 for Android, Chrome 60 and 65 for Windows, Chrome 62 for macOS, etc.

Should I tweak Firebase hosting to redirect all the missed main.*.js to the new one in my deploy script?

Shpadoinkle commented 6 years ago

yep same here. Have tried adding header caching rules to the header section with no success.

Currently trying to unregister the serviceWorker but this seems like a horrid way to get around this bug.

I swear this used to work just fine. So not sure where the issue began.

But judging on the history of react devs and how often issue threads just close down due to inactivity, I doubt this will be addressed any time soon.

antoinerousseau commented 6 years ago

Fyi, my ugly temporary workaround for now is to dynamically generate firebase.json before publishing to firebase hosting, using this script:

#!/usr/bin/env node

'use strict'

const config = {
  hosting: {
    public: 'build',
    rewrites: [
      {
        source: '**',
        destination: '/index.html'
      }
    ],
    redirects: []
  }
}

const fs = require('fs')

const path = require('path')
const folders = fs.readdirSync(path.resolve(__dirname, 'build/static'))
folders.forEach((folder) => {
  const files = fs.readdirSync(path.resolve(__dirname, 'build/static', folder))
  files.forEach((file) => {
    config.hosting.redirects.push({
      source: `/static/${folder}/${file.replace(/^main\.(\w+)/, 'main.!($1)')}`,
      destination: `/static/${folder}/${file}`,
      type: 301
    })
  })
})

fs.writeFileSync('firebase.json', JSON.stringify(config))
Stas-Buzunko commented 6 years ago

@antoinerousseau error disappeared but it always loads previous build, when i did hard reload it did load latest build, but on next refresh it loaded previous build as well you can see my console logs v12 is old build, v13 is a new one, after hard reload i got v13 and but again v12

screen shot 2018-07-01 at 21 37 33
binki commented 6 years ago

For me, my builds are omitting static/js/main.«hash».js from the generated service-worker.js. So when my browser loads the precached index.html and main.«hash».css just fine, it tries to make a real request for the .js which, after an app update, no longer exists.

Is the generated service-worker.js supposed to have main.«hash»js present when it is working properly? Could that be the issue?

binki commented 6 years ago

I’m working around my issue with https://gist.github.com/binki/e6558065360e47238240857d6cee611f . I need to update my react-scripts to the latest version (I’m currently on 1.0.7), I will see if that helps.

Stas-Buzunko commented 6 years ago

https://github.com/facebook/create-react-app/issues/3882#issuecomment-362590606 worked for me

nfantone commented 5 years ago

Hit the same issue again today with 2.0.4. Comment above did not solve it for me, unfortunately. Related: https://github.com/facebook/create-react-app/issues/3882#issuecomment-426971602

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 7 days if no further activity occurs.

stale[bot] commented 5 years ago

This issue has been automatically closed because it has not had any recent activity. If you have a question or comment, please open a new issue.