In this How to! we'll see how we can convert our mendix app to a PWA and enable precaching for the static resources using Workbox.
-
You need to have Nodejs installed on your machine.
-
You need to install Workbox CLI globally on your machine:
> npm install workbox-cli --global
-
You need to have Lighthouse on your machine (You can skip this step if you have chrome installed on your machine).
-
The explanation is assuming that you have a blank mendix app (this does NOT mean that you cannot use it for an existing app, but rather for the seek of clarity in folder structures and naming conventions).
1. First, let's start by copying some files into our mendix app.
>> Copy the following files in the MX_APP_ROOT_FOLDER/theme
folder:
//manifest.json
{
"short_name": "Mendix PWA",
"name": "Mendix Starter PWA",
"start_url": "index.html",
"icons": [
{
"src": "logo.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "logo.png",
"sizes": "192x192",
"type": "image/png"
}
],
"display": "standalone",
"theme_color": "#0595DB",
"background_color": "#ffffff"
}
-
logo.png your app's logo.
-
swRegister.js this script will register the service worker in the browser.
>> Copy the following files in the MX_APP_ROOT_FOLDER
folder:
- workbox-config.js, the configuration file which will be used by
workbox
to generate the service worker.
This configurations understand how a mendix application works. However, you can customize it for your app's needs, for more information check here.
module.exports = {
globDirectory: "deployment/web", // as the static resources will be
globPatterns: [
"**/*.{json,png,css,ico,jpg,gif,html,js,eot,svg,ttf,woff,woff2,txt,xml}",
],
// set URLs that served by the server and you do nt have direct access to them from within your project.
// e.g. in a mendix application the client js & css
// e.g. if your styles request external resources fonts, images, etc..
templatedURLs: {
"mxclientsystem/mxui/mxui.js": "mxui-client-core",
"mxclientsystem/mxui/ui/mxui.css": "mxui-styling",
"https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700":
"font-set-1",
},
// here you set URLs patterns for the resources the will be requested in runtime, or later by user interaction
// you may will customize this for the needs of your application
runtimeCaching: [
{
// Match any same-origin request that contains has the following path.
urlPattern: /mxclientsystem\/dojo/,
// Apply a cache-first strategy.
handler: "CacheFirst",
},
{
// Match any cross-origin request that contains that comes from this origin.
urlPattern: /https:\/\/fonts\.googleapis\.com/,
// Apply a cache-first strategy.
handler: "CacheFirst",
},
],
// generate a service worker file 'sw.js' and put it in 'theme' folder.
swDest: "theme/sw.js",
ignoreURLParametersMatching: [/./], // this is needed to ignore mx cache busting
cleanupOutdatedCaches: true,
cacheId: "MxApp-Cache",
};
2. Add the required meta tags & scripts to MX_APP_ROOT_FOLDER/theme/index.html
file.
>> add the following tags inside your <head>...</head>
tag:
<meta name="description" content="This a Mendix PWA Starter App.">
<meta name="theme-color" content="#ffffff">
<link rel="manifest" href="/manifest.json">
>> add the following <noscript>...</noscript>
tag inside your <body>...</body>
tag:
<noscript>
<div class="container noscript-container">
<h3>Please enable javascript in your browser</h3>
<h4><a class="mx-link" href='https://www.wikihow.com/Enable-JavaScript'>How to enable javascript in my browser</a></h4>
</div>
</noscript>
>> add the following script inside your <body>...</body>
tag:
<noscript>
<div class="noscript-container">
<h3>Please enable javascript in your browser</h3>
<h4><a class="mx-link" href='https://www.wikihow.com/Enable-JavaScript'>How to enable javascript in my browser</a></h4>
</div>
</noscript>
>> add the following script before the closing body
tag:
....
<script src="swRegister.js"></script>
</body>
....
Your index.html
file should look like this example file: index.example.html.
Note: If you're targeting IOS devices, please consider checking this article as well, as we are here focusing on android devices.
3. Generating service worker using workbox.
>> Open your command line in your MX_APP_ROOT_FOLDER
and run the following command:
> workbox generateSW
This command will make use of the configurations in our workbox-config.js
to generate a service worker sw.js
in the theme
folder of our app.
Note: before running this command, make sure that you have built your application (in other words your
deployment/web
folder is not empty) by running the app locally this folder will be generated.
🚀🚀 Now everything is set, re-rurn your app, and then it has all the required settings/files for a PWA, you can check if you're app has become a PWA using Lighthouse
4. Repeat.
Perform this command each time you have change in your static assets (mendix pages are also considered static assets).
You're most likely going to perform this only before creating your (test/accpetance/production) build.
- When running locally, it is recommended to use specific port numbers for developing PWAs which is different from the the ones you use for the normal web apps as the PWAs make use of service workers which will be registered in the browser and linked to your app domain and intercept requests for resources to this domain and return the resources from the cache if these resources are already cached, therefore using the same port numbers without clearing the cache when switching between apps could lead to the wrong assets being served, e.g. consider you have the app
my_pwa
is running onlocalhost:3000
, this app registered a service worker and this service worker savedindex.html
in the cache, now you want to work on yourmy_normal_app
(not a pwa) which is also running onlocalhost:3000
, ifmy_normal_app
requestsindex.html
the already registered service worker will intercept this request and return back the cachedindex.html
which belongs to a completely different app and that's completely wrong and confusing, so make sure to clear your cache and unregister service workers before switching to work on a different app that runs on the same port.