首页
/ webpack 代码分割实战:基于 ES Module `import()` 的按需加载与动态 import 异步上下文全面解析

webpack 代码分割实战:基于 ES Module `import()` 的按需加载与动态 import 异步上下文全面解析

2026-09-07 21:20:55作者:邵娇湘

ES Modules 的标准 import 是静态的、同步的,而 import(module) -> Promise 为 webpack 提供了语言级的代码分割(Code Splitting)入口:每个 import() 调用都是一个分割点(split point),会触发 webpack 生成独立的 chunk,直到模块真正被请求时才去加载。本文以 webpack 官方示例 examples/code-splitting-harmony 为核心,完整解析“同步 import + 按需 import() + 动态 import 表达式(async context)”三种写法在编译产物中的真实形态,带你读懂 output.js 中异步 chunk、上下文模块(context module)与运行时加载机制,并结合 ImportParserPlugin.js 的解析器源码讲清其底层分类逻辑。


一、这个示例在演示什么

该示例位于 examples/code-splitting-harmony,核心只讲一件事:用 ES6/ES Module 语法做代码分割。文档首先澄清了三个层次上的关键概念:

  • 标准 import 是同步的。它描述的是编译期的静态依赖关系,webpack 会把被导入模块直接打进当前 chunk,浏览器不需要额外请求。
  • import(module: string) -> Promise 用于按需加载。它是语言层面的动态导入原语,返回 Promise;对 webpack 而言它充当分割点,被引用的模块会被拆分进一个新的 chunk,只有在运行时执行到这行代码时,webpack 才会去加载对应 chunk。
  • 动态表达式同样可以传给 import,但受到与 require 动态表达式相同的约束:webpack 必须静态分析出所有可能取到的模块,并且每个可能被请求的模块都会生成一个额外的 chunk。示例中 import("c/" + name) 因为 node_modules/c/ 目录下只有两个文件,于是生成了两个额外 chunk——这种“把某个目录下所有可能模块全部建入 map、运行时再按需挑选”的机制,在 webpack 术语中被称为 async context(异步上下文)

该示例目录结构很精简,只包含四个文件:

  • example.js:演示入口源码;
  • webpack.config.js:仅开启 chunkIds: "deterministic"
  • template.md:README 的生成模板,其中 _{{example.js}}__{{stdout}}__{{production:stdout}}_ 等占位符会在渲染 README 时被替换成真实文件内容与两次构建(非优化 / 生产模式)的输出;
  • README.md:渲染后的成品文档。

template.md 的占位符替换逻辑定义在 examples/template-common.jsreplaceBase/replaceResults),它会把编译输出中冗长的 runtime 代码折叠为 /* webpack runtime code */<details> 区块,这正是 README 的排版结构。


二、示例源码逐行解读

入口源码 example.js 非常短,但它同时覆盖了三种典型写法:

import a from "a";

import("b").then(function(b) {
	console.log("b loaded", b);
})

function loadC(name) {
	return import("c/" + name);
}

