How Alibaba’s Tianma Seed Spec Compares to Modern Import Maps
This article examines the evolution of web resource loading—from script tags and CDN combos to CommonJS, AMD, bundlers, and bundless approaches—then compares Alibaba's Tianma seed module specification with the emerging import‑maps standard, highlighting their setups, limitations, and performance implications.
Introduction
I am Bu Tian from the Taobao front‑end building service team, responsible for the Tianma building service and Zebra platform, which provide both generic building services and ready‑to‑use building products.
Key terms:
Building: enabling non‑technical users to create pages via drag‑and‑drop or configuration.
Module: the smallest unit of a building operation.
Tianma: an internal building platform that offers services to multiple Alibaba business units, helping them quickly construct a building system.
Common Web Resource Loading Issues
Although modern browsers are fast, page load performance remains a major problem because browsers must download remote files. The community has gone through several stages:
From plain
<script>ordering to CDN combo.
From no module system to CommonJS, enabling synchronous module loading.
From no module spec to AMD, allowing asynchronous dependency declaration.
From async loading limitations to bundlers such as Dojo and Webpack.
With the rise of ES Modules and import‑maps, bundless solutions emerged to improve build efficiency and runtime standards.
Tianma Seed Specification vs Import Maps
The Tianma seed spec originates from KISSY, adopts the AMD idea, and finally uses the CMD format because its output generation logic is simpler. Unlike most low‑code platforms, Tianma’s approach:
Provides modular development while hiding underlying build logic; shared dependencies are deduplicated automatically.
Publishes pages without a build step; rendering occurs on the client, supporting massive simultaneous page edits.
Allows independent page releases, with module version updates affecting only the relevant pages.
After five years, the seed spec faces several challenges, which we compare with the import‑maps standard.
Seed Usage
1. Include the
feloaderloader, which registers global
requireand
definemethods.
2. Configure dependency relationships.
3. Load modules defined in the seed file.
<code><script src="feloader.js"></script>
<script>
require.config({
"packages": {
"example-1": { "path": "/example-1/" }
}
});
require(["example-1/index"], function (Example) {
// do something.
});
</script></code>Import‑Maps Usage
1. Declare an import‑map configuration.
2. Use the browser’s native
importto load the configured modules.
Note: Only one import‑map can be loaded per page, and it must be fetched before any module script runs.
<code><script type="importmap">
{
"imports": { ... },
"scopes": { ... }
}
</script>
<script type="importmap" src="import-map.importmap"></script>
<script>
const im = document.createElement('script');
im.type = 'importmap';
im.textContent = JSON.stringify({
imports: {
'my-library': Math.random() > 0.5 ? '/my-awesome-library.mjs' : '/my-rad-library.mjs'
}
});
document.currentScript.after(im);
</script>
<script type="module">
import 'my-library'; // will fetch the randomly‑chosen URL
</script></code>Setup Comparison
Seed is flexible: modules can be reconfigured at any script execution stage, and after loading a module its state can be reset and reloaded. Import‑maps are stricter: the JSON file must be loaded with
type="importmap", the MIME type must be
application/importmap+json, and the loading is blocking. Only one import‑map per page is allowed; adding another later results in an error.
Because of these constraints, developers cannot manage each external library’s dependencies as they do in Node.js. Instead, the whole page’s dependencies must be declared centrally, which can be cumbersome for developers who prefer “plug‑and‑play” libraries.
Dependency Management and Versioning
Both approaches require developers to know which external libraries a page uses and to upgrade them responsibly. npm‑style versioning works well for server‑side bundles but is less suitable for web pages that fetch modules on each visit, leading to version uncertainty. The author suggests that Airpack could be a good solution, though it may introduce more complexity than npm.
Performance‑wise, inline import‑maps are recommended. If external import‑maps are used, HTTP/2 Push or Web Bundle can mitigate the blocking nature. Similarly, inline CSS is preferred for the same reason.
Package Support
Seed reduces configuration size by using
packagesand
modules.
packagesdeclare module directories, while
modulesdefine inter‑module dependencies. Example:
<code>{
"modules": {
"example-1/index": {
"requires": ["example-1/utils"]
}
},
"packages": {
"example-1": { "path": "/example-1/" }
}
}</code>Import‑maps also support a
packages-like concept using trailing slashes.
<code><script type="importmap">
{
"imports": {
"moment": "/node_modules/moment/src/moment.js",
"moment/": "/node_modules/moment/src/",
"lodash": "/node_modules/lodash-es/lodash.js",
"lodash/": "/node_modules/lodash-es/"
}
}
</script>
<script type="module">
import moment from 'moment';
import _ from 'lodash';
import localeData from 'moment/locale/zh-cn.js';
import fp from 'lodash/fp.js';
</script></code>Scope and Major‑Version Incompatibility
Import‑maps allow scoped configurations so that different files can load different versions of the same library. Seed currently lacks scope support; to handle major version incompatibility, the team prefixes the version to the module name (e.g.,
example-1@1and
example-1@2).
<code>{
"packages": {
"example-1@1": { "version": "1.0.1", "path": "/example-1/1.0.1/" },
"example-1@2": { "version": "2.0.2", "path": "/example-1/2.0.2/" }
}
}</code>Dependency Download Mechanism
Under the seed mechanism, a module can declare dependencies similar to npm’s
dependencies. When a module loads, all its dependencies (and transitive dependencies) are fetched concurrently, ensuring the module can execute.
<code>{
"modules": {
"example-1/index": {
"requires": ["example-1/utils", "example-1/tools"]
}
}
}</code>Seed also supports CDN combo, merging multiple dependency requests into a single script, which can be faster than many parallel requests. Import‑maps currently lack a similar combo mechanism, leading to potentially serial downloads.
SystemJS Depcache (Experimental)
SystemJS can use a
depcacheto declare dependencies ahead of time, enabling parallel loading if the loader supports it.
<code><script type="systemjs-importmap">
{
"imports": { "dep": "/path/to/dep.js" },
"depcache": {
"/path/to/dep.js": ["./dep2.js"],
"/path/to/dep2.js": ["./dep3.js"],
"/path/to/dep3.js": ["./dep4.js"],
"/path/to/dep4.js": ["./dep5.js"]
}
}
</script>
<script>
setTimeout(() => { System.import('dep'); }, 10000);
</script></code>Future of Seed
Efforts to make seed more bundle‑like—such as merging multiple pages—face challenges like release speed and first‑paint resource calculation. Import‑maps provide a different perspective that keeps modularity viable on the web.
Looking ahead, the team plans to upgrade the CMD spec to ES Modules, devise downgrade paths for CommonJS, and develop a more standardized loading approach that combines CDN combo, async concurrent downloads, native caches, PWA techniques, server push, and experimental predictive loading. This will continue to evolve within the internal
feloaderand may integrate further with SystemJS.
References
github/import-maps
W3C import‑maps draft
SystemJS support for import‑maps
Import‑maps CSP requirements
Import‑maps depcache proposal
KISSY config
YUI Loader
Taobao Frontend Technology
The frontend landscape is constantly evolving, with rapid innovations across familiar languages. Like us, your understanding of the frontend is continually refreshed. Join us on Taobao, a vibrant, all‑encompassing platform, to uncover limitless potential.
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.