I have thoughts on this! But it’ll take me a minute to compile everything, so here’s just a couple of off the cuff random comments:
PWA is very doable now, given all existing tech. PixStori is a PWA (with one caveat below). The only real thing missing is a service-worker. There is one - I have a version in my starters. This service workers really only solves a sub-set of what you might want to solve with a service worker- mainly it captures the main js and css bundles. In order to get everything else cached for offline use, you might need to enable appcache, which aside from enabling the legacy and deprecated appcache browser feature, also prefetches and caches all dynamic modules.
The truth is, most of what you might need a Service Worker for is taken care of in other ways in Meteor, so we probably don’t need a super complex one. It’s also the kind of thing that developers might want to take the care to write and understand themselves, rather than using something generic.
Some things that are missing off the top of my head (but which are probably achievable without a TON of effort)
a way to capture a app shell when SSR is enabled, instead of capturing an SSR html page, which may contain outdated data, and other problems.
Push notifications - it’s own whole thing.
PWA manifests and the like can all be created by external tools. Meteor could have a thing built in to do that (similar to Cordova), but I actually prefer it this way. Your mileage may vary.
One problem I do have, is that I have a memory leak with my SSR code but only in production (which I think is related to mix of Fibers/Futures and React hooks/fibers - different fibers), which has been difficult to trouble shoot on Galaxy. What I probably need to do is learn enough devops to get a production build up and running in a Docker container (I got this far), and then run some tools on that to figure it out (working on this). But there’s a reason I use Galaxy. Hopefully the ability to hook up a debugger to Galaxy instances is coming. Currently SSR is disabled on PixStori because of this, which also disabled necessary features like open graph, etc.
(I’m probably mixing up some offline-first stuff with PWA here)
PWA’s are a very interesting thing. We have been using it with Meteor for around 2 years, creating dinamically a PWA for each one of our clients. We dont have SSR but we use server-render package to send the open-graph and other metatags to the client without issues. In our case the service worker does almost nothing, just get the bundle and for push notifications in Chrome.
I dont remember what else we had to do to get PWA working, but it was a couple of hours of work. I was tempted to create a package for this, but not having the app working offline hold me on that.
thank you for your inputs and will be looking forward to enjoy your contributions on the “official” documentation. I don’t expect V1 to be clean and free of mistakes, misspells and confusions but as more users try to read and implement it, things will get explained better and better.
As far as I know there are three different Push packages for Meteor: RAIX, Rocket.Chat and Activitreee:Push. I think Activitree:Push is the only one that fully relies on Firebase Admin SDK for Notifications instead of using 2 different services (one for IOS and another one for Android).
I will write the Push Notification for PWA in direct entanglement with Activitree:Push while I will maintain compatibility with the other Push packages (if they support WebPush).
Because I’m personally focusing on a Vue + Meteor app, that is how I’ll be implementing some more PWA features ideally to get the very desirable “install” option in Chrome. This is a really nice tutorial that is helpful to read when exploring this implementation. No need for Auth0 with Meteor’s accounts packages obviously, but the rest of this tutorial is pretty relevant. It recommends a webpack plugin which would even be possible with Meteor, as many people have successfully added webpack to Meteor, although there are other ways of achieving this.
If anyone is building their own PWA implementations on Meteor, this would give you some things to think about.
If anyone working with Meteor & PWAs has time to look at this, it would be cool to get your thoughts on what parts you might consider keeping and what parts you would ignore.
I keep finding more great stuff on PWAs and the packages that are powering most of the PWA apps out there. I had been drilling down a little on the Service Worker (SW) options and found another Node.js SW solution, which does seem like it would be an ideal way to build a service worker for Meteor.
Google made a package on npm called workbox-build and it seems to do most of the heavy lifting, and is of course the most popular way to accomplish these tests at the moment from what I can tell, with over 2 mil npm download per week.
@jkuester would you mind taking a look at this package since you’ve got a good handle on how Service Workers might need to work with Meteor from the tutorial your wrote?
I’ll be trying this out soon on my project, but it would be great to see what everyone thinks of this approach.
Tag anyone here on the forums that is the most familiar with the Meteor build process to comment on how this workbox-build npm package might work? It has Babel dependencies, so to me it looks like it would be nicely compatible
We looked at the Workbox in the past and I believe it was @jkuester who suggested we should do it clean without further dependencies on other technologies.
I think it is an in-between case. Some parts of Meteor bound to certain techologies (for example WebApp uses the connect api) and this should of course be reduced to a minimum.
I have not gathered an audit on the workbox packages to say how heavy this would couple us. However, I know from google, that they tend to let projects fall from one to day to another, making long term maintenance pure horror then.
On the other hand I see great potential in what workbox is offering and I think it should be discussed with Tiny (cc @filipenevola) which path this whole out-of-the-box PWA integration should go.
It looked that at times the new bundle files don’t pick up after a code update and I’d need to manually refresh the page in order to have the new Meteor bundle running. I think this requires more testing…
clients.claim() just triggers the event ''controllerchange". The following part of code that is part of the SW registration, prevents multiple reloads on the same session.
After failing for some time to load the new bundle and to pick up on the offline HTML when required, the idea came from here: https://github.com/VeliovGroup/Meteor-Files-Demos/blob/master/demo/public/sw.js
To be frank, I have not exactly fully understood the implications of calling clients.claim() multiple times but it looks that, at least for me, things are now working as desired. The ''controllerchange" event is actually only triggered on a first load (or refresh) of a page. I’d prefer to take control and ensure the availability of the bundle files from cache (or newer) at every load of the browser and not only on the activation of the service worker.
const doTabsRefresh = () => {
// Refresh all tabs after a service worker update takes place
console.log('how often I call refreshing?!!!') // check this line
let refreshing
navigator.serviceWorker.addEventListener('controllerchange', () => {
if (refreshing) { return }
refreshing = true
window.location.reload()
})
}
I am not sure what you mean. Anyway, this is an example of how to sniff on the traffic. You can listen particularly to anything that passes through the browser. I activated debugging on my test domain: https://www.activitree.com and when set with your debugger as per the documentation (mainly Preserve History ON) you can see everything that passes through.
If I don’t exclude those, the fetch API tries to get that URLs and the router seems to reply with “Page not found”. It might be my case in particular as I am redirecting to a 404 page when a page is invalid for my platform but just to make sure they are always available as files and not as routes, I exclude them. No need to cache them, I need them network first. They are only handled on event.request.mode === 'navigate' which means either a first enter in the page or a refresh of the page. This is not being called otherwise.
If the fetch doesn’t match any strategy (which basically means that it falls under the last if (), the response is returned so in principle everything else remains untouched and passed from the network.
By default, a page’s fetches won’t go through a service worker unless the page request itself went through a service worker. So you’ll need to refresh the page to see the effects of the service worker.
So technically, a clients.claim() within fetch does nothing because fetch only goes through a service worker that has control of the page. From the same page:
You can take control of uncontrolled clients by calling clients.claim() within your service worker once it’s activated.
I want from my Meteor PWA to load much faster.
For instance, right now Telegram loads instantly, WhatsApp takes up to 3 seconds, and any Meteor app takes between 6 to 8 seconds.
It’s the Meteor initialization code that takes long to start up.