Promise.all([loadC("1"), loadC("2")]).then(function(arr) {
	console.log("c/1 and c/2 loaded", arr);
});
代码 类型 webpack 的处理
import a from "a" 同步静态 import 模块 a 被直接打进主入口 chunk,启动即执行,无额外网络请求
import("b").then(...) 静态字符串的动态 import b 的表达式在编译期可被完整解析为 "b",因此生成一个独立的按需 chunk(示例中为 414.output.js
import("c/" + name) 带动态表达式的 import 无法静态确定具体文件,退化为 async context:扫描 node_modules/c/ 得到 1.js2.js,每个文件生成独立 chunk(197.output.js140.output.js),并生成一个上下文模块负责运行时转发

注意 loadC("1")loadC("2") 被放入 Promise.all,它们最终会被编译成对同一个上下文模块的两次调用;由于每次请求的请求字符串不同,加载的是两个不同的异步 chunk。

该目录配套的 webpack.config.js 出奇地简单:

"use strict";

/** @type {import("webpack").Configuration} */
const config = {
	optimization: {
		chunkIds: "deterministic" // To keep filename consistent between different modes (for example building only)
	}
};

module.exports = config;

它只做了一件事:把 chunk 命名策略固定为 deterministic。这样无论以非优化(development)模式还是生产模式构建,140197414 这些由模块内容哈希推导出的稳定 chunk id 都保持一致,产物文件名在不同模式之间可以对齐——这也是 README 中 “Unoptimized” 与 “Production mode” 两份统计里 chunk 编号完全相同的直接原因。若不加该项,默认的 total-size/named 等策略在不同模式或不同构建次数下会产出不同的 id,示例的展示与测试快照将无法稳定复现。


三、编译产物剖析:读懂 dist/output.js

README 的核心篇幅是剖析产物 output.js 的结构(在该示例中入口 chunk 名为 main,输出为 output.js,异步 chunk 以“数字 id + .output.js”命名)。下面按产物中的真实顺序拆解。

3.1 模块表(__webpack_modules__)的前三个模块

产物整体是一个“webpackBootstrap”IIFE,内部维护模块表数组 __webpack_modules__。数组前几个槽位长这样(节选自 README.mddist/output.js 一节):

/******/ (() => { // webpackBootstrap
/******/ 	var __webpack_modules__ = ([
/* 0 */,
/* 1 */
/*!***************************!*\
  !*** ./node_modules/a.js ***!
  \***************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements:  */
/***/ (() => {

// module a

/***/ }),
/* 2 */
/*!********************************************************!*\
  !*** ./node_modules/c/ lazy ^\.\/.*$ namespace object ***!
  \********************************************************/
/*! default exports */
/*! exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__.e, module, __webpack_require__.o, __webpack_require__, __webpack_require__.t, __webpack_require__.* */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

const map = {
	"./1": [
		4,
		[
			197
		]
	],
	"./1.js": [
		4,
		[
			197
		]
	],
	"./2": [
		5,
		[
			140
		]
	],
	"./2.js": [
		5,
		[
			140
		]
	]
};
function webpackAsyncContext(req) {
	try {
		if(!__webpack_require__.o(map, req)) {
			return Promise.resolve().then(() => {
const e = new Error("Cannot find module '" + req + "'");
e.code = 'MODULE_NOT_FOUND';
throw e;
});
		}
	} catch(err) {
		return Promise.reject(err);
	}

	const ids = map[req], id = ids[0];
	return __webpack_require__.e(ids[1][0]).then(() => (__webpack_require__.t(id, 7 | 16)));
}
webpackAsyncContext.keys = () => (Object.keys(map));
webpackAsyncContext.id = 2;
module.exports = webpackAsyncContext;

/***/ })
/******/ 	]);

几个值得注意的细节:

  1. 模块 1 是 ./node_modules/a.js。它就是被同步 import a from "a" 引用的模块,被直接内联进主 chunk,注释 unknown exports (runtime-defined) 表明它没有可静态分析的 ESM 导出(a.js 属于 CommonJS 风格)。
  2. 模块 2 是 node_modules/c 的惰性上下文模块,模块头的 lazy ^\.\/.*$ namespace object 是它的“身份证”:lazy 表示按需(lazy)模式,^\.\/.*$ 是匹配可能请求的正则(即 c 目录下相对路径的全部可能取值),namespace object 表示返回的是命名空间对象。
  3. map 是上下文查找表。webpack 扫描到 node_modules/c/ 下有 1.js2.js 两个文件;由于默认解析会尝试补全 .js 扩展名,map 中实际包含四个键:./1./1.js 都指向模块 4(chunk 197),./2./2.js 都指向模块 5(chunk 140)。
  4. webpackAsyncContext(req) 是运行时转发函数:先用 __webpack_require__.ohasOwnProperty 简写)校验请求是否在 map 中,不在则按 MODULE_NOT_FOUND 拒绝;命中则取 [moduleId, [chunkId]],先调用 __webpack_require__.e(chunkId) 确保对应异步 chunk 已被加载,再用 __webpack_require__.t(id, 7 | 16) 把模块 id 包装为命名空间对象返回。这里 7 | 16 === 23,与入口中 import("b") 的调用方式完全一致(详见 3.3)。
  5. 上下文模块还暴露了 keys()(返回 map 的所有键)与 id(=2),方便在 require.context 相关场景中做枚举与运行时标记。

