Error registering service-worker script with production build - javascript

I'm using Workbox Webpack plugin (v4.3.1) to generate a service worker script and Workbox-Window (v4.3.1) plugin to register it.
It all works fine on dev environment (I use webpack dev server) but with the production build I'm getting the error below on the Chrome (v78) dev console:
Uncaught (in promise) TypeError: Failed to register a ServiceWorker for scope ('http://localhost:4321/') with script ('http://localhost:4321/undefined'): A bad HTTP response code (404) was received when fetching the script.
(Note: Im using a local Nginx server to test my production build)
Im using Workbox Webpack GenerateSW like this:
new WorkboxPlugin.GenerateSW({
clientsClaim: true,
skipWaiting: false
})
And I confirmed that, after the build, the service worker script (service-worker.js) is generated and its in the dist folder.
I am using Workbox-Window plugin to register the aforementioned service worker script:
import { Workbox } from 'workbox-window'
if ('serviceWorker' in navigator) {
const wb = new Workbox('/service-worker.js') // Note: I also tried without the bar and with path './service-worker.js' and didnt work
wb.register()
}
I'm guessing the problem is not related to the fact Im using Nginx to test the prod build, nor related with the url or path of the service worker script, provided to the Workbox constructor because, using ServiceWorker Web API instead of Workbox Window API, it works fine:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js') // THIS WORKS!!!
}
Why, under the exact same conditions, the service worker registration fails with Workbox Window API? Where does that undefined, that you can see in the error logs, come from???
* Edit * I opened an issue on Workbox GitHub repo. You can find it here.

I was experiencing this same issue and had my hopes up when I saw your post here. After a mild disappointment I started searching and scavenging the web for some enlightenment. Anyway, I have a setup similar to yours, where on development environments it works but on production it doesn't.
My specific setup is: Python 3 + Flask + Webpack + npm + Apache HTTPD
What I did to solve this issue was to modify the import sentence from:
import { Workbox } from 'workbox-window'
To this:
import { Workbox } from 'workbox-window/Workbox.mjs';
According to this documentation on Google's Workbox website:
Workbox Advanced bundling concepts
Afterwards I was required to update my Webpack setup to bundle Babel-Polyfill so that I was able to avoid the regeneratorRuntime Errors caused by the promises and awaits functions that workbox-window uses, by installing it and including it as stated here: #babel/Polyfill or babel-polyfill depending on your setup and adding it as an entry on the module.exports config.
Hope this helps any one else who suffers this ambiguous and exhausting error.

Related

PYTHON module "requests" not working with packaged electron app

