# 核心、子系统与清单

选择可选入口，并在文件、宿主或应用模块中声明契约。

本页介绍 WU Framework `4.0.0`。升级现有项目之前，请阅读 [Framework 4.0 与 CLI 1.2 迁移指南](/zh-cn/docs/guides/releases/)。

<span id="elegir-el-runtime"></span>

<span class="section-anchor" id="section-1"></span>

## 选择运行时

`wu-framework` 在首次使用时加载可选子系统。`wu-framework/core` 要求宿主显式导入。CLI `1.0.0` 在开发和生产环境中让宿主与应用共享核心入口。

```js
import { wu } from 'wu-framework/core';
import 'wu-framework/timeline';
import 'wu-framework/ports';

await wu.init({ apps: [] });
const timeline = await wu.timelineReady();
```

| 功能 | 宿主导入 |
| --- | --- |
| AI | `wu-framework/ai` |
| Timeline | `wu-framework/timeline` |
| Devtools | `wu-framework/devtools` |
| MCP | `wu-framework/mcp` |
| `strict` | `wu-framework/sandbox/iframe` |
| `eval` | `wu-framework/sandbox/html-parser` + `wu-framework/sandbox/iframe` |
| Store sync | `wu-framework/store-sync` |
| Shadow | `wu-framework/shadow` |
| Windows | `wu-framework/windows` |
| Drag and drop | `wu-framework/dnd` |
| Ports / remote | `wu-framework/ports` |
| `.wuapp` | `wu-framework/wuapp` |

缺少导入时，`WU_OPTIONAL_NOT_BUNDLED` 会指出子系统及所需入口。在宿主中导入一次并重新构建。导入只注册子系统，不会授予应用权限。

<span id="tres-fuentes-de-manifest"></span>

<span class="section-anchor" id="section-2"></span>

## 三种清单来源

`manifest: "fetch"` 默认加载 `wu.json`。`manifest` 对象可在宿主中声明同样的信息。使用 `manifest: "define"` 时，模块调用 `wu.declare` 或向 `wu.define` 的第三个参数传入 `{ manifest }`；必须配置 `entry`，因为没有预先提供模块入口的文件。

```js
// shell.js
import { wu } from 'wu-framework/core';
await wu.init({ apps: [{
  name: 'greeting', url: '/apps/greeting/',
  manifest: 'define', entry: 'entry.js', grants: [],
}] });
await wu.mount('greeting', '#greeting-slot');
```

```js
// apps/greeting/entry.js
import { wu } from 'wu-framework/core';
wu.define('greeting', {
  mount(container) { container.textContent = 'Hello from WU'; },
  unmount(container) { container.replaceChildren(); },
}, { manifest: { wu: { permissions: [] } } });
```

宿主 HTML 必须包含 `#greeting-slot`；应用模块必须导入与宿主相同的 WU 实例。三种模式都验证清单并应用宿主授权。用 JavaScript 声明并不会使代码保密，也不会建立安全边界。

<span id="identidad-al-cargar"></span>

<span class="section-anchor" id="section-3"></span>

## 加载时的身份

`definesAs` 可为保留原始名称的模块注册另一实例。加载期间，WU 将 `define` 和 `declare` 重定向到新注册项。每个重定向名称只能有一个活动加载，否则返回 `WU_DEFINE_REDIRECT_BUSY`。名称错误时，`WU_DEFINE_NAME_MISMATCH` 会报告实际名称，而不会重复无效的超时重试。

<span id="montar-dentro-de-otro-shadow-dom"></span>

<span class="section-anchor" id="section-4"></span>

## 在另一个 Shadow DOM 内挂载

`mount(name, target)` 接受选择器或 `HTMLElement`。当元素位于 Shadow DOM 内时，请直接传入元素：文档选择器不能跨越该边界。恢复和卸载使用同一个宿主；以元素挂载时，`inspect()` 返回 `containerSelector: null`。

```js
// The shell has already registered and initialized the editor app.
const shell = document.querySelector('my-shell');
const slot = shell.shadowRoot.querySelector('[data-editor-slot]');
await runtime.mount('editor', slot);
// Later, when the shell releases this view:
await runtime.unmount('editor', { force: true });
```

<span id="instancias-con-recursos-propios"></span>

<span class="section-anchor" id="section-5"></span>

## 实例拥有自己的资源

每个 `new WuCore()` 都有自己的 store、内存缓存、性能条目和预加载提示。`destroy()` 释放这些资源，同时保留其他实例的资源。通过 `new WuCore({ cache })` 注入的缓存由调用方拥有，不会被自动清空。如需持久化，请创建具有明确存储方式和 `namespace` 的 `WuCache`，并决定何时清理它。

请在对应实例上通过 `runtime.define(...)` 注册生命周期。导入全局单例 `wu` 会在共享宿主上注册。独立实例在记录变更前应等待 `runtime.timelineReady()`。此模式用于在同一页面组合可信示例，不为任意代码建立安全边界。

参阅[监督、恢复与 replay](/zh-cn/docs/framework/runtime-reliability/)，了解 `superviseApp`、`createReplaySession` 和 scoped 方法 `reportError`、`now`、`random`。

`destroy()` 撤销 host 创建的 ports、将应用从分离窗口返回，并释放该实例的 drag and drop、shadow、health、replay 和 timeline 资源。应用 lease 撤销时，包括卸载或隔离，也会释放拖动 offers 和 targets。