3.2 运行时(runtime)模块速览

产物中 /* webpack runtime code */ 是一整套运行时函数。README 用 <details> 把它们折叠起来,下面是各运行时模块的作用与语义速览(行为均出自 README 中折叠代码的注释与实现,与 lib/runtime 目录下的运行时模块源码对应):

运行时符号 名称 职责
__webpack_module_cache__ + __webpack_require__ 模块缓存与加载 标准的 CommonJS 风格模块运行时:命中缓存直接返回 exports,否则创建 module、执行模块函数并写入缓存
__webpack_require__.m 模块表暴露 __webpack_modules__ 挂到 __webpack_require__.m,供 chunk 回调等机制写入新模块
__webpack_require__.n compat get default export 生成“取 default 导出”的兼容 getter:对 __esModule 模块返回 module['default'],否则返回模块本身(CommonJS 默认导出互操作)
__webpack_require__.t create fake namespace object mode 位把模块值转换为命名空间对象(见下方位说明)
__webpack_require__.d define property getters 以 getter 方式把导出定义到对象上,保证 ESM 的实时绑定语义
__webpack_require__.e ensure chunk 汇总 __webpack_require__.f 上各 chunk 加载器返回的 Promise,用 Promise.all 等待所有相关加载完成
__webpack_require__.u get javascript chunk filename 计算异步 chunk 的 URL,本例为 chunkId + ".output.js"
__webpack_require__.o hasOwnProperty 简写 Object.prototype.hasOwnProperty.call 的工具函数
__webpack_require__.l load script 创建 <script> 标签加载 chunk;按 src 去重、维护 inProgress 队列、120000ms 超时,支持 CSP nonce__webpack_require__.nc
__webpack_require__.r make namespace object 给导出对象打上 Symbol.toStringTag === 'Module'__esModule === true 标记
__webpack_require__.p publicPath 本例被设置为 "dist/",是脚本 URL 的前缀
__webpack_require__.f.j jsonp chunk loading 浏览器端的 JSONP chunk 加载器(见 3.4)

其中 __webpack_require__.tmode 参数是一组位标志,产物代码中的注释把它解释得很清楚:

// create a fake namespace object
// mode & 1: value is a module id, require it
// mode & 2: merge all properties of value into the ns
// mode & 4: return value when already ns object
// mode & 16: return value when it's Promise-like
// mode & 8|1: behave like require

也就是说:1 表示“值是个模块 id,需要先 require”;2 表示把值的所有属性并入命名空间;4 表示若值已是命名空间对象则原样返回;16 表示若值类似 Promise(有 then)则原样返回。入口中对 b 的调用 __webpack_require__.t(3, 23)23 = 16 + 4 + 2 + 1,等价于 7 | 16:先按模块 id 3 require,加载完成得到 CommonJS 风格的导出对象,再包装成“含 default 导出的命名空间对象”交给 .then 回调。

3.3 入口模块的编译形态

产物末尾是入口模块(./example.js)被编译后的样子,它被包在一个 "use strict" 的 IIFE 中(节选自 README 中 dist/output.js 一节):

(() => {
"use strict";
/*!********************!*\
  !*** ./example.js ***!
  \********************/
/*! namespace exports */
/*! exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_require__.n, __webpack_require__.r, __webpack_exports__, __webpack_require__.e, __webpack_require__.t, __webpack_require__.* */
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var a__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! a */ 1);
/* harmony import */ var a__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(a__WEBPACK_IMPORTED_MODULE_0__);


__webpack_require__.e(/*! import() */ 414).then(() => (__webpack_require__.t(/*! b */ 3, 23))).then(function(b) {
	console.log("b loaded", b);
})

function loadC(name) {
	return __webpack_require__(2)("./" + name);
}

Promise.all([loadC("1"), loadC("2")]).then(function(arr) {
	console.log("c/1 and c/2 loaded", arr);
});

})();

