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

This article explains how to achieve module scalability in web interactive systems by defining modules, encapsulating their style, structure, and logic, managing dependencies with Uniform Module Identifiers, flattening hierarchical relationships, and applying scheduling strategies for display, refresh, and messaging.

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

In the second article of the series "Building Highly Scalable Web Interactive Systems", we focus on the scalability of individual modules.

Module Scalability

A web interactive system should support:

Extensibility – quickly respond to new functional requirements.

Reducibility – remove or replace degraded modules with minimal changes.

What Is a Module?

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

Module Composition

Each module consists of three elements:

Style – defines the visual appearance.

Structure – defines the HTML markup.

Logic – implements the functional behavior.

Module Encapsulation

These elements can be packaged together, for example in an module.html file:

<!-- 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 avoid premature execution, 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>

Dependency Management

Modules often depend on one another. A simple single‑page application example is illustrated below:

The system includes components such as log management, blog settings, account management, etc., each represented as a module.

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

Uniform Module Identifier (UMI)

We introduce a Uniform Module Identifier (UMI) to decouple modules from their implementations. UMI follows URI‑like path rules, e.g., /m/m0/, starts with a slash, and private modules start with /?. The path encodes the parent‑child relationship.

Each UMI maps to a concrete module file, allowing independent addition, removal, or modification of modules without touching business logic.

Flattening Dependencies

By abstracting the hierarchical tree into a flat list of UMIs, the dependency graph becomes a simple tree where each node corresponds to a module file.

Module Composition

Modules can be categorized as container providers or container users; a module may serve both roles, enabling arbitrary composition.

Configuration example for composing modules:

'/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 – construct the module structure.

Show – render the module in its container.

Refresh – fetch and display data based on input.

Hide – release resources while keeping the module in memory.

The scheduler controls transitions between these states.

Module Display Process

When a user requests a module (e.g., /m/blog/list/), the system:

Loads implementation files registered along the path from root to target.

Ensures all ancestor modules are displayed before showing the target.

Attempts to display the target once its ancestors are ready.

Module Switch Process

Switching from one module to another follows four steps: find the common parent, hide modules from the source to the common node, refresh modules from the root to the common node, and finally show modules from the common node to the target.

Message Channels

Two communication patterns are recommended:

Point‑to‑point – a module sends a message to a specific UMI.

Publish/Subscribe – a module declares messages it can emit; others subscribe to them.

The article concludes by promising a concrete example using NetEase's NEJ framework in the final installment.

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.

frontenddependency managementmodule architecture
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.