PWA InjectManifest workbox console / debug output suddenly disabled (Vue.js / Quasar Framework) - vue.js

I'm building a PWA with Vue.js / Quasar Framework and recently added the PWA capability. I changed the "workboxPluginMode" property to "InjectManifest" and at first Workbox gave me debug / console as expected.
Also, the "custom-service-worker.js" definetly gets picked up by the process because it displays an error when i remove this line:
precacheAndRoute(self.__WB_MANIFEST)
So the file is recognized and actively using the defined caching strategies (i think), but it won't provide me any debug info or console.log's on console anymore. I really don't know what i have changed to do that.
My "custom-service-worker.js" looks like this:
import { precacheAndRoute } from 'workbox-precaching'
import { registerRoute } from 'workbox-routing'
import { StaleWhileRevalidate } from 'workbox-strategies'
console.log('custom service worker active')
// Use with precache injection
precacheAndRoute(self.__WB_MANIFEST)
// Caching strategies
registerRoute(
({url}) => {
console.log(url)
// url.pathname.startsWith('/images')
},
new StaleWhileRevalidate()
);
self.addEventListener('fetch', function(event) {
console.log(event)
event.respondWith(fetch(event.request));
})

I have no clue why, but the console debug output of workbox was only displayed in my default browser (Vivaldi). I wanted to work on plain Chromium because I couldn't install my PWA with Vivaldi (no installation prompt popped up), but that also works now. Have literally no explanation for this, but this is PWA development I guess, it is what it is. Anyways, problem solved for me.

Related

How to check if server build has been updated in SSR Nuxt application

