Immutable Web applications are a frame-independent approach for building and deploying static, single-page applications:
- Minimize the risk and complexity of real-time publishing.
- Simplify and maximize caching.
- Minimize the need for server and runtime environment management.
- Continuous delivery through simple, flexible atomic deployment.
This method is based on the principle of strict separation:
- Configuration from code.
- Release the task from the build task.
- Dynamic content from static content.
The following concepts define the core requirements of an immutable Web application. They have nothing to do with frameworks and infrastructure.
Static assets are independent of the web application environment(s)
Static assets must not contain anything that is environment-specific
All the leading application frameworks (Angular CLI, Create React App, Ember CLI, Vue CLI 3) recommend defining environment variables at compile time. This approach requires that static assets be generated for each environment and regenerated for any changes to the environment.
Immutable Web applications refer to environment variables defined at a global scope and refer to them in one of two ways:
- Directly from the window object
- Injection of services by wrapping environment variables
Static assets must be hosted in a unique and independent location from the Web application environment.
Static assets that do not contain any particular environment can be built once, published to a unique location, and then used in multiple environments of a Web application.
The location of the jQuery library above, referenced by countless Web applications, is both application-independent and unique.
Configure the static assets for long-term caching
Static assets that do not contain any environment-specific content and are hosted in a unique and permanent location can be configured to be cached (almost) indefinitely by the browser:
cache-control: public, max-age=31536000, immutable
Index.html is a deployable configuration
The HTML document for a single-page application (typically index.html) is not static. It varies by environment and by deployment destination. An HTML document is a combination of environment-specific configuration and immutable static assets that define a Web application.
Index.html contains fully qualified references to static assets.
Here’s an example:
index.html must never be cached
Note: To allow for immediate changes to the Web application environment, index.html must not be cached by browsers or public caches that cannot be cleared on demand:
Immutable Web applications separate publish and build tasks into two different workflows.
The code base of an immutable Web application is responsible for building static assets and publishing them to a static Web server. Each state of a code base can be represented by a set of static assets in a unique location. Not every state of a codebase needs to be published, but no single state of a codebase needs to be published multiple times.
Typically, a code base is a source-control code repository that is integrated with a continuous integration system that can build, versioning, and publish static assets to a static Web server.
An example of this might be:
An Angular project hosted in a GitHub repository. When a commit is pushed to the main branch, the repo integrates with TravisCI to build and version the asset. Versioned assets are published to a unique place in the AWS S3 bucket.
The index.html files are managed independently of the code base and act as a manifest for each environment. They should be treated as configuration files and managed accordingly. In addition, you need a mechanism to modify or replace index.html in each Web application environment. The act of changing index.html is actually a deployment.
An example of this might be:
A set of index.html files, one for each environment, hosted in the GitHub repository. This repository integrates with TravisCI to publish index.html files when modified as AWS S3 buckets. There is an index.html and an S3 bucket dedicated to each Web application environment.
The underlying setup for this separate build and publish workflow is shown in the figure below:
The infrastructure that supports immutable Web applications consists of three parts:
- Web application server: A static Web server that hosts the Web application environment by providing index.html.
- Static asset server: A static Web server used to host an immutable static asset.
- API: One or more exposed endpoints to interact with the Web application backend.
Building a static asset is a complex process that usually involves:
- Depend on the resolution
- Download Library Files
- Uglifying, Code Splitting, Tree Shaking, * Autoprefixing…
These processes are time-consuming, heavily dependent on external dependencies, and often run in a seemingly indeterminate manner. They are not processes that should end with the immediate release of the generated assets to production without validation. Even the act of publishing multiple large, static assets is a process that can be disrupted and leave the Web application environment in a corrupted state.
Immutable Web applications are built once and published to a location once. This process occurs before live publishing. They can be validated in the staging environment and promoted to production without having to be regenerated with significantly reduced risk.
Atomic Live Releases – Atomic Live Releases
Real-time publishing of an immutable Web application is the act of publishing a single index.html file. Deployment is instantaneous, with all assets available for immediate use without any cache risk of being corrupted at release time.
Rollback is just as risky as deployment, and often more so. For immutable Web applications, the same quality of deployment applies to rollbacks. It is important to note that in the case of a rollback, most browsers will still cache the previous asset.
In the event that the browser tries to load an older version of index.html, all the assets from the previous version are still available and uncorrupted.
Simplified caching strategy
Managing cache control headers can be daunting, especially when the Web application infrastructure leverages the common cache used by a CDN. Two of the simplest concepts in caching are “always cache” and “never cache.” Immutable Web applications incorporate these concepts, completely separating code that can be “always cached” from configurations that are “never cached.”
Simplified routing strategy
Leading application frameworks do not separate the location of static assets from index.html in their deployment recommendations. Instead, they suggest adding routing rules to the Web server that return index.html for all paths that are not parsed into physical files.
The implementation of these routing rules may vary from Web server to Web server, and errors often cause the path to resolve to the wrong resource.
This risk is eliminated by separating the managed and static assets of index.html. The static asset server always provides a physical file represented by a URL, while the Web application server always provides index.html for any URL.
Immutable Web applications are often associated with the following concepts:
- Modern application frameworks: Angular, React, Vue, and Ember enable teams to build increasingly complex, single-page, static applications. Tools like Webpack improve the ability to create, optimize, and manage build artifacts.
- DevOps: The DevOps culture enables Web application developers to decompose and reevaluate their Web application infrastructure to better meet the needs of their Web applications.
- Mature application patterns and practices: Backend applications and services are converging around a set of best practices that support portability, extensibility, and high availability. This trend has dramatically increased the number of tools and services available, especially those related to containers and container choreography. Many of these practices are just beginning to be applied to static single-page Web applications.
More of Jerry’s original articles can be found on “Wang Zixi “: