How to Build Scalable Web Modules: Architecture, Encapsulation, and Dependency Management

This article explains how to design scalable web modules by defining their composition, encapsulating HTML/CSS/JS, managing dependencies with uniform identifiers, flattening hierarchical relationships, and applying scheduling strategies for module display, switching, and messaging in single‑page applications.

ITFLY8 Architecture Home
ITFLY8 Architecture Home
ITFLY8 Architecture Home
How to Build Scalable Web Modules: Architecture, Encapsulation, and Dependency Management

Module Scalability

Web interactive systems require modules to be both extensible—quickly supporting new features—and reducible—allowing removal with minimal changes.

Module

A module is an independent unit split from the system that interacts with users to complete a specific function.

Module Composition

Each module consists of three elements:

Style: defines the visual appearance.

Structure: defines the HTML layout.

Logic: implements the functional behavior.

Module Encapsulation

Modules can be packaged as separate HTML files (e.g., module.html) or using script files with injected style and structure. An example of HTML encapsulation:

<!-- Module style --><style>
    .m-mdl-1 .a{color:#aaa;}
    .m-mdl-1 .b{color:#bbb;}
</style>
<!-- Module structure -->
<div class="m-mdl-1">
    <p class="a">aaaaaaaaaaaaaaaaaaa</p>
    <p class="b">bbbbbbbbbbbbbbbbbbb</p>
</div>
<!-- Module logic -->
<script>
    (function(){
        var a = 'aaa';
        var b = 'bbb';
        // ...
    })();
</script>

To prevent immediate execution when pre‑loaded, the module’s elements can be stored as text, for example using <textarea> tags:

<!-- Module style -->
<textarea name="css">
    .m-mdl-1 .a{color:#aaa;}
    .m-mdl-1 .b{color:#bbb;}
    /* ... */
</textarea>
<!-- Module structure -->
<textarea name="html">
    <div class="m-mdl-1">
        <p class="a">aaaaaaaaaaaaaaaaaaa</p>
        <p class="b">bbbbbbbbbbbbbbbbbbb</p>
    </div>
</textarea>
<!-- Module logic -->
<textarea name="js">
    (function(){
        var a = 'aaa';
        var b = 'bbb';
        // ...
    })();
</textarea>

Manage Dependencies

Modules often depend on each other; a module may need another to render first. The article illustrates a single‑page application with components such as log management, blog settings, account management, etc., and shows the hierarchical relationships.

Traditional hierarchical patterns like PAC and HMVC suffer from strong coupling, deep event propagation, and costly changes when modules are added or removed.

Module Identifier (UMI)

The Uniform Module Identifier (UMI) uniquely identifies a module and its dependency path, following URI‑like syntax (e.g., /m/m0/). Private modules start with /?. The UMI maps directly to the module’s implementation file.

Module Dependency

By flattening the hierarchical module tree into a dependency‑relationship tree, each module becomes independent. The tree’s paths correspond to UMIs, enabling a one‑to‑one mapping between UMIs and module files.

Module Composition

Modules can be categorized as container providers or container users. A module may serve both roles, allowing arbitrary composition.

Example configuration for module composition:

'/m/blog/list/':{
    module:'module/layout/blog.list/index.html',
    composite:{
        box:'/?/blog/box/',
        tag:'/?/blog/tag/',
        list:'/?/blog/list/',
        clazz:'/?/blog/class/'
    }
}

Scheduling Strategy

After flattening, modules are assigned to developers, built, and then integrated according to the dependency tree. Modules transition through four states: build, display, refresh, and hide. The scheduler controls these transitions.

Module Display

When a user requests a module (e.g., /m/blog/list/), the system checks the path, loads the implementation if registered, ensures all ancestors are displayed, and then renders the target module.

Module Switch

Switching from one module to another involves locating the common ancestor, hiding modules from the source up to the ancestor, refreshing modules from the root to the ancestor, and finally displaying modules from the ancestor to the target.

Message Channel

Two communication methods are recommended:

Point‑to‑point messages: sender specifies the target module’s UMI.

Publish‑subscribe messages: modules declare published messages and others subscribe to them.

The article concludes with a preview of applying these principles to the NEJ framework.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Frontend ArchitectureSingle Page Applicationmodule encapsulationmodule scalability
ITFLY8 Architecture Home
Written by

ITFLY8 Architecture Home

ITFLY8 Architecture Home - focused on architecture knowledge sharing and exchange, covering project management and product design. Includes large-scale distributed website architecture (high performance, high availability, caching, message queues...), design patterns, architecture patterns, big data, project management (SCRUM, PMP, Prince2), product design, and more.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.