Become a backer or sponsor to support our work.
PWAs (Progressive web apps) are web apps developed using a number of specific technologies and standard patterns to allow them to take advantage of both web and native app features. The PWA module includes preliminary support for Hugo sites, see the features below.
Module | github.com/hugomods/pwa |
---|---|
Stats |
You may still be a bit confused about the features, the following video will show what the module can bring to your sites. You can also give it a shot on our website or the demo site.
This section is for theme developers to integrate this module with their themes.
There is a demo site and it’s source code to help you get started.
hugo.yaml
1module:
2 imports:
3 - path: github.com/hugomods/pwa
hugo.toml
1[module]
2 [[module.imports]]
3 path = 'github.com/hugomods/pwa'
hugo.json
1{
2 "module": {
3 "imports": [
4 {
5 "path": "github.com/hugomods/pwa"
6 }
7 ]
8 }
9}
The meta partial generate the manifest meta tag to tell browser the location of web app manifest.
1<head>
2 {{ partialCached "pwa/assets/meta" . }}
3</head>
1{{ $css := resources.Get "main.css" }}
2<link href="{{ $css.RelPermalink }}" rel="stylesheet" />
3{{/* THIS OPERATION CANNOT BE BE CACHED BY partialCached. */}}
4{{ partial "pwa/functions/precache" (dict "URL" $css.RelPermalink "Page" .) }}
1{{ $js := resources.Get "main.js" }}
2<script src="{{ $js.RelPermalink }}"></script>
3{{/* THIS OPERATION CANNOT BE BE CACHED BY partialCached. */}}
4{{ partial "pwa/functions/precache" (dict "URL" $js.RelPermalink "Page" .) }}
As the comments said, pwa/functions/precache
cannot be cached, since Hugo renders pages concurrently.
sequenceDiagram participant P1 as Page1 participant H as Hugo participant P2 as Page2 P1->>H: Precache CSS. H-->>P1: Done! P2->>H: Precache CSS. H-->>P2: Cache found, ignored! P2->>H: Precache JS. H-->>P2: Done! P1->>H: Precache JS. H-)P1: Cache found, ignored!
The example above shows the case of caching the pwa/functions/precache
operations.
So far, the Page1
precaches the CSS, while the Page2
precaches the JS, in either case, the service worker not aware of all the resources that need to be precached.
Finally, import the pwa/assets/sw
partial to generate service worker script.
<body>
.1<body>
2...
3{{ partialCached "pwa/assets/sw" . }}
4</body>
It’s recommended to use partialCached
to cache the partial for getting better build performance.
This module provides a built-in offline page with inline style, you can change it by creating the layouts/_default/index.offline.html
file.
This section is for theme users to set up the PWA.
Append the Offline
and WebAppManifest
format into the outputs.home
, to generate the offline page and web app manifest.
hugo.yaml
1outputs:
2 home:
3 - HTML
4 - RSS
5 - Offline
6 - WebAppManifest
hugo.toml
1[outputs]
2 home = ['HTML', 'RSS', 'Offline', 'WebAppManifest']
hugo.json
1{
2 "outputs": {
3 "home": [
4 "HTML",
5 "RSS",
6 "Offline",
7 "WebAppManifest"
8 ]
9 }
10}
Parameter | Type | Default | Required | Description |
---|---|---|---|---|
debug | boolean | false | - | Whether to enable the debug mode. |
icon_path | string | images/pwa/icon.png | - | The icon image relative to the assets folder, which used to generate icons in multiple sizes. |
icon_sizes | array | [48, 64, 128, 144, 256, 512] | - | The target sizes of icons. |
offline_image | string | images/pwa/offline.png | - | The offline image relative to the assets folder, which will be shown when request an image offline. |
precaches | array | [] | - | Custom precache files. |
precaches.url | string | - | - | The URL of precache file. |
caches | object | - | - | Cache settings. |
caches.font | object | - | - | Font cache settings. |
caches.font.origins | array | [] | - | Trusted origins2. |
caches.font.strategy | string | cache-first | - | Font cache strategy1. |
caches.font.max_age | string | 2592000 | - | Font cache max age in second. |
caches.image | object | - | - | Image cache settings. |
caches.image.origins | array | [] | - | Trusted origins2. |
caches.image.strategy | string | cache-first | - | Image cache strategy1. |
caches.image.max_age | string | 2592000 | - | Image cache max age in second. |
caches.script | object | - | - | Script cache settings. |
caches.script.origins | array | [] | - | Trusted origins2. |
caches.script.strategy | string | cache-first | - | Script cache strategy1. |
caches.script.max_age | string | 2592000 | - | Script cache max age in second. |
caches.style | object | - | - | Style cache settings. |
caches.style.origins | array | [] | - | Trusted origins2. |
caches.style.strategy | string | cache-first | - | Style cache strategy1. |
caches.style.max_age | string | 2592000 | - | Style cache max age in second. |
manifest | object | - | - | Manifest settings, such as theme_color , background_color . |
This module doesn’t provide the built-in icon and offline images, you’ll need to save your icon and offline images to corresponding path.
hugo.yaml
1params:
2 pwa:
3 caches:
4 font:
5 max_age: 2592000
6 origins: []
7 strategy: cache-first
8 image:
9 max_age: 2592000
10 origins: []
11 strategy: cache-first
12 script:
13 max_age: 2592000
14 origins: []
15 strategy: cache-first
16 style:
17 max_age: 2592000
18 origins: []
19 strategy: cache-first
20 debug: false
21 icon_path: images/pwa/icon.png
22 icon_sizes:
23 - 48
24 - 64
25 - 128
26 - 144
27 - 256
28 - 512
29 manifest:
30 background_color: '#ff4088'
31 theme_color: '#ff4088'
32 offline_image: images/pwa/offline.png
33 precaches:
34 - url: /
35 - url: foo.png
hugo.toml
1[params]
2 [params.pwa]
3 debug = false
4 icon_path = 'images/pwa/icon.png'
5 icon_sizes = [48, 64, 128, 144, 256, 512]
6 offline_image = 'images/pwa/offline.png'
7 [params.pwa.caches]
8 [params.pwa.caches.font]
9 max_age = 2592000
10 origins = []
11 strategy = 'cache-first'
12 [params.pwa.caches.image]
13 max_age = 2592000
14 origins = []
15 strategy = 'cache-first'
16 [params.pwa.caches.script]
17 max_age = 2592000
18 origins = []
19 strategy = 'cache-first'
20 [params.pwa.caches.style]
21 max_age = 2592000
22 origins = []
23 strategy = 'cache-first'
24 [params.pwa.manifest]
25 background_color = '#ff4088'
26 theme_color = '#ff4088'
27 [[params.pwa.precaches]]
28 url = '/'
29 [[params.pwa.precaches]]
30 url = 'foo.png'
hugo.json
1{
2 "params": {
3 "pwa": {
4 "caches": {
5 "font": {
6 "max_age": 2592000,
7 "origins": [],
8 "strategy": "cache-first"
9 },
10 "image": {
11 "max_age": 2592000,
12 "origins": [],
13 "strategy": "cache-first"
14 },
15 "script": {
16 "max_age": 2592000,
17 "origins": [],
18 "strategy": "cache-first"
19 },
20 "style": {
21 "max_age": 2592000,
22 "origins": [],
23 "strategy": "cache-first"
24 }
25 },
26 "debug": false,
27 "icon_path": "images/pwa/icon.png",
28 "icon_sizes": [
29 48,
30 64,
31 128,
32 144,
33 256,
34 512
35 ],
36 "manifest": {
37 "background_color": "#ff4088",
38 "theme_color": "#ff4088"
39 },
40 "offline_image": "images/pwa/offline.png",
41 "precaches": [
42 {
43 "url": "/"
44 },
45 {
46 "url": "foo.png"
47 }
48 ]
49 }
50 }
51}
The default parameters is best for production, but will be bad for development, because you may see a cached, out-of-date page and have to clear the cache or do a force refresh.
But don’t worry, we can fix it by changing the default cache strategies1 for development environment.
config/development/hugo.yaml
1params:
2 pwa:
3 caches:
4 font:
5 strategy: network-first
6 image:
7 strategy: network-first
8 script:
9 strategy: network-first
10 style:
11 strategy: network-first
config/development/hugo.toml
1[params]
2 [params.pwa]
3 [params.pwa.caches]
4 [params.pwa.caches.font]
5 strategy = 'network-first'
6 [params.pwa.caches.image]
7 strategy = 'network-first'
8 [params.pwa.caches.script]
9 strategy = 'network-first'
10 [params.pwa.caches.style]
11 strategy = 'network-first'
config/development/hugo.json
1{
2 "params": {
3 "pwa": {
4 "caches": {
5 "font": {
6 "strategy": "network-first"
7 },
8 "image": {
9 "strategy": "network-first"
10 },
11 "script": {
12 "strategy": "network-first"
13 },
14 "style": {
15 "strategy": "network-first"
16 }
17 }
18 }
19 }
20}
Available strategies: cache-first, network-first and stale-while-revalidate. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Only trusted third-party origin resources will be cached, such as https://example.com
, https://example.org/
. ↩︎ ↩︎ ↩︎ ↩︎