-
-
Notifications
You must be signed in to change notification settings - Fork 37
/
SPEC-draft.txt
426 lines (316 loc) Β· 16 KB
/
SPEC-draft.txt
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
Deployment artifact & hosting runtime for frontend applications
Abstract
This document describes a format to package up any browser based
application, regardless of patterns, framework or toolkit so that it
can run in any hosting environment that confirms to the hosting
specification.
It is aiming to achieve for frontends what Docker did for backends.
Requirements Language
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in BCP
14 [RFC2119][RFC8174] when, and only when, they appear in all
capitals, as shown here.
Table of Contents
1. Introduction
1.1. Terminology
2. Anatomy of a frontend application
2.1. Server
2.2. Client Side Assets
3. Design considerations & constraints
3.1. Reliability
3.2. Compatibility
3.2.1. Application compatibility
3.2.2. Hosting compatibility
3.2.3. Advanced use-cases
3.3. Performance
3.4. Developer Experience
3.4.1. Application developers
3.4.2. Application framework developers
3.4.3. Hosting Provider developers
4. Frontend Application Bundle format
4.1 Static Assets
4.1.1 URL scheme
4.1.2 Caching behaviour
4.1.3 Performance optimisations
4.1.3.1 Content-Encoding
4.1.3.2 Content-Type
4.2 Server component
5. Server JavaScript interface
5.1 Render method
5.2 Production settings
5.2.1 Encrypted variables
5.3 metadata
6. Hosting runtime specification
6.1 Fetch
1. Introduction
Frontend applications (Applications running in a browser and often
connecting to one or backends via APIs) are gaining popularity,
leading to an explosion of practices, libraries, frameworks and
toolkits.
And at the same time the options for hosting have ballooned as well.
Not too long ago the two main options were either static hosting or
running your own servers, possibly on an Infrastructure as a Service
solution (IaaS).
But now we have an entire range of options ranging from static
hosting, through serverless (edge) hosting, Platforms as a Service
and IaaS.
Frontend Application Bundle is a specification which both describes a
deployment artifact and a hosting runtime. So that any frontend
application can be run in any server that is implements the hosting
runtime.
In short, FAB is aiming to be the lingua franca between code on
one end and the hosting infra on the other.
The hope is that this will allow us to build the next level of
abstractions on top, just like it happened with Docker.
1.1 Terminology
Frontend Application: An application that runs inside the browser and
may optionally connect to one or more backends for data and business
logic.
2. Anatomy of a frontend application
Any frontend application consists of two parts: a Server and Client
Side Assets.
2.1 Server
The Server is the part of the application to responds to HTTP
requests. At a bare minimum the only thing it does is serve the
Client Side Assets.
But it may do a lot more, including, but not limited to, generating
HTML pages and other assets on the fly.
In many frontend applications, the server is a regular static file
hosting service that serves a static HTML file.
2.2 Client Side Assets
The Client Side Assets are the files that contain the code and other
assets that run inside the browser such as Javascript or CSS files
images or configuration.
3. Design considerations & constraints
The design of the FAB specification is driven by a list of qualities
that we strive for in particular order. Whenever we need to make a
trade-off, the higher ordered quality weighs more heavily than lower
ordered qualities.
Implementors of the specification SHOULD follow the same list of
qualities when considering trade-offs.
3.1. Availability & Reliability
As FABs will be used by applications in production, it is
vital that reliability is our absolute top priority.
We MUST always strive to optimise for the availability of
applications. This implies a few other related qualities, such as
security, predictability, resilience and ability to recover from
errors.
It is this reliability that will generate trust in the ecosystem and
our deploys, allowing application developers to release more often.
This will generate a virtuous cycle of more frequent, less risky
releases.
There MUST NOT be any downtime for regular deploys.
Most importantly, the functional behaviour of an application MUST
be the same when run in different hosting environments with the same
settings.
A hosting environment MAY have different performance characteristics
and other optimisations.
3.2. Compatibility
Because the purpose of Frontend Application bundles is to provide
a standard for packaging frontend applications and the runtime
environment they run in, it is important that it is compatible with
as many different applications and hosting providers.
3.2.1. Application compatibility
There are many different patterns, frameworks and practices when it
comes to frontend applications. Broadly speaking there are three
patterns: "Pre-rendering", "Client-Side Rendering" (CSR) and
"Server-Side Rendering" (SSR).
And while we should always strive to support as wide a variety of
applications, we should optimise for the more dynamic ones, such as
SSR and CSR.
3.2.2. Hosting compatibility
For FABs to be successful it needs to not only support a large amount
of applications, but also hosting providers.
The requirements for a hosting provider should be as low as possible.
It should run on serverless (edge) hosting platforms, but also on
large distributed hosting clusters.
It must be possible to deploy the static assets and the server
components to two seperate and specialised systems.
And lastly it should be possible to host FABs on hosting providers
that do not yet support FABs natively, so that the FAB community can
create adapters/wrappers for that particular hosting runtime.
And while we see great promise in non-Javascript languages on the
browser platform (particularly WebAssembly), we are currently only
specifying a JavaScript/Typescript server interface.
3.2.3. Advanced use-cases
A lot of advanced use-cases for FABs (blue/green deployments, canary
releases & A/B testing to name just a few) rely on the ability to run
multiple bundles in production concurrently. Either different
applications or different versions of the same application.
Not every hosting provider must support these use-cases, but
decisions must not be made that make this impossible.
3.3. Performance
Performance is critical for a lot of applications. So hosting
runtimes SHOULD automatically optimise as much as possible. And
both framework and application developers SHOULD be able to
easily customise the behaviour of the server component to improve the
performance of the application.
3.4. Developer Experience
No software ecosystem thrives without a focus on the experience of
the developers using it. We recognise 3 different types of
developers, each with different skills and objectives.
3.4.1. Application developers
Application developers are the developers working on the frontend
application that will be used by end users.
The experience they have with FABs are the most important one to
consider. Both because there are many more of them than both
framework and hosting runtime developers, but also because they have
less experience and knowledge when it comes to writing reliable and
performant applications to be able to make the right trade-off.
A lot of these developers may not even know they are using FABs.
3.4.2. Application framework developers
Application framework developers are the people working on the
building blocks that are used by the Application Developers to
create their applications. It is these application frameworks that
may have logic to output a FAB as a deployment artefact.
By making it easy to output a FAB it will lower the bar for different
frameworks to support it natively.
3.4.3. Hosting Provider developers
These are the developers working on the hosting runtimes. Their
experience isn't about making it easier, but to allow them to build
the best possible runtime that their hosting platform will allow
them to build.
4. Frontend Application Bundle format
A FAB is a regular zip file which mirrors the two components of a
frontend application. It includes a director called '_assets', which
includes all the static assets that are used by the application and
a file called 'server.js' that handles all server logic.
-- server.js
|
- _assets - main.abcd1234.js
|
- main.bcdef567.css
4.1 Static Assets
Static assets are files such as client side Javascript and CSS files,
images, configuration files or templates or any other content that is
not dynamically generated.
4.1.1 File structure
These files are stored in the top level '_assets' directory inside
the zip file.
Because these files will be cached for a very long time in Content
Delivery Networks, intermediate proxies and client browsers
(see 4.1.2), it is RECOMMENDED that the filename includes a unique
fingerprint based on the content of the file such as (a part of) a
hash of the contents.
4.1.1 URL scheme & availability
Hosting runtimes MUST make the files available on the '/_assets/'
relative URL for fetches made from the FAB server code.
Hosting runtimes SHOULD make them available on the same pathname for
external HTTP clients, but MAY give applications the option to
disable this to force all statis assets to be served through the
server code. This makes it possible to do authentication or
authorization in the server code.
So '/_assets/js/main.abcd12345.js' in the zipfile MUST map to the
'/_assets/js/main.abcd12345.js' from the server code and SHOULD map
to 'https://example.com/_assets/js/main.abcd12345.js' from external
HTTP clients.
A hosting runtime SHOULD serve assets that were deployed through
older FABs, because most frontend applications can be open for a long
time and not serving those assets could result in runtime exceptions.
4.1.2 Caching behaviour
To improve the performance of the frontend application, all files
served at the '/_assets/` URL pathname prefix MUST be served with the
following headers:
Cache-Control: public, max-age=31536000, immutable
Vary: Accept, Accept-Encoding
4.1.3 Performance optimisations
A hosting runtime SHOULD optimise the performance of the application
without affecting the availability of functionality of the
application. If offering performance optimisations that have the
potential to affect the availability or functionality of an
application it MUST have implicit or explicit permission of the
application to do so.
4.1.3.1 Content-Encoding
Compression is one of the many techniques used to improve the
performance of web sites & applications. Beyond the content
negotion as specified in the HTTP specification, there are some
additional recommendations for FAB hosting runtimes.
If an application has included a text-based asset file with the same
filename, but including the '.br' suffix, the hosting runtime SHOULD
serve that file with the Brotli content-encoding 'br' set if the client
including Brotli support in the Accept-Encoding header.
So a request for:
GET /_assets/main.abcde1234.js HTTP/1.1
Host: www.example.com
User-Agent: UA 1.1
Accept-Encoding: br, gzip, deflate
Accept: */*
when a file called '/_assets/main.abcde1234.js.br' is available, the
runtime SHOULD respond with this file as the body and the following
headers:
HTTP/1.1 200 OK
Content-Encoding: br
Cache-Control: public, max-age=31536000, immutable
Vary: Accept, Accept-Encoding
...
It is RECOMMENDED that a hosting runtime precompresses any assets
that aren't already compressed by the application (framework).
4.1.3.2 Content-Type
In a similar vein, a runtime SHOULD also check for the presence of
alternative binary formats. The two most obvious examples being
WEBP and AVIF for images.
If a file with the same basename, but different extension is present,
the runtime SHOULD respond with that first match in the Accept
header.
GET /_assets/hero.12345abcd.jpg HTTP/1.1
Host: www.example.com
User-Agent: UA 1.1
Accept: image/avif, image/webp, */*
and no file with filename '/_assets/hero.12345abcd.avif' is available,
but `/_assets/hero.12345abcd.webp` is, the hosting runtime SHOULD
respond with the `/_assets/hero.12345abcd.webp` file as the body of the
response and the following headers:
HTTP/1.1 200 OK
Content-Type: image/webp
Cache-Control: public, max-age=31536000, immutable
Vary: Accept, Accept-Encoding
...
A hosting runtime MAY generate these alternative formats ondeployment, but
MUST make sure application developers are aware and SHOULD allow them to
opt-out.
4.2 Server component
What sets Frontend Application Bundles apart from regular static assets
deployments is that it contains server logic for serving requests. The code
for this is contained in a single javascript file in the root directory
called 'server.js'.
The reason for the single file is to make it easier for hosting runtimes to
manage multiple versions of the same application without introducing
versioning bugs. The server and all its dependencies are contained in one
file. And because the file is re-used for many requests and servers generally
have much better network connections than clients, create one large bundle
is not much of a bottleneck.
The Javascript interface of the server.js is described in chapter 5.
5. Server JavaScript interface
The server.js is a CommonJS compatible JavaScript file with 3 exports:
* getProdSettings()
* render(request, settings) => response
* metadata property
The exports are described in more detail below
5.1 Render method
The core method of a FAB is a single render method that takes a Request
object and a settings object and returns either a Response or a Request
object. The Request and Response objects are defined in the JavaScript
Fetch specification at: https://fetch.spec.whatwg.org/
The settings object is a dictionary of key/value pairs. The contents of the
settings object is not specified, but MUST contain all the configuration
that the application needs to function. This can include API URLs, secrets
or feature flags.
When the FAB returns a Response object the hosting runtime MUST create a
HTTP response to the client that corresponds with the content of the
Response object returned by the FAB.
When the FAB returns a Request object it signals to the hosting runtime that
it should proxy that request to the client. The hosting runtime MAY return
a cached copy, if it has one cached.
The one change from the Fetch spec is that the FAB may return a Request
object with a relative URL starting with `/_assets/`. To signal it would
like to return one of the static assets.
5.2 Production settings
TODO: Production settings in the bundle. Doesn't break 12 factor apps.
Makes it so that every change to production code has a corresponding commit
in the repository.
5.2.1 Encrypted variables
Most settings for frontend applications are not secret, as most of them end
up in the browser, where anyone can see them. But it is possible to have
server-only settings that should stay secret. We will be defining an
interface on how to handle that later.