对照原始源码,可以看到三种写法被翻译成了三种不同的调用序列:

  1. 同步 importimport a from "a" 变成 __webpack_require__(1)。由于 a.js 不是 ESM,webpack 额外生成 __webpack_require__.n(...) 取 default 的互操作 getter(代码中标注了 /* harmony import *//*#__PURE__*/)。
  2. 静态 import()import("b") 变成 __webpack_require__.e(414).then(() => (__webpack_require__.t(3, 23)))。先保证 chunk 414 已加载,再把其中的模块 3 包装成命名空间对象交给业务回调;注释 /*! import() */ 保留了源码位置信息。
  3. 动态 import()(async context)import("c/" + name) 变成对模块 2 的调用 __webpack_require__(2)("./" + name)。请求字符串在运行时由参数 name 拼出("./1""./2"),真正加载哪个 chunk 取决于运行时传入的名字——这正体现了异步上下文“编译期穷举、运行期派发”的设计。

值得注意的是,产物顶部还标注了本模块运行时需求清单(runtime requirements),包括 __webpack_require__.n.r.e.t 等。webpack 会按“模块实际用到的运行时能力”最小化注入这些代码,这也是产物能被 tree-shaking 与按需裁剪的基础。

3.4 JSONP chunk 加载:异步 chunk 是如何被拉取的

异步 chunk 的加载由 __webpack_require__.f.j 与全局 JSONP 回调共同完成,其关键数据结构 installedChunks 的状态语义在产物注释中标明:

// object to store loaded and loading chunks
// undefined = chunk not loaded, null = chunk preloaded/prefetched
// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded

加载流程大致为:__webpack_require__.e(chunkId) 遍历 __webpack_require__.f 上的加载器;f.j 检查 installedChunks[chunkId]——若为 0 说明已安装直接跳过;若已有 Promise 则复用;否则创建 [resolve, reject] 三元组并调用 __webpack_require__.l<script> 方式请求 __webpack_require__.p + __webpack_require__.u(chunkId),即 "dist/" + chunkId + ".output.js"。加载成功后由全局回调 webpackJsonpCallback 把 chunk 中的模块合并进 __webpack_require__.m,逐一把 chunk 标记为已安装(installedChunks[chunkId] = 0)并 resolve 对应 Promise。加载失败时(load 错误、超时等)会构造一个 ChunkLoadError,其 message 形如 Loading chunk 140 failed. (type: ...)

全局数组 self["webpackChunk"]push 被覆写为 webpackJsonpCallback,这样异步 chunk 文件无论先于还是后于入口执行,都能可靠地把自己的模块注册进运行时。


四、构建统计信息(Info)解读

README 末尾“Info”一节分别给出 UnoptimizedProduction mode 两份 webpack 编译统计,这也是验证上述拆分的直接证据。

Unoptimized(未压缩构建)

asset output.js 13.1 KiB [emitted] (name: main)
asset 140.output.js 284 bytes [emitted]
asset 197.output.js 284 bytes [emitted]
asset 414.output.js 276 bytes [emitted]
chunk (runtime: main) 140.output.js 13 bytes [rendered]
  > ./2 ./node_modules/c/ lazy ^\.\/.*$ namespace object ./2
  > ./2.js ./node_modules/c/ lazy ^\.\/.*$ namespace object ./2.js
  ./node_modules/c/2.js 13 bytes [optional] [built] [code generated]
    [used exports unknown]
    import() context element ./2 ./node_modules/c/ lazy ^\.\/.*$ namespace object ./2
    import() context element ./2.js ./node_modules/c/ lazy ^\.\/.*$ namespace object ./2.js
chunk (runtime: main) 197.output.js 13 bytes [rendered]
  > ./1 ./node_modules/c/ lazy ^\.\/.*$ namespace object ./1
  > ./1.js ./node_modules/c/ lazy ^\.\/.*$ namespace object ./1.js
  ./node_modules/c/1.js 13 bytes [optional] [built] [code generated]
    [used exports unknown]
    import() context element ./1 ./node_modules/c/ lazy ^\.\/.*$ namespace object ./1
    import() context element ./1.js ./node_modules/c/ lazy ^\.\/.*$ namespace object ./1.js
chunk (runtime: main) 414.output.js 11 bytes [rendered]
  > b ./example.js 3:0-11
  ./node_modules/b.js 11 bytes [built] [code generated]
    [used exports unknown]
    import() b ./example.js 3:0-11
