Web Components, Boundary Control Entity (BCE) and Unidirectional Data Flow with redux 📎
class JavaDev extends HTMLElement {
connectedCallback() {
const message = "Web Components"
this.innerHTML = `Hello, ${message}`;
}
}
customElements.define('java-dev',JavaDev);
However, the "vanilla" Web Component approach would require a complete re-rendering of the entire element and will result in slower performance in more sophisticated applications. Because we are setting a raw string, which can also contain user input and data fetched from a server, the above approach also comes with a security risk. Thankfully, JavaScript provides a way to declare functions "tagged templates" (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates), which process the raw String and can realize a faster or more secure rendering.
A tagged template function receives the entire String with all "bindings," which allows the implementation of additional syntactic sugar. lit-html is an example of such implementation, which optimizes the rendering, escapes JavaScript code, and adds convenient event handlers' attachment:
const template = html`
<button @click="${_ => this.newBookmark()}">new bookmark</button>
`;
Vanilla Web Components combined with plain lit-html templating "function" already feel like a lean and productive JavaScript framework.
With lit-html, you are already good to go for smaller web applications. Applications with many interacting components will require a state management solution. Without a central "mediator" (https://en.wikipedia.org/wiki/Mediator_pattern), the individual Custom Elements will have to communicate with each other directly.
Redux (https://redux.js.org) is a lean (single file) implementation of the "mediator" pattern. It is a central singleton that manages the entire state of the application and notifies all listeners about the changes. The Redux library's use may lead to a significant boilerplate, but it integrates well with lit-html and Web Components. Web Components combined with lit-html, redux, and a few conventions are productive and scale for more complex, interactive applications.
The "Boundary Control Entity" is one of the oldest architectural patterns (https://en.wikipedia.org/wiki/Entity-control-boundary), is similar to MVC, and even provides icons available in all popular design and sketching tools. Equipped with BCE, you don't have to argue about the naming conventions, can conveniently ignore the "Parkinson's law of triviality" (https://en.wikipedia.org/wiki/Law_of_triviality), and focus on the semantics instead.
A complex application is divided into functional, feature-driven folders named after essential concepts. Each such folder comprises at most the following directories:- Boundary: contains the views implemented with Custom Elements ("Web Components"). The custom elements react to user input and forward the extracted, relevant data to the "controls." All views are listening to redux store changes and are re-rendered at any state mutation.
- Control: are the glue between the visual views and the redux "store." A control package contains functions that implement business logic and backend communication. Controls are asynchronous, "fire-and-forget" functions that process the user input, call external services, and dispatch the data as "redux actions" to the store.
- Entity: the entity folder contains reducers that mutate the state. Any state change leads to notification of all listeners. Maintaining object lists, filtering, or changing the state are the typical responsibilities of functions residing in the "entity" package.
Combining vanilla Web Components with lit-html and redux comes with the following advantage:
- You can start with Web Components without learning any additional framework. Web Components are built-in into the browser, they are well documented, stable, and not expected to change. Migrations or upgrades are not necessary--you only have to learn them once and never migrate.
- lit-html and redux are small utilities with several alternatives available.
- BCE comes with a clear and consistent structure, which scales for large frontends.
- The combination of Web Components, lit-html, and redux toolkit leads to code similar to React without any framework involved.
- The necessary tooling is minimal. No transpilations, build tools, or bundling is required. Only a simple web server with hot-reload functionality like, e.g., https://browsersync.io, is recommended.
Check the following quickstarter, just "git clone
&& go." https://github.com/adambien/bce.design
See the BCE quickstarter in action: