Evolution of Front‑End Build Technologies and the Idea of Service‑Based Build
The article reviews the historical progression of front‑end build techniques from simple script loading and file concatenation to dependency‑based bundlers like webpack and vite, and proposes a future service‑oriented build model to overcome scalability limits.
Initially front‑end code had no build concept; JavaScript files were directly loaded via <script> tags. As modular loaders such as SeaJS and RequireJS appeared, the first build technique emerged: file concatenation, often combined with tools like Gulp to handle images, styles, compression, and Babel transpilation.
File Concatenation
File concatenation simply stitches multiple JavaScript files together while using a module loader to isolate execution contexts. Although easy to implement, this approach cannot satisfy the performance demands of large SPA applications because concatenation and module loading are unrelated, preventing optimizations such as tree‑shaking, code splitting, and shared‑dependency extraction.
Dependency‑Based Build
Webpack advanced build technology by analyzing module‑level dependencies rather than whole files, supporting various module syntaxes and enabling ES6‑module tree‑shaking (as introduced by Rollup). It abstracts files into chunks, merges or splits them via optimization algorithms, and offers Module Federation (MF) to split large monorepos into independently built parts.
Vite further accelerates development by leveraging native browser module loading, though production still requires bundling for compatibility.
Despite these advances, the growing number of files raises concerns about browser loading limits, prompting developers to consider separating build performance between runtime and development phases.
Service‑Based Build
Inspired by micro‑services, the author envisions a build model where front‑end code is packaged as services rather than static module dependencies. In this model, modules communicate via a protocol‑like interface, making the loading order irrelevant to the caller.
Example of traditional dependency loading:
import hello from 'hello'
import hello1 from 'hello1'
import hello2 from 'hello2'
import hello3 from 'hello3'
import hello4 from 'hello4'
import hello5 from 'hello5'
import hello6 from 'hello6'
import hello7 from 'hello7'
hello()
hello1()
hello2()
hello3()
hello4()
hello5()
hello6()
hello7()Turning a module into an asynchronous load:
import('hello').then(module => {
module.default()
})In a service‑oriented approach the call becomes independent of loading: mpc('hello').hello() When the service method is asynchronous, the caller can still use a synchronous‑looking call: await mpc('hello').hello() Service‑based builds still need to resolve module loading internally, but the external API no longer relies on import(). Instead, services can be pre‑loaded (e.g., via CDN) and invoked through a message queue.
const helloProxy = mpc('hello') // construct a hello service proxy
helloProxy.hello() // push a call message to the service queueBecause services can be loaded ahead of time, large applications could parallel‑load many service bundles over HTTP/2 and achieve “asynchronous services with synchronous calls,” eliminating the manual maintenance of import timing.
In summary, the next generation of front‑end build technology may shift from dependency‑centric bundling to a service‑centric paradigm that encapsulates modules as services, enabling unlimited scalability and transparent, parallel loading.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
