Skip to content

Commit 09a5865

Browse files
committed
adding more structure to the 'decomposition' section, unfinished.
1 parent dd75f83 commit 09a5865

File tree

1 file changed

+68
-52
lines changed

1 file changed

+68
-52
lines changed

README.md

Lines changed: 68 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -21,122 +21,138 @@ These principles are inspired by [The Twelve-Factor App](https://12factor.net/).
2121

2222
## Decomposing a web application
2323

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.
2525

26-
### The Monolithic Web-Application
26+
### The anatomy of a single-page application
2727

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.
2929

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.
3136

32-
- javascript, css, images, bundled assets
33-
- long term cached
34-
- artifacts live on the client
37+
#### static assets
3538

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.
3742

38-
- dynamic
39-
- no cache
43+
#### api
4044

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.
4248

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”
4650

4751
> An image of typical network traffic for a simple single page application
4852
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:
5054

5155
```javascript
5256
var express = require('express');
5357
var path = require('path');
54-
var cookieParser = require('cookie-parser');
55-
var logger = require('morgan');
5658

5759
var indexRouter = require('./routes/index');
5860
var usersRouter = require('./routes/users');
5961

6062
var app = express();
6163

62-
app.use(logger('dev'));
6364
app.use(express.json());
6465
app.use(express.urlencoded({ extended: false }));
65-
app.use(cookieParser());
6666

6767
/* serves static assets */
6868
app.use(express.static(path.join(__dirname, 'public')));
6969

7070
/* serves the document */
7171
app.use('/', indexRouter);
7272

73-
/* serves dynamic requests */
73+
/* serves the api */
7474
app.use('/users', usersRouter);
7575

7676
module.exports = app;
7777
```
7878

79-
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
8080

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
8382
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
8586

8687
> 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
8788
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.
8993

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
9895

99-
### Separate frontend from backend
96+
There are several benefits to the encapsulation of an entire web application:
10097

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.
102100

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.
106109

107-
#### The static web application
110+
#### Architecture
108111

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
110113
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
112115

113-
The static web apps should generally be cached for the long term, the backend should have caching turned off.
116+
- Web API
114117

115-
#### The backend api
118+
#### Workflow
116119

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_:
118127

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.
120129

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.
122131

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:
124133

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.
126135

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.
128137

129-
### index.html as a special file
138+
### The Single-Page Decomposed App
130139

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.
132141

133142
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.
134143

144+
#### Architecture
145+
135146
> An image of the three separated build processes:
136147
> code => build static assets => publish to static web server
137148
> code => build docker image => publish image to docker repo => deploy to server
138149
> index.html => publish to static web server that always returns index.html
139150
151+
#### Workflow
152+
153+
154+
155+
140156
#### `index.html`
141157

142158
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
145161

146162
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
147163

148-
#### Characteristics of the index/frontend/backend web application
164+
#### Characteristics
149165

150166
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.
151167

0 commit comments

Comments
 (0)