sapper icon indicating copy to clipboard operation
sapper copied to clipboard

service-worker.js: "Uncaught (in promise) TypeError: Request failed" on export with relative path

Open gavinr opened this issue 5 years ago • 8 comments

Describe the bug If you configure the site to run at a relative sub-directory, like https://my-example-site.com/my-base-path/, per Base URLs, then run a sapper export, when you load the page you get an error:

service-worker.js:1 Uncaught (in promise) TypeError: Request failed

... and if you look at the network requests in the browser console, you see it trying to load files at the root instead of the relative path (ex: http://localhost:5000/client/index.4a975818.js instead of http://localhost:5000/my-base-path/client/index.4a975818.js)

To Reproduce

npx degit "sveltejs/sapper-template#rollup" my-app
cd my-app

Then update the basepath via https://sapper.svelte.dev/docs#Base_URLs

Then run:

sapper export --basepath my-base-path

Then serve the files at __sapper__/build/export locally then load the site.

Expected behavior No error.

Information about your Sapper Installation:

System:
    OS: Windows 10 10.0.18362
  Binaries:
    Node: 12.18.3
    npm: 6.14.6
  npmPackages:
    rollup: ^2.3.4 => 2.26.5
    sapper: ^0.28.0 => 0.28.1
    svelte: ^3.17.3 => 3.24.1

Severity Annoying, not a huge deal, but would appreciate help and interested if others are having the same issue.

gavinr avatar Aug 26 '20 05:08 gavinr

I'm also getting this error with the same steps.

I think it's happening because files and shell from @sapper/service-worker contain the filenames with / prepended, but any resources loaded with a / make them absolute to the root of the domain so the <base> tag is ignored, but getting rid of the / makes them relative again.

Not sure if this is the correct fix, but I tweaked the service-worker.js file to:

import { timestamp, files, shell, routes } from '@sapper/service-worker';

const ASSETS = `cache${timestamp}`;

const nonRootFiles = files.map(f => f.startsWith('/') ? f.substr(1) : f);

const nonRootShell = shell.map(f => f.startsWith('/') ? f.substr(1) : f);

// `shell` is an array of all the files generated by the bundler,
// `files` is an array of everything in the `static` directory
const to_cache = nonRootShell.concat(nonRootFiles);
const cached = new Set(to_cache);

and it seems to work now.

Edit: after doing this, I got the following error for the manifest.json:

No matching service worker detected. You may need to reload the page, or check that the service worker for the current page also controls the start of the URL from the manifest.

so had to tweak the service worker registrations to include {scope:"/"} as per https://w3c.github.io/ServiceWorker/#service-worker-script-response (from https://stackoverflow.com/a/48068714). (Sapper seems to add this registration on this line.)

Again, not sure if this is the best/correct solution! 😆

shu8 avatar Sep 18 '20 10:09 shu8

@shu8 my best solution was actually to switch from GitHub Pages to Netlify haha, that fixed the service worker issues by itself.

mcmxcdev avatar Sep 18 '20 15:09 mcmxcdev

Ah, this was probably caused by https://github.com/sveltejs/sapper/pull/1244

benmccann avatar Sep 18 '20 15:09 benmccann

@mhatvan I'm guessing that's because netlify you're at the root (http://my-app.netlify.com) vs GitHub Pages you're at a subdirectory (http://username.github.io/my-repo-name)

gavinr avatar Sep 18 '20 15:09 gavinr

I have been getting the same error when trying to export the application to my customer. :-(

To temporally solve the problem, I commented the service-worker entries in rollup.config.js in my application:

-  serviceworker: {
-    input: config.serviceworker.input(),
-    output: config.serviceworker.output(),
-    plugins: [
-      resolve(),
-      replace({
-        'process.browser': true,
-        'process.env.NODE_ENV': JSON.stringify(mode)
-      }),
-      commonjs(),
-      !dev && terser()
-    ],
-
-    preserveEntrySignatures: false,
-    onwarn,
-  }
+  // serviceworker: {
+  //   input: config.serviceworker.input(),
+  //   output: config.serviceworker.output(),
+  //   plugins: [
+  //     resolve(),
+  //     replace({
+  //       'process.browser': true,
+  //       'process.env.NODE_ENV': JSON.stringify(mode)
+  //     }),
+  //     commonjs(),
+  //     !dev && terser()
+  //   ],
+
+  //   preserveEntrySignatures: false,
+  //   onwarn,
+  // }

So, is there any plan to solve this problem?

TIA

silvioprog avatar Nov 03 '20 18:11 silvioprog

@shu8 thank you for a solution! I also had the following issue:

Edit: after doing this, I got the following error for the manifest.json:

No matching service worker detected. You may need to reload the page, or check that the service worker for the current page also controls the start of the URL from the manifest.

It can be easily fixed by editing manifest.json:

-  "start_url": "/",
+  "start_url": "/your-subdir/",

ierhyna avatar Feb 01 '21 07:02 ierhyna

shu8's solution works but we have to edit the generated serviceworker file everytime we export

I have a github workflow script here that would go bazooka and sed every faulty code lines in the exported folder every time we commit:

- run: npm run export

- name: Post Build 🛸 (fix Sapper bug of not using proper basePath)
  run: |
      sed -i 's/<base href=\/ >/<base href=\/[your-repo-name]\/ >/g' ./__sapper__/export/[your-repo-name]/index.html
      sed -i 's/src="\/client\//src="\/[your-repo-name]\/client\//g' ./__sapper__/export/[your-repo-name]/index.html
      sed -i 's/"data-main","\/client/"data-main","\/[your-repo-name]\/client/g' ./__sapper__/export/[your-repo-name]/index.html
      sed -i "s/'\/service-worker.js'/'\/[your-repo-name]\/service-worker.js'/g" ./__sapper__/export/[your-repo-name]/index.html
      sed -i 's/"\//"\/[your-repo-name]\//g' ./__sapper__/export/[your-repo-name]/service-worker.js
      sed -i 's/<base href=\/ >/<base href=\/[your-repo-name]\/ >/g' ./__sapper__/export/[your-repo-name]/service-worker-index.html
      sed -i 's/src="\/client\//src="\/[your-repo-name]\/client\//g' ./__sapper__/export/[your-repo-name]/service-worker-index.html
      sed -i 's/"data-main","\/client/"data-main","\/[your-repo-name]\/client/g' ./__sapper__/export/[your-repo-name]/service-worker-index.html
      sed -i "s/'\/service-worker.js'/'\/[your-repo-name]\/service-worker.js'/g" ./__sapper__/export/[your-repo-name]/service-worker-index.html

You guys can see my example repo here

tcd93 avatar Feb 08 '21 02:02 tcd93

Still not fixed, I just deleted the service-worker and the corresponding service-worker configuration in the webpack config file.

benwinding avatar Apr 30 '21 07:04 benwinding