I dont know how to solve the problem if SSR Nuxt app in browser is not compatible with server side build cause build has been updated. It means that user have old version of application in the browser and needs to refresh the page. I found something like this: https://dev-clone.nuxtjs.app/alejandroakbal/632139
So I have created pwa-update.js file in the plugins dir and register it in the nuxt.config.js.
But I dont see any console.log() in the console. Dont understand how to use it and if it is the right way to do it.
Implementaion looks like pwa-update.js
export default async (context) => {
const workbox = await window.$workbox;
if (!workbox) {
console.debug("Workbox couldn't be loaded.");
return;
} else {
console.log('Workbox has been loaded.'); // Dont see any message.
}
workbox.addEventListener('installed', (event) => {
if (!event.isUpdate) {
console.log('The PWA is on the latest version.');
return;
}
console.log('There is an update for the PWA, reloading...');
// window.location.reload();
});
};
nuxt.config.js
plugins: [
{ src: '~/plugins/pwa-update.js', mode: 'client' },
],
If you're regenerating your service worker using workbox during your development build process, a new service worker will be installed after every build. You can check this in your browser's dev tools. I believe the workbox generated service worker callls skipWaiting() in order to install new service workers immediately.
The client should get the new resources automagically because of webpack JS chunk name changes (assuming you're using webpack, the JS chunks it generates get new names after every new build, for cache busting purposes) and service worker version changes (workbox auto-increments service worker version, busting that cache as well). In other words, SSR or not, you won't need to worry about any version mismatches so long as you're using workbox to generate your service worker for you.

VueJS and ElectronJS | VueJS stops rendering completely when I import ipcRenderer in a component

So I am coding a VueJS and ElectronJS template which can be found here: https://github.com/dev-aethex/electronjstemplate
My code works something like this,
Inside of my Vue component I access a global pre constructed class called MainProcessInterface and when it's constructed it first checks if vue is compiled for running in a development server. If it's in a dev server it will connect to the dev socket which electrons main process will host if electron is in dev mode and not compiled. This method seems to be working great, I had to use a socket because vue dev server is being loaded into electron via loadURL and so vue has no clue what ipcRenderer is. Inside the main process interface, if vue is compiled it will instead use the ipcRenderer.send() method. This is were the problem was born.
As soon as Vue runs thought the TS code, it sees ipcRenderer.send and freaks out while printing an error to the electron window console saying fs.existsSync does not exist or is defined.
I can't find a way around this. I though maybe i'll split MainProcessInterface into 2 peices, one for ipc and the other for websockets. Although it isn't a very good way, so before implementing it, I would like to know if there is a better more proper way of doing such.
I had a similar issue with React. Are you importing the ipcRenderer object somewhere in your build process? You might want to make sure it references the correct variable. I tried to drop this in as a comment but it wouldn't fit:
//index.html (index.ejs) for me... This is in the main HTML entry point
var IPC = null;
try {
IPC = require('electron').ipcRenderer;
console.log('IPC IS: ' + IPC)
} catch (err) {
console.log('CRICITCAL ERROR: IPC NOT ENABLED')
console.log(err)
IPC = null;
}
Then I initialize off that context in React with a startup here:
setTimeout(()=>{
console.log('----------------HACK FIRED POST REHYDRATE')
window.REDUX_STORE.dispatch(
(dispatch, getState) => {
const _state = getState()
if(window.IPC) {
if(_state.osc && _state.osc.on) {
dispatch( reconnectToEos() )
} else {
dispatch( updateStatus('[OSC Startup: DISCONNECTED]', ))
}
console.log('\t------------ELECTRON')
} else {
//Shut off OSC
dispatch( updateOscKey('on', false) )
dispatch( updateStatus('[WebApp, OSC disabled]', ))
console.log('\t------------WEB')
}
}
)
}, 1000)
Basically I'm using a global variable (window.IPC) to initialize my app so I don't import a bad variable in my build process. I have a fair number of Electron APIs where this alleviates the issues with building via Webpack.
I hope this helps!

How to refer other html file to load in production mode of application that are developed using electron?

I have problem in building electron application, which is made using electron.js and vue.js.
The development is almost done, so I need to build it and make production.
Basically, my project has license system, so when the program starts, users should activate it by entering license key. I wrote this part inside activate.html. So, inside public folder, there are two html files, one is default index.html, and the other is activate.html
Inside activate.html, when activation is success, startMain() javascript function is called. Inside this function, the program is navigated to main program, especially to index.html. This html file is Vue application, and then main program is started.
All this process is working fine in the development mode. But when it
comes to production, this is not working anymore. I probably know why this
happens, this is just because index.html is not available in
production mode when all these are built up.
Alternatively, I tried to load localhost:8080 inside
startMain(). But also this works fine in development mode, but unluckily, we don't have localhost server on production mode, so this
doesn't solve the problem.
This is startMain() inside activate.html
function startMain() {
window.__static = "index.html";
// Alternatively, we can use location.href on development mode.
// window.location.href = "http://localhost:8080/";
}
This is background.js ( electron main engine)
function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 1400,
height: 900,
titleBarStyle: "hiddenInset"
});
win.setMenuBarVisibility(false);
if (isDevelopment) {
// Load the url of the dev server if in development mode
// win.loadURL(process.env.WEBPACK_DEV_SERVER_URL);
win.loadURL(`file://${process.cwd()}/public/activate.html`);
// if (!process.env.IS_TEST) win.webContents.openDevTools()
} else {
createProtocol("app");
// Load the index.html when not in development
win.loadFile("activate.html");
}
win.on("closed", () => {
win = null;
});
}
What I want is to make it run correctly in production mode.
Specifically, when the user finishes activation flow ( activate.html),
it should start main program ( index.html )
Please help me with this issue. I welcome any comments.
I built this application using vue-cli-plugin-electron-builder package
In Vue usually you use vue-router to switch between views. You set the BrowserWindow.location the first time, in background.js, but after that you are in the Vue app and you make router calls like this:
router.replace({ name: "index" }).catch(() => { });
It's hard to guess what to do in your case, without seeing the rest of your activate.html. You need to define router in your App and probably want to convert your activate.html into an activate.vue component and make it the proper first page of your App.
I think the cli-plugin boilerplate will call main.js where you will define your app and bootstraps it. You add router there:
import router from "./router";
window.$app = new Vue({
router,
In your bootstrap function you can also call something like router.replace({ name: "activate"}) to start your app with your activate vue component.

Electron Builder Vue cli 3 application on Windows throwing error registerStandardSchemes undefined

Background
We are building an Electron application and have been able to work on it, and build it using Linux and Mac OS. When we move it to a Windows machine in development or when build on a Mac OS machine then ran on the Windows machine, it fails.
When we follow the instructions here it says,
vue add electron-builder
yarn electron:serve
should run the application. On a fresh install using Windows this fails for us.
Problem
When we try and start the application on Windows we get an error,
TypeError
electron__WEBPACK_IMPORTED_MODULE_0__.protocol.registerStandardSchemes
is not a function
Example
This line comes with the boilerplate when we add Electron Builder to the app that seems to be throwing the error.
protocol.registerStandardSchemes(['app'], { secure: true })
It is being used like this,
import { protocol} from 'electron'
protocol.registerStandardSchemes(['app'], { secure: true })
// Helper to create our main view BrowserWindow
function createWindow() {
// Create the browser window.
win = new BrowserWindow({ width: 800, height: 600 })
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
if (!process.env.IS_TEST) win.webContents.openDevTools()
} else {
createProtocol('app')
// Load the index.html when not in development
win.loadURL('app://./index.html')
}
}
What We Tried
When I console.log protocol the only key available is, registerSchemesAsPrivileged which is in the docs but not what came with the boiler and nor does it work. I can see at this page that the registerStandardSchemes is referenced in a paragraph but it is not well explained in it's own section like the rest of the methods on that page.
Question
What does one need to do to access the method, protocol.registerStandardSchemes(['app'], { secure: true }) when running an Electron-Builder application scaffold with Vue CLI 3 on Windows 10?
I recently had this issue - if you're just looking to get back to development, running vue add electron-builder again fixed it for me.

Vue Cli 3 how to use the official PWA plugin ( Service Worker )

on my first vue project attempting to wrestle with the official PWA plugin ( https://github.com/yyx990803/register-service-worker ).
My specific problem: capturing the registered service worker and using it for anything. The github readme shows the exact file that is produced, and there seems to be zero documentation about how to work with this service worker once it is instantiated ( do I capture the registration instance? if so, how? )
I found this issue: https://github.com/vuejs/vue-cli/issues/1481
and am providing a better place to talk about this, as I haven't been able to find any example code or clear documentation about how to work with this.
If anyone has some sample code, please share. Vue and the new cli are incredible tools, documenting things like this is a necessary step forward to increasing the adoption of the platform
As already pointed out, it's more of a "service workers" issue than a "vue cli" one.
First of all, to make sure we're on the same page, here's what the boilerplate content of registerServiceWorker.js should look like (vue cli 3, official pwa plugin):
import { register } from 'register-service-worker'
if (process.env.NODE_ENV === 'production') {
register(`${process.env.BASE_URL}service-worker.js`, {
ready () {
console.log(
'App is being served from cache by a service worker.\n'
)
},
cached () {
console.log('Content has been cached for offline use.')
},
updated () {
console.log('New content is available; please refresh.')
},
offline () {
console.log('No internet connection found. App is running in offline mode.')
},
error (error) {
console.error('Error during service worker registration:', error)
}
})
}
If you haven't changed the BASE_URL variable in your .env file, then it should correspond to the root of your vue app. You have to create a file named service-worker.js in the public folder (so that it's copied into your output directory on build).
Now, it is important to understand that all the code in the registerServiceWorker.js file does is register a service worker and provide a few hooks into its lifecycle. Those are typically used for debugging purposes and not to actually program the service worker. You can understand it by noticing that the registerServiceWorker.js file will be bundled into the app.js file and run in the main thread.
The vue-cli 3 official PWA plugin is based on Google's workbox, so to use the service worker, you'll have to first create a file named vue.config.js at the root of your project and copy the following code in it:
// vue.config.js
module.exports = {
// ...other vue-cli plugin options...
pwa: {
// configure the workbox plugin
workboxPluginMode: 'InjectManifest',
workboxOptions: {
// swSrc is required in InjectManifest mode.
swSrc: 'public/service-worker.js',
// ...other Workbox options...
}
}
}
If you already have created a vue.config.js file, then you just have to add the pwa attribute to the config object. Those settings will allow you to create your custom service worker located at public/service-worker.js and have workbox inject some code in it: the precache manifest. It's a .js file where a list of references to your compiled static assets is stored in a variable typically named self.__precacheManifest. You have to build your app in production mode in order to make sure that this is the case.
As it is generated automatically by workbox when you build in production mode, the precache manifest is very important for caching your Vue app shell because static assets are usually broken down into chunks at compile time and it would be very tedious for you to reference those chunks in the service worker each time you (re)build the app.
To precache the static assets, you can put this code at the beginning of your service-worker.js file (you can also use a try/catch statement):
if (workbox) {
console.log(`Workbox is loaded`);
workbox.precaching.precacheAndRoute(self.__precacheManifest);
}
else {
console.log(`Workbox didn't load`);
}
You can then continue programming your service worker normally in the same file, either by using the basic service worker API or by using workbox's API. Of course, don't hesitate to combine the two methods.
I hope it helps !
as an addition to the answer above: I wrote a small guide on how to go further and add some functionality to the custom service-worker, using the setup above. You can find it here.
Four main things to keep in mind:
configure Workbox in vue.config.js to InjectManifest mode, pointing the swSrc key to a custom service-worker file in /src
In this custom service-worker, some lines will be added automatically in the Build process for importing the precache-manifest and workbox CDN. Following lines need to be added in the custom service-worker.js file to actually precache the manifest files:
self.__precacheManifest = [].concat(self.__precacheManifest || []);
workbox.precaching.suppressWarnings();
workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
Listen to registration events in the registerServiceWorker.js file. You can use the registration object that is passed as first argument to the event handlers to post messages to the service-worker.js file:
...
updated(registration) {
console.log("New content is available; please refresh.");
let worker = registration.waiting
worker.postMessage({action: 'skipWaiting'})
},
...
Subscribe to messages in the service-worker.js file and act accordingly:
self.addEventListener("message", (e)=>{
if (e.data.action=='skipWaiting') self.skipWaiting()
})
Hope this helps someone.