chunk (runtime: main) output.js (main) 414 bytes (javascript) 6.7 KiB (runtime) [entry] [rendered]
  > ./example.js main
  runtime modules 6.7 KiB 10 modules
  dependent modules 171 bytes [dependent] 2 modules
  ./example.js 243 bytes [built] [code generated]
    [no exports]
    [used exports unknown]
    entry ./example.js main
webpack X.X.X compiled successfully

Production mode(生产压缩构建)

asset output.js 2.91 KiB [emitted] [minimized] (name: main)
asset 140.output.js 66 bytes [emitted] [minimized]
asset 197.output.js 66 bytes [emitted] [minimized]
asset 414.output.js 66 bytes [emitted] [minimized]
chunk (runtime: main) 140.output.js 13 bytes [rendered]
  > ./2 ./node_modules/c/ lazy ^\.\/.*$ namespace object ./2
  > ./2.js ./node_modules/c/ lazy ^\.\/.*$ namespace object ./2.js
  ./node_modules/c/2.js 13 bytes [optional] [built] [code generated]
    [used exports unknown]
    import() context element ./2 ./node_modules/c/ lazy ^\.\/.*$ namespace object ./2
    import() context element ./2.js ./node_modules/c/ lazy ^\.\/.*$ namespace object ./2.js
chunk (runtime: main) 197.output.js 13 bytes [rendered]
  > ./1 ./node_modules/c/ lazy ^\.\/.*$ namespace object ./1
  > ./1.js ./node_modules/c/ lazy ^\.\/.*$ namespace object ./1.js
  ./node_modules/c/1.js 13 bytes [optional] [built] [code generated]
    [used exports unknown]
    import() context element ./1 ./node_modules/c/ lazy ^\.\/.*$ namespace object ./1
    import() context element ./1.js ./node_modules/c/ lazy ^\.\/.*$ namespace object ./1.js
chunk (runtime: main) 414.output.js 11 bytes [rendered]
  > b ./example.js 3:0-11
  ./node_modules/b.js 11 bytes [built] [code generated]
    [used exports unknown]
    import() b ./example.js 3:0-11
chunk (runtime: main) output.js (main) 403 bytes (javascript) 6.43 KiB (runtime) [entry] [rendered]
  > ./example.js main
  runtime modules 6.43 KiB 9 modules
  dependent modules 160 bytes [dependent] 1 module
  ./example.js 243 bytes [built] [code generated]
    [no exports]
    [no exports used]
    entry ./example.js main
webpack X.X.X compiled successfully

从这两份统计可以读出:

  • 一共生成 4 个 asset:入口 output.js(name: main)与三个异步 chunk 140.output.js197.output.js414.output.js
  • 414.output.js 承载模块 ./node_modules/b.js(来源标注为 import() b ./example.js 3:0-11,即源码第 3 行);197.output.js 承载 c/1.js140.output.js 承载 c/2.js,二者均被标注为 import() context element,并且每个元素分别对应 ./1./1.js 两个“上下文元素”(因 webpack 自动尝试补全扩展名)。
  • 由于 c 目录模块只有在真正被请求时才加载,它们被标为 [optional],主 chunk 中对模块 2(上下文模块)与 a.js(模块 1)是必需的。
  • 生产模式下文件大幅缩小:入口从 13.1 KiB 降到 2.91 KiB,三个异步 chunk 分别降到 66 bytes;入口部分 [no exports used] 表明生产构建还额外做了导出使用情况分析,runtime modules 也从 10 个减到 9 个。
  • 末尾的 webpack X.X.X compiled successfullyX.X.X 是模板化占位符——README 由构建脚本渲染,实际版本号不固定,这正是 examples/template-common.js 在渲染前做文本规范化的原因之一。

五、源码级验证:解析器如何区分两种 import()

