From spm to Ant Tool: Evolution of Alibaba’s Front‑End Build System
This article traces the history of Alipay’s front‑end build ecosystem—from the early spm package manager through the all‑in‑one spm3 era, the rise of ant tool, and the shift toward modular presets—highlighting the challenges of centralisation, configuration complexity, and future directions.
If you're not interested in the history of spm, you can start reading from the ant tool section.
Below I discuss my understanding of the evolution of Alipay's front‑end build tools, from spm to ant tool and the possible future direction.
spm1 & spm2
Around 2012, front‑end modularisation was booming, and module loaders like seajs emerged. spm was initially a packaging tool for seajs, and because npm did not accept browser packages at the time, a dedicated spm source server was created to host modules.
spm then became a front‑end component package manager, similar to npm for node modules, managing the lifecycle of various modules. It did not include build functionality itself; instead, extensions such as gulp or spm‑build handled the build step.
spm focused on the CMD module ecosystem, but soon npm began accepting browser packages and the CommonJS standard gained traction, causing spm to lose ground and leading to the creation of spm3.
spm3
spm3 was an all‑in‑one solution covering the full browser module lifecycle—initialisation, local debugging, documentation, publishing, unit testing, building, and source services—solving many build issues of earlier seajs projects.
The most significant shift was the migration from CMD to CommonJS, signalling the gradual retirement of CMD.
During this period, spm and seajs still had an unclear relationship, and the coexistence of spm2 and spm3 caused confusion, prompting tool convergence.
spm3.4 – spm3.6
This series merged sea.js functionality into
spm‑sea, allowing the build tool to fully embrace community solutions. However, the all‑in‑one configuration introduced maintenance challenges: configuration conflicts, scalability issues, and long build times that grew from seconds to minutes.
Around early 2015, webpack entered the scene. Although powerful, its steep learning curve and functional configuration deterred many developers.
Consequently, multiple spm variants (spm2, spm3, spm3.4, spm3.6, spm‑sea) coexisted.
spm3.6.x and beyond
With webpack’s popularity, spm3.6.x switched its core build engine to webpack while still offering a configurable interface. The integration with the react ecosystem highlighted conflicts between the closed spmjs.io ecosystem and the open npm world, leading to frequent source‑server failures.
Eventually, spm’s source server was migrated to npm, requiring a massive effort to publish over 2,000 modules and tens of thousands of versions.
Maintaining a front‑end ecosystem is difficult, especially when balancing build, debugging, and source services with community expectations.
The growing complexity of spm’s configuration made further additions risky, and the explosion of H5 projects amplified developers’ demand for customisation.
Two opposing philosophies emerged:
Centralisation: an all‑in‑one approach that covers the entire workflow (initialisation, development, build, debugging, release, testing, proxy, documentation, etc.). It offers a unified experience but becomes bulky, hard to maintain, and limits customisation.
Decentralisation: modular tool development where only needed functionalities are loaded. It provides flexibility at the cost of higher integration effort, often mitigated by scaffolding.
ant tool
ant tool is a codename for a suite of specialised modules that together provide build, debugging, testing, documentation, and offline package solutions.
atool‑build: a wrapper around webpack that generates default configuration and invokes webpack.
dora: a development server that aggregates debugging solutions (webpack, livereload, browsersync, mock data, local proxy, weinre, jsonapi, etc.).
atool‑test: front‑end testing integration.
atool‑doc: front‑end documentation solution.
moggles: offline package solution for mobile.
We define a front‑end development tool as a transformer that converts standardized input into standardized output.
The solution is to provide “business‑type scaffolds” that abstract away complex configurations, making tools lighter and more community‑oriented.
However, scaffolds also bring problems:
Developers may not upgrade scaffolds, causing them to fall behind tool evolution.
Scaffold content changes with business needs, but once initialised it becomes static, making it hard to adopt new benefits or adjust code organisation.
Business‑maintained scaffolds change frequently, leaving users uncertain about which version to use.
Flexible webpack.config.js and configuration disaster
atool‑build introduces a
webpack.config.jsto let users override default settings. While reasonable, this flexibility creates upgrade pain: customisations may clash with upstream changes, breaking builds when internal defaults change (e.g., SVG loader adjustments).
The lesson: highly flexible
webpack.config.jsmakes the build core hard to upgrade, yet custom needs persist.
create‑react‑app
Facebook’s create‑react‑app provides a zero‑config React setup. To modify its internal webpack config, developers must “eject”, which exposes the full configuration but removes the benefits of the tool.
roadhog
roadhog builds on CRA to offer configurable internal loaders and plugins, targeting dva applications. It illustrates the tension between wanting an elegant default experience and needing custom configuration.
Future direction
Key proposals:
Stop extending business‑specific scaffolds on top of generic build configs; this hinders upgrades and locks businesses to specific versions.
Eliminate
webpack.config.jswherever possible.
Adopt semantic configuration: users only need to specify high‑level intent, while the system resolves concrete build details.
How can we achieve these three points?
Inspired by the evolution of the
m‑initmobile scaffold and Babel presets, I propose a “build factor” architecture.
Build factor: a minimal, reusable solution for a specific build scenario, implemented as an extension with hooks (pre, post, main, service).
Preset: a business‑level package (published to npm) that composes selected build factors. Developers adjust preset behaviour via a semantic rc file; if a preset does not fit, a new preset is created.
This approach enables painless upgrades (preset version bump) and abstracts away low‑level configuration from developers.
Re‑examining centralisation vs decentralisation
Centralised tools become large (e.g., spm >400 MB) and hard to maintain; they also suffer from configuration overload (20+ options) that confuses users. Decentralised “build factors” are discrete, replaceable units, while presets provide a higher‑level, stable description of required build behaviour.
Why presets should be npm packages
Presets, maintained by business owners, can be versioned and distributed via npm, allowing all downstream developers to upgrade with a single dependency bump, eliminating manual coordination.
In this model, atool‑build becomes a stable shell that dispatches presets, performs performance analysis, and prompts preset upgrades.
@IM Web Front‑End Community – author pigcan – https://github.com/pigcan/blog/issues/4
Tencent IMWeb Frontend Team
IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.
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.