请将以下文字发送给AI,AI会自动优化此插件,以适合新内核的「按需加载」特性。
优化后,请再次提交,非常感谢。请阅读插件文档 https://bbs1.org/dev_docs 完成按需加载的优化 ### 插件资源按需加载 默认情况下,启用插件的 `assets` 会被合并进公共合集 `app/assets/plugins.css` 和 `app/assets/plugins.js`,全站每个页面都会加载。功能只在少数页面出现的插件(编辑器、播放器、图表、大尺寸样式)会拖慢所有页面,这类插件应改为按需加载。 **声明方式**:manifest 增加 `'assets_mode' => 'ondemand'`。值不是 `ondemand` 时按默认(公共合集)处理,无需为旧插件补字段。 **登记方式**:在负责渲染该页面的 Hook 里调用 `if (function_exists('plugin_asset_require')) plugin_asset_require('插件ID')`。只需要其中一类资源时传第二个参数:`plugin_asset_require('插件ID', 'css')` 只输出样式、`plugin_asset_require('插件ID', 'js')` 只输出脚本;不传(或传其它值)表示两类都要。核心按页面收集并去重,公共合集照常输出,被登记的插件再追加自己的 `<link>` / `<script>`;CSS 落在 `<head>`,JavaScript 在页脚以 `defer` 加载。未登记的页面完全不加载该资源。 **按类型登记**:页面只用到样式或只用到脚本时,传第二个参数,避免另一类资源白下载。 规则: - 登记必须发生在页面输出之前,也就是插件自己的 Hook 里。核心在整页模板渲染完成后统一收集,因此 `page.footer` 这类页脚 Hook 里的登记同样有效。 - 同一个插件多次登记无副作用,核心自动去重;不同插件之间互不影响,输出顺序按登记顺序。 - `assets` 函数仍必须无参数、返回源码、不依赖当前用户或页面数据,与默认模式一致;动态值通过 `data-*` 传递。 - 按需资源由核心生成到 `app/assets/plugins/<插件ID>.css|js`,插件不要手写或提交这些文件,升级器也不会覆盖该目录。生成与重建由启用、停用、卸载、市场安装、更新和后台同步自动完成;文件缺失时页面首次访问会补生成。 - 参数是插件 ID,只有已启用且声明为按需模式的插件会被接受;未启用、未声明按需或 ID 非法时静默忽略。插件之间的直接调用仍受「不得依赖其他插件」约束,通常只登记自己。 - 类型过滤只决定输出哪类标签,不拆分文件:插件仍是一个 `app/assets/plugins/<插件ID>.css` 和一个 `.js`。`plugin_asset_require('插件ID', 'css')` 只是不再同时输出 `<script>`,适合「列表页只要样式、只有编辑页才要脚本」这类场景;同一请求内先后调用不同类型(或后调不带参数)时取并集,只增不减。插件没有声明该类型时不会输出任何标签。 - 兼容老内核时写成 `if (function_exists('plugin_asset_require')) plugin_asset_require('插件ID');`:老内核没有这个函数,且会忽略 `assets_mode`、把资源照旧并入公共合集,兜底后界面正常、只是不按需;裸调则会抛错并被自动停用插件。老内核的 `plugin_asset_require()` 也不认识第二个参数,多传的类型参数会被忽略并回退为两类都加载,所以上述兜底写法可以直接保留第二个参数。兜底只包住调用,不要用它定义无前缀函数。 - 页面内的 AJAX 局部 HTML 不会触发资源输出:局部内容若要动态用上按需资源,需在首次整页渲染时已登记,或由插件自行保证依赖可用。 - 从默认模式改成按需模式(或反向)后,系统会在对应插件更新或下次后台同步时迁移资源位置:移入独立文件并删除合集里的旧分块,反向则写回公共合集并删除独立文件。迁移不影响其他插件。 **何时不要用按需加载**:几乎每页都需要的资源(导航、主题列表样式、全局脚本)留在公共合集更划算,否则每页都要多一次请求。只在少数路由出现的功能才适合按需。 **资源加载约束(必须遵守)**: - 插件的 CSS / JavaScript 只在实际使用该插件功能的页面加载;要按类型分别登记,列表页只用样式就不要顺带输出脚本,详情页才需要的脚本不要在前一页登记。 - 禁止在每页都会触发的全局渲染 Hook 里无条件调用 `plugin_asset_require()`。属于这一类的是 `page.before_render`、`page.head`、`page.header`、`page.footer`、`page.seo`、`page.template`、`page.template.before`、`top.menu_links`、`top.bar.actions`、`user.menu_links`、`sidebar.feature_links`、`sidebar.stack`。 - 功能确实要挂在全局 Hook 上时,必须先判断当前路由、页面类型或 HTML 上下文(`$_GET['a']`、`$ctx` 中的页面信息、页面里是否存在对应 `data-*` 锚点等),命中才登记,不命中直接返回原 HTML。 - 判断页面范围只能依据实际路由和 Hook 调用关系,不能凭插件名、目录名或文件名猜测;无法安全确定范围的保留现状并在交付说明里写明原因,不要为了「减少请求」删掉真实的全局依赖。 - 主题、皮肤、全局控件这类确实每页都会用到的资源,继续留在公共合集或在全局 Hook 里有明确理由地登记;按需化改造只调整资源登记位置与加载条件,不改变现有功能、页面文案、业务逻辑和后台配置。 ### `links` 入口数据化 入口只是在导航或 Tab 栏加一条静态链接时,不必注册 Hook,直接在 manifest 的 `links` 里声明,核心会按原有位置和顺序渲染,并且不会 include 插件文件。`links` 与旧内核兼容:老内核不认识该字段会忽略它,所以同一插件应同时保留原有 `hooks` 回调;新内核检测到 `links` 声明后自动优先使用数据、跳过该入口的回调。 可声明的入口只有 7 个:`top_menu`、`feature_links`、`profile_card`、`profile_tabs`、`profile_settings_tabs`、`home_tabs`、`admin_tabs`。`sidebar_cards`、`topic_actions`、`top_actions` 返回 HTML 或依赖页面数据,继续用函数 Hook。 - `text`(Tab 类入口可写 `label`):纯文本,核心输出时统一转义,最多 60 字;和 `text_config` 至少写一个。 - `text_config`:文案取自插件配置的键名(`plugin_config()` 里保存的键)。配置值非空时用它覆盖 `text`,此时 `text` 可写配置缺省值,也可以留空;纯文本、会话前经过截断与去标签,最多 60 字。 - `url` 或 `route` + `params`:二选一。`url` 只允许相对地址或 `http`/`https` 绝对地址;`route` 由 `route_url()` 生成,参数键只用小写字母、数字、下划线。参数值可以写 `{ctx}` 占位符,从当前入口上下文取值:`{uid}`(当前登录用户)、`{self}`、`{active}`、`{forum_id}`、`{query}`、`{page}`、`{user.id}`、`{user.username}`;取不到值或为空时整条链接不渲染。 - `key`:Tab 类入口必填(`admin_tabs`/`home_tabs`/`profile_tabs`/`profile_settings_tabs`),与 `$active` 比较决定高亮;`before` / `after` 可把该 Tab 插到指定核心 Tab 之前/之后,锚点不存在时追加在末尾。 - `icon`:核心图标名(`user`/`id`/`reply`/`notify`/`forum`/`topic`/`view`/`settings`/`admin`/`pages`/`upload`),`icon_html` 可传单行 `<svg>` 片段,仅允许绘图标签与普通属性。 - `when`:渲染条件,全部满足才显示。`login`(已登录)、`self`(当前查看的是本人主页)、`admin`(`true` 要求可访问后台,`false` 要求不是管理员)、`config`(插件配置条件)、`ctx`(入口上下文条件)。`config` 与 `ctx` 可写单个键名、单个条件数组或条件数组列表,列表内全部满足才显示;单个条件形如 `['key' => 'enabled', 'default' => true]`,`default` 是配置缺省值,再加 `'equals' => false` 表示配置值必须等于该值(布尔值按真假比较,其他按字符串比较)。`ctx` 按当前入口上下文判断,键支持 `user.id` 这类点号路径,`'equals' => false` 表示该上下文值为空。 - 文字可以来自配置(用 `text_config`);依赖 `$ctx` 的显示条件和 URL 参数用 `when.ctx` 与 `{ctx}` 占位符表达;带未读角标、需要拼装动态文案或调用 `plugin_asset_require()` 的入口仍无法数据化,继续用函数 Hook。 - 每个入口最多 20 条,非法条目在同步时直接丢弃。 - 数据条目只输出核心链接结构,不能再调用 `plugin_asset_require()`;需要插件样式或脚本的入口继续用函数 Hook。 - 同一入口不要同时期待数据和回调都生效:声明 `links` 后该入口的回调会被跳过,回调里的其他逻辑也会一起失效。最后由 bbs1 编辑于 2026-10-31 16:56点赞与点评1sheyang投币1个25分钟前
主楼