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

Service Worker caches download links #3171

Closed
cetra3 opened this issue Sep 22, 2017 · 14 comments
Closed

Service Worker caches download links #3171

cetra3 opened this issue Sep 22, 2017 · 14 comments

Comments

@cetra3
Copy link

cetra3 commented Sep 22, 2017

Is this a bug report?

Yes

Can you also reproduce the problem with npm 4.x?

Yes

Which terms did you search for in User Guide?

Service Worker and Caching

Environment

N/A

Steps to Reproduce

The default ServiceWorker appears to cache files that it has not seen or downloaded. I have an api call which basically generates a zip to download, and is accessible via a http link. When a user navigates to this download URL by clicking on a link, the service worker intercepts the request, and tries to service the default index page.

With the ServiceWorker active, it appears that it is trying to retrieve this file from cache rather than requesting it from the server.

  1. (I think this is important) Have the homepage set to "." in the package.json config.
  2. Have a link somewhere on your application that points to a file via an API call
  3. Click on the think with the service worker active

Expected Behavior

The browser would download the file (as it does without the service worker active)

Actual Behavior

The service worker intercepts the download and serves the normal index.html file.

Suggested Behaviour

Have the whitelist exposed as a configuration so that a set of paths don't invoke the service worker.

@chee
Copy link

chee commented Sep 22, 2017

my advice here (not affiliated with create-react-app) is to build the service-worker.js yourself.

you don't need to eject to take hold of this part of your project, you can leave the registerServiceWorker.js exactly as it is and do the following:

create a sw-precache config file:

// config/sw.js
module.exports = {
  staticFileGlobs: [
    'build/**/*.js',
    'build/**/*.css',
    'build/index.html'
  ],
  navigateFallback: '/index.html',
  // something like this should allow everything but files ending with `.zip`
  navigateFallbackWhitelist: [/^(?!.*[.]zip$).*$/],
  cacheId: 'my-magical-cache-machine'
}

then install sw-precache:

npm i -D sw-precache

and add something like this as part of your build script:

sw-precache --root='build/' --config config/sw.js 

this is what i've been doing in a couple of production applications for a month or two now and it works very nicely.

@jeffposnick
Copy link
Contributor

For this specific use case, using <a href='/path/to/file' download> is the standard way of telling the browser that the link is inteded to download, not navigate to, the href.

@cetra3
Copy link
Author

cetra3 commented Sep 23, 2017

The download attribute works up until If I copy the link, and give it to someone else.

@jeffposnick
Copy link
Contributor

Yes, someone navigating to a random download URL that was shared with them would lead to the App Shell taking over.

The default configuration for create-react-app exempts URLs beginning with _ from triggering the App Shell, so if you wanted to avoid opting-out of the default behavior, and you have flexibility in constructing your download links, you can create them of the form _download/someId.

Or you can either disable the service worker entirely, and potentially create your own via sw-precache directly as @chee points out, or eject and modify the default configuration.

@cetra3
Copy link
Author

cetra3 commented Sep 24, 2017

Yeah I have just disabled it for now as a workaround. I think that having to eject just to whitelist a few paths is a bit overkill though. How hard would it be to add this as a config param?

@chee
Copy link

chee commented Sep 24, 2017

@cetra3 you don't need to eject to do what i mentioned in this comment.

that will work fine with a unejected create-react-app !

@gaearon
Copy link
Contributor

gaearon commented Nov 3, 2017

As stated in User Guide, you don't need to eject to opt out of caching:

https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#opting-out-of-caching

I think this (or prefixing URL with _) is a reasonable workaround.

@gillescastel
Copy link

The url should be prefixed with double underscores!

  • http://example.com/__auth works
  • http://example.com/_auth does not work
  • http://example.com/test/__auth does not work

@yegodz
Copy link

yegodz commented May 2, 2018

@gillescastel is this approach of using double underscores to bypass serviceworker interception documented anywhere?
I have tested that it works, but I'd be much more comfortable using it in production if it was was officially supported.

@gillescastel
Copy link

@yegodz This behavior has been added in #2347, but was then removed in #3419, so AFAIK, you have to eject when using this feature. However, it may get merged back in (#3924) in a future realease.

@yegodz
Copy link

yegodz commented May 2, 2018 via email

@iansu
Copy link
Contributor

iansu commented May 2, 2018

It was removed on the next branch which is for the 2.0 release.

@yegodz
Copy link

yegodz commented May 3, 2018

Thanks @iansu
I apologize if this is not the right place to ask this question... but how can I force create-react-app to cache a particular html file without ejecting? Right now it seems to be caching only index.html, css and js files and a request for another html file is responded to with index.html.
Copying a file like xo.html to the public folder does not seem to make a difference.

@yegodz
Copy link

yegodz commented May 3, 2018

never mind - just figured out.

You can overwrite create-react-app's default service worker by running sw-precache directly in package.json after react-scripts build like so:

"build": "react-scripts build && cd build && sw-precache --config ../sw-precache-config.js",

Then you can add a sw-precache-config.js file in the root folder where you can control the options for the serviceworker created by sw-precache

@lock lock bot locked and limited conversation to collaborators Jan 19, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants