sapper
sapper copied to clipboard
service-worker.js: "Uncaught (in promise) TypeError: Request failed" on export with relative path
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.
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 my best solution was actually to switch from GitHub Pages to Netlify haha, that fixed the service worker issues by itself.
Ah, this was probably caused by https://github.com/sveltejs/sapper/pull/1244
@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)
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
@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/",
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
Still not fixed, I just deleted the service-worker and the corresponding service-worker configuration in the webpack config file.