You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+68-52Lines changed: 68 additions & 52 deletions
Original file line number
Diff line number
Diff line change
@@ -21,122 +21,138 @@ These principles are inspired by [The Twelve-Factor App](https://12factor.net/).
21
21
22
22
## Decomposing a web application
23
23
24
-
The _Immutable Web App_ methodology was developed by through a process of decomposing web applications based on the principles declared above and then reconsidering the relationship between the different components. Before defining the methodology, this document will step through the decomposition. It starts with a monolithic web application.
24
+
The _Immutable Web App_ methodology was developed by through a process of decomposing web applications based on the principles declared above and then reconsidering the relationship between the different components. Before defining the methodology, this document will step through the decomposition.
25
25
26
-
### The Monolithic Web-Application
26
+
### The anatomy of a single-page application
27
27
28
-
There generally are three types of network traffic commonly made in by web application from the browser:
28
+
The infrastructure for a single-page application must support serving three different types of requests. These three types of requests have different characteristics that should impact the infrastructure that supports them.
29
29
30
-
#### static assets
30
+
#### document
31
+
32
+
- Entry point to the single-page application.
33
+
- A small HTML document that returns references to the static assets and just enough to bootstrap the loading of the application.
34
+
- Must not be cached by the browser so that changes to the document or static assets are immediately available. Changes are usually in the form of a deployment.
35
+
- Served for all routes that do not refer to static assets or apis to support client-side routing.
31
36
32
-
- javascript, css, images, bundled assets
33
-
- long term cached
34
-
- artifacts live on the client
37
+
#### static assets
35
38
36
-
#### xhr/fetch
39
+
- The javascript, css, images and other physical files that compose the single-page application.
40
+
- Properly versioned or fingerprinted static assets can be cached over a long term.
41
+
- Delivery is stable and unlikely to cause failures or web server downtime.
37
42
38
-
- dynamic
39
-
- no cache
43
+
#### api
40
44
41
-
#### the document
45
+
- All other dynamic http requests, usually executed as an XHR.
46
+
- Responses are seldom be cached by the browser.
47
+
- The complexity of api requests is higher, contain more dependencies, and more likely to cause failures than delivering static assets.
42
48
43
-
- typically in the form of `index.html`
44
-
- no caching
45
-
- returned for all routes that aren't physical files
49
+
### The Single-Page “Monolith”
46
50
47
51
> An image of typical network traffic for a simple single page application
48
52
49
-
A monolithic web application will handle the requests for all three types of requests. Express, a very popular node framework for building web applications, generally supports handling all three types of requests. Running the `express-generator` will create an application skeleton that supports routes for each:
53
+
All of the requests for an application can be handled by a single process. Express, a very popular Node.js web application framework, supports handling all three types of requests as a part of the same node process:
A monolithic web application will also include a web application framework, like Angular, for building the single-page application assets. Using Express and Angular together in a single code base will results in a multi-stage build:
79
+
#### Architecture
80
80
81
-
- First the static Angular apps are generated and
82
-
- Then the assets are embedded in the creation of the executable package (docker image, rpm).
81
+
> Image of a machine running the express nod app with static files in it serving all three request types
83
82
84
-
The package is then typically stored in a versioned repository of packages before it is deployed to a runtime environment.
83
+
- Web application
84
+
85
+
#### Workflow
85
86
86
87
> An image of the monolith build process: code => build static assets => build docker image with assets baked in => publish image to docker repo => deployed to server
87
88
88
-
#### Characteristics of the monolithic web application
89
+
1. First the static Angular apps are generated and
90
+
2. Then the assets are embedded in the creation of the executable package (docker image, rpm).
91
+
3. The package is then typically stored in a versioned repository of packages
92
+
4. It is deployed to a runtime environment.
89
93
90
-
- separation release tasks from build tasks (good)
91
-
- high cohesion between the backend and frontend contract (good)
92
-
- ability to test the same build artifact in multiple environments (good)
93
-
- if the backend goes down, so does the frontend - serving static assets is much more reliable then dynamic backends, and gracefully handling backend outages is a better user experience than 404s and 500s (bad)
94
-
- zero downtime deploys can be tricky considering caching and existing browser sessions (bad)
95
-
- complicated project dependencies that represent two very different jobs (bad)
96
-
- building a static web application assets
97
-
- running a web server
94
+
#### Characteristics
98
95
99
-
### Separate frontend from backend
96
+
There are several benefits to the encapsulation of an entire web application:
100
97
101
-
The first stage of decomposition is to separate the client from the server. This aligns with the principle of strict separation of dynamic content from static content.
98
+
- There is high cohesion between the contract of the client and the server.
99
+
- Creating a single executable package decouples the build from the deploy and enables the ability to test the package in multiple environments before promoting it to production, reducing risk during a live release.
102
100
103
-
> An image of the two separated build processes:
104
-
> code => build static assets => publish to static web server with routing rules
105
-
> code => build docker image => publish image to docker repo => deploy to server
101
+
However there are several drawback:
102
+
103
+
- Serving the static assets and api in the same process means that if the api causes a crash the web application is completely unavailable.
104
+
- The dependencies to run a web application are very different than the dependencies to generates the static assets. It can be difficult to manage the dependencies of the project in a way that does not bloat the codebase.
105
+
106
+
### The Single-Page Frontend/Backend
107
+
108
+
The first stage of decomposition is to separate the client from the server. This aligns with the principle of strict separation of dynamic content from static content. It also aligns with the best practices recommended by many web application platforms, like Angular.
106
109
107
-
#### The static web application
110
+
#### Architecture
108
111
109
-
code base generates static assets,
112
+
> Image of an web server with static files serving static assets and document, image of a web api serving api calls
110
113
111
-
The static assets can be deployed to a static web server that will have much higher reliability than the backend.
114
+
- Web server with static assets
112
115
113
-
The static web apps should generally be cached for the long term, the backend should have caching turned off.
116
+
- Web API
114
117
115
-
#### The backend api
118
+
#### Workflow
116
119
117
-
code base generates an executable package.
120
+
> An image of the two separated build processes:
121
+
> code => build static assets => publish to static web server with routing rules
122
+
> code => build docker image => publish image to docker repo => deploy to server
123
+
124
+
#### Characteristics
125
+
126
+
There are some improvements from the _single-page monolith_:
118
127
119
-
generally you can read up on 12 factor app for help here, as it has been decoupled from many of the web application specific concerns
128
+
- Two separate code bases are streamlined to handle their single responsibility.
120
129
121
-
#### Characteristics of the frontend/backend web application
130
+
- Independently hosting the static assets will allow the app to continue to operate even if the api is unavailable.
122
131
123
-
deployments require a little more careful sequencing to avoid zero-downtime. The backend may need to support multiple versions of an app as the frontend is deployed from one version to another. this is good, because it makes an preexisting problem more visible.
132
+
But we have also introduced some complexity:
124
133
125
-
Code bases for generating the backend and the code base for generating the static application is separated.
134
+
- Application platforms, like Angular, recommend defining environment specific configuration at build time. This eliminates the portability of the assets and effectively eliminates the separation of deploy tasks from build tasks.
126
135
127
-
Client side assets are often environment specific and deployed right after they are built as a part of a release.
136
+
- There is less cohesion between the frontend and the backend. Because they are not deployed atomically, deployments must be phased to support multiple running versions of the application. The reality is that this is also a problem with single-page monoliths, it is just not as obvious.
128
137
129
-
### index.html as a special file
138
+
### The Single-Page Decomposed App
130
139
131
-
The second stage of decomposition continues to emphasize the strict separation of dynamic content from static content by separating `index.html`.
140
+
The second stage of decomposition is going to separate the document (typically, `index.html`) from the static assets.
132
141
133
142
The document, `index.html`, is a bit of a special case. It may be a static file from the perspective of a specific deployment, but over the lifetime of multiple deployments, it is a dynamic file... evident by the fact that it cannot be cached at any location by the browser. Moreover, it has routing responsibilities that are unlike any of the other static assets or apis.
134
143
144
+
#### Architecture
145
+
135
146
> An image of the three separated build processes:
136
147
> code => build static assets => publish to static web server
137
148
> code => build docker image => publish image to docker repo => deploy to server
138
149
> index.html => publish to static web server that always returns index.html
139
150
151
+
#### Workflow
152
+
153
+
154
+
155
+
140
156
#### `index.html`
141
157
142
158
can be hosted by a static web server that for whatever path it is requested it always returns `index.html`
@@ -145,7 +161,7 @@ can be hosted by a static web server that for whatever path it is requested it a
145
161
146
162
it allows us to simplify the hosting of all other static assets, all other static assets can be hosted in a completely different domain, and cached for long term if they are versioned or fingerprinted
147
163
148
-
#### Characteristics of the index/frontend/backend web application
164
+
#### Characteristics
149
165
150
166
assets can be build prior to deployment, a live release is effectively the act of updating `index.html`, but opportunities for testing them are limited.
0 commit comments