In my electron app I have a python file that has two import statements shown below
import requests
import shutil
The app works fine without an errors in the IDE but after packaging the electron app with
npx electron-packager ./ --platform=darwin --icon=src/img/logo.icns
The app gives me this error
It only gives this error for the 'requests' module but not the 'shutil' module. And yes, 'requests' is installed on my computer. I also use the PythonShell module in the js file to run the python file like below
function version_checker(){
form.classList.toggle('hide');
circle.classList.toggle('show');
let pyshell = new PythonShell(__dirname + '/version_checker.py');
pyshell.on('message', function (message){
console.log(message);
if(message !== "same"){
console.log("updating")
}
else{
if(message !== "restart"){
form.classList.toggle('hide');
circle.classList.toggle('show');
}
else{}
}
})
pyshell.end(function (err,code,signal) {
if (err) throw err;
console.log('The exit code was: ' + code);
console.log('The exit signal was: ' + signal);
console.log('finished');
});
}
I also do not wish to compile the python file into an executable because the python script "talks" to the js file. I am also on a M1 Pro Macbook running macOS Ventrua if that helps
How do I package the app and include the 'requests' module OR How do I make the 'requests' module work with the packaged app
I did find a stackoverflow post that asked a similar question but the owner voluntary took down the question so I wasn't able to view it
I looked at this post but it wasn't helpful because I'm not using 'anaconda' or 'child-process'
PythonShell just calls the system's Python interpreter, so use PIP to install the requests library
Or specify the interpreter as follows:
new PythonShell(__dirname + '/version_checker.py', {
pythonPath: '/path/to/python'
})
Note: For production purposes, it is recommended to include an interpreter in electron and install dependencies
It seems you just want to make a HTTP request, why not try fetch in javascript?
If the error is ModuleNotFoundError, then your python interpreter is struggling to find the requests module. This can happen for a number of reasons:
Module does not exist: We can rule this out if your ide ran program successfully.
2: Module is not where interpreter expects to find it: Most likely.
Almost certainly the python interpreter used by your IDE is different to the one you ran after packaging the electron app.
The solution is to either:
a. make sure the location of requests is visible to the PYTHONPATH by setting that in the proper location (I don't use MAC but I believe you have ~/.bash_profile file to set it in or
b. Explicitly add the request module location via a sys.path.append command in your code eg
import sys
import os
path = 'your path to request module'
sys.path.append(os.path.join(path, 'requests')
import requests
You should be able to find the path location by investigating your IDE and looking where you set the module to be included in your program

What are the "Query Suffixes" referred to in the Vite Docs?

I have been reading through the Vite documentation for Web workers, and it mentioned importing a file using "Query Suffixes," which I have never encountered and am not sure what to search for to learn more. I'm not sure if this is native to Node.js, Vite.js, or if it is a plugin that is built into Vite.
This is the specific section that I am referring to:
Import with Query Suffixes
A web worker script can be directly imported by appending ?worker or ?sharedworker to the import request. The default export will be a custom worker constructor:
import MyWorker from './worker?worker'
const worker = new MyWorker()
The worker script can also use import statements instead of importScripts() - note during dev this relies on browser native support and currently only works in Chrome, but for the production build it is compiled away.
By default, the worker script will be emitted as a separate chunk in the production build. If you wish to inline the worker as base64 strings, add the inline query:
import MyWorker from './worker?worker&inline'
If you wish to retrieve the worker as a URL, add the url query:
import MyWorker from './worker?worker&url'
See Worker Options for details on configuring the bundling of all workers.
Update:
I found an MDN page on import that seems like a step in the direction that I am looking for, as well as this MDN page on import.meta that looks a lot like what I am searching for. I tried following that lead, but it didn't help me understand this Vite feature any better.
Is the ?worker query suffix a custom Vite implementation of import.meta?

Import maps + Stimulus: error in JS "Unknown Content-Type text/html"

I'm having a JS issue with my first Rails app, which I suspect is related to my using import maps instead of Webpack. I've searched and searched but haven't found any discussions of this.
It's a Rails 6 app with some JS via Stimulus, which I installed by adding importmap-rails and then stimulus-rails. It works fine locally, but in production on Heroku the JS doesn't work and I see errors like this in the browser console: Uncaught (in promise) Error: Unknown Content-Type "text/html; charset=utf-8" doFetch https://plainreading.herokuapp.com/assets/es-module-shims-424762490b07cc7f9a37745e8b53356bca11997a8e313f47d780e29009df7e8e.js:580
I'm wondering if it's because I removed Webpack from my app, using How to completely remove webpack and all its dependencies from Rails App. I removed it because I was getting Webpack-related build errors in Heroku, and it's my understanding that I don't need Webpack if I'm using import maps.
A while ago I fixed a similar issue in a static site on Netlify by including this in its netlify.toml config:
[[headers]]
for = "/*.js"
[headers.values]
Content-Type = "text/javascript; charset=utf-8"
I couldn't find any similar config for Heroku. So then I tried customizing the response headers in the app, but I couldn't find a way to do that for my JS files, only for the main HTML response and for public assets.
Here's the repo in case it helps: https://github.com/fpsvogel/plainreading
In the end I solved the issue by doing the following:
Install Rails 7 alpha.
Create a test project with import maps: rails _7.0.0.alpha2_ new importmap-test. (You can use -j to set a different JS bundling option, such as -j esbuild, but the default is import maps.)
Upgrade my main project to Rails 7 alpha.
In my main project, make all JS-related code identical to the corresponding code in the test project. For me this meant overwriting app/javascript/controllers/index.js.
Then my JS worked without errors.

GatsbyJS: Import npm package in serviceworker file (gatsby-plugin-offline)

We use gatsby-plugin-offline in order to get a auto-generated service worker. It works fine since all pages are available offline now. With the following code in gatsby-config.js, some additional code can be added to the service worker.
{
resolve: `gatsby-plugin-offline`,
options: {
appendScript: 'src/custom-sw-code.js',
},
},
Within custom-sw-code.js we could not manage to import any npm package so far. If we use import or require on top of the file, browsers complain about non-working serviceworker code (after building and serving the app).
Do you know, how to import packages in the serviceworker?
If you want to pull in external scripts into a service worker, importScripts() will help. (Another option is to use static ES module imports, but they aren't supported in all browsers as of this writing.)
For each script URL you pass in, importScripts() will synchronously download and execute the code within the context of the current ServiceWorkerGlobalScope. The service worker will also take care of automatically caching the scripts, so you don't need to manually add those URLs to a cache, and the request for those scripts won't trigger your service worker's fetch event listeners.
If you're loading code from npm from a CDN, make sure that you're requesting either a UMD or IIFE bundle, and make note of what the exported global symbols are, as that's what will end up being exposed in the ServiceWorkerGlobalScope.

Uncaught SyntaxError: Cannot use import statement outside a module Vue 3 PWA Workbox

I am trying to convert my vue js app into a PWA. Following the workbox documentation in the following link:
https://developers.google.com/web/tools/workbox/modules/workbox-strategies
I have to import some modules
import { registerRoute } from 'workbox-routing';
import { StaleWhileRevalidate } from 'workbox-strategies';
import { Queue } from 'workbox-background-sync';
After running npm run build, vue js automatically generates the following line of code which is at the top of service-worker.js file followed by the imports mentioned above:
importScripts("/precache-manifest.f6666fe9d8f679ee90db8a98ef900aa4.js", "https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
My app is fully functional without any errors, if I remove the imports, the service worker is registered successfully. When i add the imports I am getting this error:
Uncaught SyntaxError: Cannot use import statement outside a module
Error during service worker registration: TypeError: Failed to register a ServiceWorker for scope ('http://127.0.0.1:8887/') with script ('http://127.0.0.1:8887/service-worker.js'): ServiceWorker script evaluation failed
From my research I have learned that the scripts need to be bundled using webpack or a similar service.
https://developers.google.com/web/tools/workbox/guides/using-bundlers
However since I am using the CDN to importScripts, according to my understanding it should automatically bundle as stated in the following website:
https://developers.google.com/web/tools/workbox/modules/workbox-sw
It's an either-or thing: if you have full control over your build a bundling process, then following the "Using bundlers with Workbox" guide and using the ES module import {...} from '...' syntax, but not using workbox-sw, would work.
If you don't have full control over your build process (and it sounds like you don't), then you can use workbox-sw to load the rest of Workbox. Since you already have the importScripts('/path/to/workbox-sw.js') in your service worker, using statements like workbox.routing.registerRoute() or workbox.strategies.registerRoute() in your service worker, and not putting in any import {...} from '...' statements, should just work.

Categories

Resources