parcel
parcel copied to clipboard
Service Worker: Failed to construct 'URL': Invalid URL
🐛 bug report
My PWA works fine when using the Parcel dev server on my localhost. So I tried building and deploying to a webhost and it breaks.
When using the build command parcel build --no-content-hash --no-source-maps --no-optimize src/index.html
, and copying the output to a server
dist/index.html 1.63 KB 1.09s
dist/app.webmanifest 450 B 967ms
dist/index.5375eb8a.js ⚠️ 2.48 MB 1.07s
dist/serviceWorker.020ed210.js 2.28 KB 1.07s
I get the error caught (in promise) TypeError: Failed to construct 'URL': Invalid URL at $db13d2c0f4fb9b17$var$registerServiceWorker (index.5375eb8a.js:66710:30)
.
Here's the code that gives the error (taken from https://parceljs.org/languages/javascript/#service-workers
)
async function registerServiceWorker(): Promise<void>
{
const serviceWorkerUrl = new URL('./serviceWorker.ts', import.meta.url);
console.log(`Registering service worker file located at ${serviceWorkerUrl} ...`);
if ('serviceWorker' in navigator)
{
try
{
const registration = await navigator.serviceWorker.register(serviceWorkerUrl, {type: 'module', scope: '/' });
console.log('Service worker registered', registration);
}
catch (error)
{
console.error('Error registering service worker:', error);
}
}
else console.warn('Service workers are not supported.');
}
I can't debug this because I can't see what URL Parcel is trying to generate here.
If I don't try to put the URL in a string, like this:
async function registerServiceWorker(): Promise<void>
{
if ('serviceWorker' in navigator)
{
try
{
const registration = await navigator.serviceWorker.register(new URL('./serviceWorker.ts', import.meta.url), {type: 'module', scope: '/' });
console.log('Service worker registered', registration);
}
catch (error)
{
console.error('Error registering service worker:', error);
}
}
else console.warn('Service workers are not supported.');
}
and build, Parcel now doesn't add a hash to the service worker filename
dist/index.html 1.63 KB 1.16s
dist/app.webmanifest 450 B 992ms
dist/index.5375eb8a.js ⚠️ 2.48 MB 1.15s
dist/serviceWorker.js 2.68 KB 1.15s
and I get a different error when browsing to the site:
A bad HTTP response code (404) was received when fetching the script.
index.5375eb8a.js:66716 Error registering service worker: TypeError: Failed to register a ServiceWorker for scope ('https://journal.example.app/') with script ('https://journal.example.app/undefined'): A bad HTTP response code (404) was received when fetching the script.
$
🎛 Configuration (.babelrc, package.json, cli command)
package.json
{
"version": "0.1.0",
"comments": "",
"scripts": {
"build": "rm -r dist; rm -r .parcel-cache; parcel build --no-content-hash --no-source-maps --no-optimize src/index.html",
"check": "clear && vue-tsc --noEmit",
"run": "rm -r .parcel-cache; parcel src/index.html"
},
"dependencies": {
"@parcel/service-worker": "^2.8.3",
"crypto-js": "^4.1.1",
"dayjs": "^1.11.3",
"dropbox": "^10.34.0",
"idb": "^7.1.1",
"jszip": "^3.10.1",
"ramda": "^0.29.0",
"uuid": "^8.3.2",
"vue": "^3.2.37",
"vue-router": "^4.0.16",
"vue-tsc": "^0.38.2"
},
"devDependencies": {
"@parcel/packager-raw-url": "^2.8.3",
"@parcel/transformer-vue": "^2.6.2",
"@parcel/transformer-webmanifest": "^2.8.3",
"@types/node": "^18.0.1",
"@types/ramda": "^0.29.0",
"@types/serviceworker": "^0.0.67",
"@types/uuid": "^8.3.4",
"@vue/tsconfig": "^0.1.3",
"assert": "^2.0.0",
"browserify-zlib": "^0.2.0",
"buffer": "^5.7.1",
"crypto-browserify": "^3.12.0",
"events": "^3.3.0",
"https-browserify": "^1.0.0",
"os-browserify": "^0.3.0",
"parcel": "^2.6.2",
"path-browserify": "^1.0.1",
"process": "^0.11.10",
"querystring-es3": "^0.2.1",
"stream-browserify": "^3.0.0",
"stream-http": "^3.2.0",
"typescript": "^4.7.4",
"url": "^0.11.0",
"util": "^0.12.4"
},
"serve": {
"port": 1234,
"headers": {
"Service-Worker-Allowed": "/"
}
}
}
🤔 Expected Behavior
The service worker should load and I should be able to log its path to the console. The service worker filename should not be given a hash no matter what code calls it.
😯 Current Behavior
Parcel's path assignment for the service worker is broken. Parcel keeps changing the service worker filename.
🌍 Your Environment
Software | Version(s) |
---|---|
Parcel | 2.6.2 |
Node | 16.15.0 |
npm/Yarn | 8.5.5 |
Operating System | Ubuntu 22.04, but this is occurring on some web server and I don't know any of it's OS details. Just Apache or whatever |
And here's the generated JS code, which looks roughly right to me, at least serviceWorker.js
has the right name.
(parcelRequire("2JpsI")).register(JSON.parse('{"cpKN1":"index.5375eb8a.js","exyRE":"serviceWorker.js"}'));
...
var $8308987b7f2d1c72$exports = {};
$8308987b7f2d1c72$exports = new URL((parcelRequire("2JpsI")).resolve("exyRE"), import.meta.url).toString();
async function $db13d2c0f4fb9b17$var$registerServiceWorker() {
if ("serviceWorker" in navigator) try {
const registration = await navigator.serviceWorker.register($8308987b7f2d1c72$exports, {
scope: "/"
});
If I put $8308987b7f2d1c72$exports = new URL((parcelRequire("2JpsI")).resolve("exyRE"), "http://journal.example.app").toString();
in the console it gives me the right filename.
My ts.config
of my root folder is
{
"extends": "@vue/tsconfig/tsconfig.web.json",
"include":
[
"env.d.ts", "src/**/*", "src/**/*.vue"
,"src/external/dropbox/dropbox_sdk_10_32_0.js"
],
"compilerOptions":
{
"alwaysStrict": true,
"baseUrl": ".",
"importsNotUsedAsValues": "remove",
"isolatedModules": false,
"lib": ["ES2021", "DOM", "webworker"],
"module": "ES2020",
"moduleResolution": "node",
"noImplicitAny": true,
"paths": { "@/*": ["./src/*"] },
"preserveConstEnums": true,
"preserveValueImports": false,
"removeComments": true,
"sourceMap": true,
"strict": true,
"strictNullChecks": true,
"target": "ES2021",
"types": ["node", "dropbox"]
},
}
navigator.serviceWorker.register(new URL('./serviceWorker.ts', import.meta.url), {type: 'module', scope: '/' })
That is definitely the version you should be using. If you put the url constructor outside, then Parcel doesn't know that serverWorker.ts
should be the service worker.
Not sure yet why that then fails to load the correct url
Thanks @mischnic. Here's a reproducible example: https://we.tl/t-6RVGridxhJ
Run:
npm update
npm run dev # browse to localhost:1234 and see that it works
npm run preview # browse to localhost:1234 and see that it doesn't work
I can confirm this issue.
Uncaught (in promise) DOMException: Failed to register a ServiceWorker for scope ('https://test.local/') with script ('https://test.local/undefined')
Parcel tries to load an undefined URL. My service worker URL should be https://test.local/service_worker.js.
Interestingly, if I pass the --no-scope-hoist
flag when building, then Parcel loads the correct URL.
I have this problem with 2.12.0. Has no progress really been made in over a year? This is a show-stopping bug.
Is the value of import.meta.url really meant to be file:///src/index.ts
even when serving from a web server?