forked from DannyMoerkerke/instant-multi-page-app
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
132 lines (118 loc) · 5.2 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<base href="/">
<title>Instant Multi-Page App</title>
<link rel="icon" href="favicon.ico" type="image/x-icon"/>
<link rel='shortcut icon' type='image/x-icon' href='favicon.ico'>
<link rel="stylesheet" href="src/css/styles.css">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body>
<header>
<nav>
<material-dropdown>
<i class="material-icons" slot="icon" tabindex="1">menu</i>
<li slot="option"><a href="/">Home</a></li>
<li slot="option"><a href="/readablestream">Readable Stream</a></li>
<li slot="option"><a href="/serviceworker">Service Worker</a></li>
<li slot="option"><a href="/images">Images</a></li>
<li slot="option"><a href="/blog">Blog</a></li>
</material-dropdown>
<a href="https://github.com/DannyMoerkerke/instant-multi-page-app" target="_blank" rel="noopener" id="github">
<img src="src/img/github.svg" />
</a>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/readablestream">Readable Stream</a></li>
<li><a href="/serviceworker">Service Worker</a></li>
<li><a href="/images">Images</a></li>
<li><a href="/blog">Blog</a></li>
</ul>
</nav>
</header>
<main>
<section id="content">
<h2>An instant multi-page app</h2>
<p>
This is a demo of a instantly loading multi-page app, using modern web technology like Service Worker,
ReadableStream and CSS Containment.
</p>
<p>
The purpose is to demonstrate that a multi-page app can load just as fast as a single-page app, without all
the
added complexity that a single-page app brings.
</p>
<p>
Each request is intercepted by the Service Worker which then constructs each page from a header, footer and
the
page content. These parts are all separate HTML templates that are fetched separately and then put together to
form
a page.
</p>
<p>
To make sure that content is shown to the user as soon as possible, a ReadableStream is used to stream content
to
the browser. This means that the browser doesn't need to wait for the whole response to arrive, but can start
rendering content as soon as it becomes available.
</p>
<p>
The Service Worker also caches all assets locally so these no longer need to be fetched from the network.
</p>
<p>
The result is that each page loads instantly, just like a single-page app, even though the browser performs a
full
page reload for each page.
</p>
<p>
This effectively reduces single-page apps to a polyfill.
</p>
<h2>How it works</h2>
<p>
The trick to making multi-page apps blazing fast is utilizing the browser's streaming HTML
parser.
</p>
<p>
The browser renders HTML while it downloads. It doesn't need to wait for the whole response to arrive,
but it can start rendering content as soon as it becomes available.
</p>
<p>
We can leverage this by having a Service Worker fetch all the content we need and have it stream everything
to the browser.
</p>
<p>
The Service Worker will then intercept any outgoing request, fetch the header and footer and then determine
which body content it needs to fetch. This can be just a simple HTML template or a combination of a template
and some data fetched from the network.
</p>
<p>
The Service Worker will then combine these parts to a full HTML page and return it to the browser. It's like server-side
rendering, but it's all done on the client-side in a streaming manner, using a <code>ReadableStream</code>.
</p>
<p>
This means it can start rendering the header of the page while the content and footer are still downloading,
giving a <em>huge</em> performance benefit.
</p>
<p>
The demo contains some simple text pages, a page with some large images and a page containing some postings from my
blog which are dynamically fetched, combined into a large HTML page and then cached.
</p>
<p>
You will notice that even the large blog page and the page containing the large images load nearly instantly, even
though every page requires a full page reload.
</p>
<p>
This is how good browsers are at rendering the DOM <em>if we use the streaming HTML parser</em>.
</p>
<p>
You can find the source code of this demo on
<a href="https://github.com/DannyMoerkerke/instant-multi-page-app" target="_blank" rel="noopener">Github</a>.
</p>
</section>
</main>
<footer></footer>
<script type="module" src="src/js/index.js"></script>
</body>
</html>