产物形态背后是解析器对 import() 表达式的分类逻辑。import() 在编译期由 lib/dependencies/ImportParserPlugin.js 处理,其核心分支正是“参数能否被静态求值为字符串”:

  • 静态字符串参数(如 import("b")):见 ImportParserPlugin.js,构造一个 AsyncDependenciesBlock(代码分割块的载体)并放入 ImportDependency,随后 parser.state.current.addBlock(depBlock) 把整块挂到当前模块上,从而形成“新 chunk + 异步依赖”的结构。除此之外还会根据第二参数(expr.options)是否为可静态提取的 import attributes 决定是否保留运行时校验逻辑。
  • 动态表达式参数(如 import("c/" + name)):落入 ImportParserPlugin.jselse 分支,走 ContextDependencyHelpers.create(ImportContextDependency, ...),并传入 typePrefix: "import()"category: "esm" 等选项。ImportContextDependency(定义于 lib/dependencies/ImportContextDependency.js)会驱动上下文模块(ContextModule)的创建——也就是我们在产物中见到的模块 2 node_modules/c/ lazy ^\.\/.*$ namespace object。此时依赖块不再指向单个模块,而是指向“一个目录 + 一组穷举出的元素(context element)”,每个元素又各自成为一个 chunk。

从产物回推,还可以确认动态分支的 mode 处理:上下文模块在运行时使用 7 | 16(即 23)作为命名空间包装的 mode 位,与静态 import("b") 编译出的 23 完全一致——二者最终都通过 __webpack_require__.e + __webpack_require__.t 的组合实现“先保证 chunk 就绪、再返回规范命名空间对象”。这也解释了为什么 README 在讲解 async context 时说“每个可能的模块创建一个额外 chunk”:因为穷举发生在编译期(生成 map 与多个 chunk),而真正的加载被推迟到运行期。

需要留意:动态 import 的约束与动态 require 一致,即表达式能被静态分析到“确定的候选集合”。例如把 name 换成真正无法分析的变量(如网络返回值),webpack 会给出警告或无法生成精确的上下文。若需要过滤上下文内的文件,可以通过 import(/* webpackInclude: ... */ ...) 等 magic comment 或 ContextReplacementPlugin 控制,这些都属于建立在本文“async context”机制之上的进阶用法。


六、如何运行、验证与继续阅读

运行示例

  1. 先完成仓库依赖准备:在仓库根目录按 _SETUP.md 执行 yarn setup(其脚本见 setup/setup.js,会执行 yarn installyarn linkyarn link webpack,使 node_modules/webpack 指向仓库自身)。
  2. 示例通过裸模块名 abc/1c/2 引用依赖(对应仓库 node_modules 中安装后的 a.jsb.jsc/1.jsc/2.js 等模块),在 examples/code-splitting-harmony 目录下分别以 development 与 production 模式执行 webpack,即可复现 README “Unoptimized / Production mode” 两份产物:
cd examples/code-splitting-harmony
npx webpack --mode development
npx webpack --mode production

由于 webpack.config.js 固定了 chunkIds: "deterministic",两次构建产出的 chunk 文件名(140.output.js197.output.js414.output.js)应当一致。浏览器中可通过把 dist/output.js 作为入口加载、观察控制台日志与 Network 面板中异步 chunk 的按需请求来验证加载时机。

测试验证

所有带 template.md 的示例都会由 examples/examples.js 递归收集,并在 test/Examples.test.js 中以 jest 用例方式被真实编译验证:该测试逐个加载示例的 webpack.config.js(兼容 .js/.mjs/.cjs 三种后缀)、设置 output.path 为示例下 distoutput.publicPath"dist/",并检查构建错误与基础设施日志。也就是说,README 中展示的产物与统计并非“手写的期望”,而是可被持续集成反复核对的真实编译结果,这为本文的全部拆解提供了可复现的测试背书。

扩展阅读


小结

通过 examples/code-splitting-harmony 这一个例子,我们可以完整看到 webpack 对三类 ESM 导入的三级处理策略:同步 import 被原样内联、静态 import("b") 生成单一异步 chunk、动态 import("c/" + name) 生成带查找表(map)的 async context 上下文模块并为每个候选模块各建一个 chunk。产物中的 __webpack_require__.e(chunk 加载)、__webpack_require__.t(命名空间包装与 CommonJS 互操作)以及 JSONP 运行时共同构成了浏览器端按需加载的完整链路。掌握了这条从语法、解析器(ImportParserPlugin.js)到运行时产物的完整证据链,你就拥有了对 webpack 代码分割进行二次优化与排障的最扎实基础。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391