深入拆解 webpack Harmony(ES Module)打包机制:从 examples/harmony 看 import/export 编译与 import() 代码分割
本篇文章以当前仓库中 examples/harmony 示例 为核心线索,逐行分析一个仅由原生 ES Module(webpack 语境下的 Harmony 模块)组成的微型应用,是如何被 webpack 编译成可运行的 bundle 的。你将看到 import/export 被翻译成模块包装函数与 __webpack_require__ 调用的全过程,import() 动态导入如何自动触发代码分割并生成异步 chunk,以及 __webpack_require__.e/.u/.l/.f.j 与 JSONP 回调构成的按需加载运行时。读完本文,你能从产物层面真正读懂 ES Module 在 webpack 中的编译形态,为理解 tree shaking、模块联邦、懒加载等进阶能力打下基础。
示例全景:一个只有 ES Module 的最小应用
examples/harmony 是 webpack 官方 examples 目录中演示 Harmony 模块(即 ES2015+ 模块) 的基准示例。在 webpack 的历史命名中,harmony 正是 ECMAScript 模块(ESM / ES Module)的代称——webpack 的 harmony 相关解析插件、依赖类与产物注释(如 /* harmony export */)都沿用了这一叫法。相关示例被集中收录在 examples/README.md 的 "Harmony" 分组下。
整个示例只包含 4 个源文件,形成一条清晰的依赖链:
| 文件 | 模块角色 | 说明 |
|---|---|---|
| example.js | 入口模块 | 命名导入(带别名)、同步调用、import() 动态加载 |
| increment.js | 中间模块 | export function 导出,并从 math.js 导入 add |
| math.js | 叶子模块 | export function add,接受任意数量参数求和 |
| async-loaded.js | 异步模块 | 仅 export var answer = 42,会被切分为独立 chunk |
入口模块 example.js
example.js 展示了 ES Module 的两种典型消费方式:
import { increment as inc } from './increment';
var a = 1;
inc(a); // 2
// async loading
import("./async-loaded").then(function(asyncLoaded) {
console.log(asyncLoaded);
});
import { increment as inc }是带别名的命名导入,编译产物中会保留“引用原绑定”的语义(见后文产物中的increment处理);inc(a)是对 Harmony 模块导出函数的同步调用,在产物中会被改写为(0,_increment__WEBPACK_IMPORTED_MODULE_0__.increment)(a),这样调用时this不会被意外指向模块命名空间;import("./async-loaded")是动态导入表达式,webpack 会把它识别为一个新的依赖块,自动切分出独立的异步 chunk,而不是把代码塞进主 bundle。
中间模块 increment.js
increment.js 体现了 ES Module 的“再导入 + 再导出”组合:
import { add } from './math';
export function increment(val) {
return add(val, 1);
};
increment 本身导出一个命名函数,函数体内调用的 add 来自对 math.js 的命名导入。这类“导入后调用其他模块导出”的模式是 webpack 产物中最常见的编译对象。
叶子模块 math.js
math.js 是依赖链的末端:
export function add() {
var sum = 0, i = 0, args = arguments, l = args.length;
while (i < l) {
sum += args[i++];
}
return sum;
}
注意 add 故意写成变参求和的传统函数,而不是固定两个参数,目的是让示例在 inc 任意取值时都能正确返回 val + 1(例如 add(1, 1) === 2)。
被切分出去的异步模块 async-loaded.js
async-loaded.js 只有一行导出:
export var answer = 42;
正因为它只被 import() 引用,webpack 会把它编排进一个按需加载的 chunk(本示例中即 655.output.js),而不是打进主 output.js。
产物体检:bundle 的整体骨架
在示例目录下以 example.js 为入口执行构建后,产物落在 dist/,本文引用的 examples/harmony/README.md 展示了完整的 dist/output.js。整个 bundle 由三个逻辑层构成:
- 模块表
__webpack_modules__:一个以 module id 为下标的数组,每个元素是一个“模块包装函数”; - webpack 运行时(runtime):负责模块缓存、
require、命名空间标记、属性 getter、chunk 加载等基础设施的 IIFE; - 入口执行代码:被包裹在独立 IIFE 中的入口模块逻辑。
外层再用一个 (() => { ... })() 自执行函数整体包裹,形成"webpackBootstrap"结构:
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ([
/* 0 */,
/* 1 */ ...
/* 2 */ ...
/******/ ]);
模块表:每个 ES Module 都变成“包装函数”
模块表把每个模块编译成一个 (module, module.exports, __webpack_require__) => { ... } 形式的函数,数组下标即 module id。id 0 是占位(留给入口),id 1 是 increment.js,id 2 是 math.js,async-loaded.js 则随异步 chunk 携带(本示例中为 id 3)。
以 increment.js 为例,其编译形态如下:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ increment: () => (/* binding */ increment)
/* harmony export */ });
/* harmony import */ var _math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./math */ 2);
function increment(val) {
return (0,_math__WEBPACK_IMPORTED_MODULE_0__.add)(val, 1);
};
这里可以提炼出 Harmony 模块编译的三条核心规则:
__webpack_require__.r标记命名空间:把当前模块的exports标记为 ES Module(打上Symbol.toStringTag与__esModule);__webpack_require__.d定义导出 getter:ES Module 的导出是只读绑定,因此不能用简单赋值,而是通过Object.defineProperty定义 getter(/* binding */ increment说明该 getter 直接绑定到函数声明);import被降级为__webpack_require__调用:import { add } from './math'变成var _math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./math */ 2),(0, ...)前缀确保以 undefined 的this调用被导入函数。
math.js 的编译形态与之一致:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ add: () => (/* binding */ add)
/* harmony export */ });
function add() {
var sum = 0, i = 0, args = arguments, l = args.length;
while (i < l) {
sum += args[i++];
}
return sum;
}
模块顶部的“导出信息注释”
每个模块包装函数上方都有一段 webpack 生成的注释,例如:
/*! namespace exports */
/*! export add [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__.r, __webpack_exports__, __webpack_require__.d, __webpack_require__.* */
这些注释并非装饰,而是模块导出信息(ExportsInfo)分析结果的直接投影,其中:
namespace exports:该模块按 ES Module 命名空间方式导出;export add [provided]:表示add这个导出被“提供”且可被静态识别,[no usage info]/[used exports unknown]表示当前还没有跨模块的使用信息回传;runtime requirements: ...:精确列出该模块运行期依赖的__webpack_require__帮助函数,webpack 据此做“按需注入运行时片段”。
“provided / not provided / used exports unknown”这类状态词汇对应 webpack 的 ExportsInfo 数据结构(维护于 lib/ExportsInfo.js)与导出使用分析(FlagDependencyExportsPlugin、FlagDependencyUsagePlugin 等),它同时也是 tree shaking 与 stats 输出中 [exports: answer]、[no exports used] 等信息的来源。这正是 Harmony 模块相比 CommonJS 最大的优势:静态语法让 webpack 能精确知道每个模块导出了什么、被用到了什么,从而为死代码消除(sideEffects 与 tree shaking)铺路。
webpack 运行时(Runtime)逐段解析
在 bundle 里,模块表之后是运行时代码。为了让 bundle 既能同步 require 又能按需加载异步 chunk,运行时提供了成套的 __webpack_require__ 帮助函数。原文 README 用 <details> 折叠块完整保留了这约 200 行运行时,下面分层拆解其职责。
模块缓存与 require 函数
// The module cache
const __webpack_module_cache__ = {};
// The require function
function __webpack_require__(moduleId) {
// Check if module is in cache
const cachedModule = __webpack_module_cache__[moduleId];
if (cachedModule !== undefined) {
return cachedModule.exports;
}
// Create a new module (and put it into the cache)
const module = __webpack_module_cache__[moduleId] = {
// no module.id needed
// no module.loaded needed
exports: {}
};
// Execute the module function
__webpack_modules__moduleId;
// Return the exports of the module
return module.exports;
}
这是最核心的 CommonJS 运行时抽象:首次 require 时创建模块对象并执行包装函数,之后命中 __webpack_module_cache__ 直接返回同一份 exports,从而保证多模块共享单例、避免重复执行副作用。__webpack_require__.m = __webpack_modules__ 则把模块表暴露出来,供 JSONP 回调向表中追加新 chunk 的模块。
定义 harmony 导出 getter:__webpack_require__.d
// define getter/value functions for harmony exports
__webpack_require__.d = (exports, definition) => {
for(var key in definition) {
if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
}
}
};
它遍历定义对象,用 Object.defineProperty 把每个导出定义成可枚举的 getter 而非值。这意味着当模块内被导出的变量后续发生变化时,外部读取到的始终是最新绑定,忠实还原了 ES Module “导出是活的绑定(live binding)”的语义;这也是为什么导出的函数/变量都以 () => (/* binding */ x) 闭包形式给出。
标记模块为 ES Module:__webpack_require__.r
// define __esModule on exports
__webpack_require__.r = (exports) => {
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
Object.defineProperty(exports, '__esModule', { value: true });
};
__webpack_require__.r 同时打上 Symbol.toStringTag = 'Module'(使 Object.prototype.toString.call 返回 [object Module])与 __esModule = true(供 Babel/TS 等编译产物的 _interopRequireDefault 判断“是否是 ES Module”)。webpack 自身的互操作运行时 __webpack_require__.n 也以 __esModule 为依据决定 default 的取法,详见 harmony-interop 示例。
辅助短函数:__webpack_require__.o
__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop));
hasOwnProperty 的简写,用于 __webpack_require__.d 中避免覆盖已有导出,也用于 chunk 状态查询。
异步 chunk 加载链路(code splitting 的运行时支柱)
示例代码里的 import("./async-loaded") 在运行时并不存在原生 import,它被编译成下面这样:
__webpack_require__.e(/*! import() */ 655).then(() => (__webpack_require__(/*! ./async-loaded */ 3))).then(function(asyncLoaded) {
console.log(asyncLoaded);
});
即两步走:先 __webpack_require__.e(chunkId) 把 chunk 加载并执行好,再 __webpack_require__(moduleId) 取出模块。整个链路由以下几段运行时组成:
1. ensure chunk 调度器 __webpack_require__.e
__webpack_require__.f = {};
// This file contains only the entry chunk.
// The chunk loading function for additional chunks
__webpack_require__.e = (chunkId) => {
return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {
__webpack_require__.fkey;
return promises;
}, []));
};
__webpack_require__.f 是“chunk 加载方案注册表”(如 f.j 代表 JavaScript JSONP 方案),e 会聚合所有方案的 promise,因此同一套骨架也能扩展支持 css、importmaps 等其它 chunk 类型。
2. 异步 chunk 文件名 __webpack_require__.u
// This function allow to reference async chunks
__webpack_require__.u = (chunkId) => (chunkId + ".output.js");
因为 output.filename 是 [id].output.js,这里直接拼接出 655.output.js;若配置了 chunkFilename: "[name].bundle.js" 或带 contenthash 的文件名,此函数会相应生成不同的拼接逻辑。
3. script 标签加载 __webpack_require__.l
__webpack_require__.l = (url, done, key, chunkId) => {
...
let script, needAttach;
if(key !== undefined) {
const scripts = document.getElementsByTagName("script");
for(var i = 0; i < scripts.length; i++) {
const s = scripts[i];
if(s.getAttribute("src") == url) { script = s; break; }
}
}
if(!script) {
needAttach = true;
script = document.createElement('script');
script.charset = 'utf-8';
if (__webpack_require__.nc) {
script.setAttribute("nonce", __webpack_require__.nc);
}
script.src = url;
}
inProgress[url] = [done];
...
const timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000);
script.onerror = onScriptComplete.bind(null, script.onerror);
script.onload = onScriptComplete.bind(null, script.onload);
needAttach && document.head.appendChild(script);
};
它负责在浏览器环境用 <script> 标签拉取 chunk 文件,管理 inProgress 去重、timeout 超时、nonce(CSP 支持)以及 onload/onerror 回调。
4. JSONP chunk 加载实现 __webpack_require__.f.j
const installedChunks = {
792: 0
};
__webpack_require__.f.j = (chunkId, promises) => {
// JSONP chunk loading for javascript
let installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;
if(installedChunkData !== 0) { // 0 means "already installed".
// a Promise means "currently loading".
if(installedChunkData) {
promises.push(installedChunkData[2]);
} else {
if(true) { // all chunks have JS
// setup Promise in chunk cache
const promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject]));
promises.push(installedChunkData[2] = promise);
// create error before stack unwound to get useful stacktrace later
const error = new Error();
...
__webpack_require__.l(__webpack_require__.p + __webpack_require__.u(chunkId), loadingEnded, "chunk-" + chunkId, chunkId);
}
}
}
};
installedChunks 是 chunk 状态表:0 表示已加载完成、[resolve, reject, Promise] 表示加载中、undefined 表示尚未加载。并发触发同一 chunk 的多次 import() 时会复用同一个 Promise。加载失败时则构造带 errorType、request、event 细节的 ChunkLoadError 供上层捕获。
5. publicPath __webpack_require__.p
__webpack_require__.p = "dist/";
因为输出目录是 dist,异步脚本的完整 URL 由 __webpack_require__.p + __webpack_require__.u(chunkId) 拼出,即 dist/655.output.js。
6. JSONP 回调与 self["webpackChunk"] 全局数组
const webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
let [chunkIds, moreModules, runtime] = data;
// add "moreModules" to the modules object,
// then flag all "chunkIds" as loaded and fire callback
var moduleId, chunkId, i = 0;
if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
for(moduleId in moreModules) {
if(__webpack_require__.o(moreModules, moduleId)) {
__webpack_require__.m[moduleId] = moreModules[moduleId];
}
}
if(runtime) var result = runtime(__webpack_require__);
}
if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
for(;i < chunkIds.length; i++) {
chunkId = chunkIds[i];
if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
installedChunks[chunkId][0]();
}
installedChunks[chunkId] = 0;
}
};
const chunkLoadingGlobal = self["webpackChunk"] = self["webpackChunk"] || [];
chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
异步 chunk 文件内容其实只是一段对全局数组 self["webpackChunk"] 的 push 调用。回调把新 chunk 的 moreModules 灌进 __webpack_require__.m 模块表(此时 async-loaded.js 的模块函数才被登记),再把对应 installedChunks 标记为已加载并 resolve 等待中的 promise,随后入口代码里的 .then(() => __webpack_require__(3)) 即可取回模块。self 而非 window 也意味着这套运行时同样适用于 Web Worker 等非窗口环境。
为什么 module id 3 是 async-loaded.js
回看产物注释 __webpack_require__(/*! ./async-loaded */ 3),异步模块的 module id 在编译期就已分配(id 3),只是它的模块函数直到 chunk 加载完成、JSONP 回调把 moreModules 写入模块表后才可用。这正是“先加载代码、再执行 require”的运行时协作模型。
入口执行代码的最终形态
模块表与运行时之后,是入口模块的引导代码,它被包在独立 IIFE 中以保证与 chunk 中其它模块隔离:
let __webpack_exports__ = {};
// This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk.
(() => {
/*!********************!*\
!*** ./example.js ***!
\********************/
/*! namespace exports */
/*! exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_require__.r, __webpack_exports__, __webpack_require__.e, __webpack_require__.* */
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _increment__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./increment */ 1);
var a = 1;
(0,_increment__WEBPACK_IMPORTED_MODULE_0__.increment)(a); // 2
// async loading
__webpack_require__.e(/*! import() */ 655).then(() => (__webpack_require__(/*! ./async-loaded */ 3))).then(function(asyncLoaded) {
console.log(asyncLoaded);
});
})();
可以清楚看到原文源码与产物的逐行对应关系:
| 源码 | 编译产物 |
|---|---|
import { increment as inc } from './increment' |
var _increment__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1) |
inc(a) |
(0,_increment__WEBPACK_IMPORTED_MODULE_0__.increment)(a) |
import("./async-loaded").then(...) |
__webpack_require__.e(655).then(() => __webpack_require__(3)).then(...) |
构建信息解读:Unoptimized 与 Production 的差异
README 的 Info 部分给出了同一份源码在两种模式下的构建统计,逐条解读如下。
Unoptimized(未压缩构建)
asset output.js 11.3 KiB [emitted] (name: main)
asset 655.output.js 761 bytes [emitted]
chunk (runtime: main) 655.output.js 24 bytes [rendered]
> ./async-loaded ./example.js 6:0-24
./async-loaded.js 24 bytes [built] [code generated]
[exports: answer]
[used exports unknown]
import() ./async-loaded ./example.js 6:0-24
chunk (runtime: main) output.js (main) 400 bytes (javascript) 5.34 KiB (runtime) [entry] [rendered]
> ./example.js main
runtime modules 5.34 KiB 8 modules
dependent modules 225 bytes [dependent] 2 modules
./example.js 175 bytes [built] [code generated]
[no exports]
[used exports unknown]
entry ./example.js main
- 两个 asset:主 chunk
output.js(11.3 KiB)与异步 chunk655.output.js(761 bytes)。655是编译期分配给该异步 chunk 的数值 id; > ./async-loaded ./example.js 6:0-24:指明异步 chunk 的来源是example.js第 6 行第 0–24 列(即import("./async-loaded")所在位置);- 异步模块
[exports: answer]、[used exports unknown]:非生产模式下没有做深入的导出使用分析,因此显示 unknown; - 主 chunk 内 400 bytes javascript + 5.34 KiB runtime(8 个 runtime 模块):运行时体积远大于业务代码,这正是小应用在生产中应启用压缩与精简运行时的原因;
dependent modules 225 bytes 2 modules:即increment.js、math.js被归入入口 chunk 的依赖模块。
Production(压缩构建)
asset output.js 2.01 KiB [emitted] [minimized] (name: main)
asset 655.output.js 121 bytes [emitted] [minimized]
...
./example.js + 2 modules 400 bytes [built] [code generated]
[no exports]
[no exports used]
- 开启 production 后 Terser 等压缩器介入,主 chunk 从 11.3 KiB 降到 2.01 KiB,异步 chunk 从 761 bytes 降到 121 bytes(
answer常量与最小化模块机制共同作用); - 导出使用状态从
[used exports unknown]变为[no exports used]——生产模式完成了全量使用分析,为后续按sideEffects/tree shaking 裁剪预留了精确依据; - 统计中
./example.js + 2 modules表明入口及其同步依赖被合并统计,这正是基于 Harmony 静态信息才可能做到的深度优化前提。
源码级印证:这些编译行为在仓库哪里实现
如果想进一步验证上述产物背后的机制,可以在仓库源码中找到对应的实现线索:
- Harmony 依赖族:
import/export的静态依赖解析分散在 lib/dependencies 下以Harmony命名的约 12 个依赖类中,例如 HarmonyImportSpecifierDependency.js(命名导入引用绑定)、HarmonyExportSpecifierDependency.js、HarmonyImportSideEffectDependency.js(副作用导入)等;模块包装函数内/* harmony import */、/* harmony export */注释即源于此类依赖的代码生成逻辑; - 导出信息与 tree shaking 基础:lib/ExportsInfo.js 承载每个模块的导出/使用状态(
[provided]、[no usage info]、[used exports unknown]等标记的直接来源); - 运行时帮助函数:
__webpack_require__.e/.d/.o/.r/.u/.l/.p/.f等符号统一注册于 lib/RuntimeGlobals.js,具体实现分散在 lib/runtime 目录(约 38 个运行时模块),产物中的 "runtime modules 5.34 KiB 8 modules" 对应的正是这些运行时片段的按需集合; - 产物生成入口:模块表、包装函数与各依赖模板的拼接发生在代码生成阶段,相关公共逻辑可见 lib/RuntimeModule.js 与
lib/DependencyTemplate体系。
动手复现与关联示例
如果你想在本机复现这份产物,可以参考 examples/README.md 记录的示例构建流程:在仓库根目录依次执行 yarn、yarn setup,然后针对单个示例运行构建命令;仓库同时也提供 examples/buildAll.js 这样的批量构建脚本(它会遍历 examples/examples.js 收集到的所有含 template.md 的示例目录逐一构建)。examples/harmony 目录内的 README 由 template.md 驱动生成,examples/template-common.js 负责把真实构建 stdout 与 dist/output.js 回填进模板;test/Examples.test.js 则在 CI 中驱动这些示例,保证展示的产物与真实编译结果一致。注意:示例展示的运行时代码是浏览器环境下的 JSONP 加载实现,Node 环境或开启了 HMR、output.chunkLoading 等不同配置时,运行时会随之更换。
围绕 Harmony 模块,仓库还提供了多个互补示例,适合串联阅读:
- examples/harmony-interop:ES Module 与 CommonJS、AMD 模块的互操作,覆盖
export *再导出 CommonJS 的特殊性及__esModule判定; - examples/harmony-unused:未使用导出如何影响产物与
[no exports used]分析; - examples/harmony-library:以 ESM 形态打包库时的导出处理;
- examples/code-splitting-harmony:Harmony 模块在代码分割场景下的更多变体;
- examples/commonjs:对比 CommonJS 模块在相同场景下的编译形态。
小结
examples/harmony 是一个“小切口、大纵深”的教科书式示例:仅 4 个文件,却完整覆盖了 ES Module 同步导入、命名导出、模块再导出、动态 import() 代码分割四大主题。透过这份产物你能直观确认三件事:其一,webpack 用“模块包装函数 + 模块缓存 + __webpack_require__”复刻了模块系统,并用 __webpack_require__.r/.d 还原 ESM 的命名空间与只读绑定语义;其二,import() 是编译期静态解析的代码分割点,会在运行时被替换成 __webpack_require__.e(chunkId) 驱动 JSONP 加载再 __webpack_require__(moduleId) 取模块的完整流程;其三,每个 Harmony 模块的导出/使用信息都被精确记录([provided]、[used exports unknown] 等注释),这正是生产模式下压缩体积与 tree shaking 得以奏效的数据基础。理解了这个最小闭环,再去看 webpack 的 tree shaking、scope hoisting、module federation 等高级特性,都会顺畅得多。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00