From bb730480b165a34e46012290d10a37b8e332fce5 Mon Sep 17 00:00:00 2001 From: GVSADS Date: Sun, 22 Feb 2026 11:06:50 +0800 Subject: [PATCH] Fix-CSS-Relative-Paths --- DOC.MD | 235 +++++ README.MD | 218 +++++ TOOLS.MD | 1 + app.py | 10 + build/ResourceShare-1.3.7.4.js | 1376 +++++++++++++++++++++++++++ build/ResourceShare-1.3.7.4.min.js | 13 + build/ResourceShare-1.3.7.5.js | 1421 ++++++++++++++++++++++++++++ build/ResourceShare-1.3.7.5.min.js | 13 + src/Copyright.js | 13 + src/build.json | 16 + src/build/output.js | 47 + src/modules/Diagnostics.js | 77 ++ src/modules/ResourceShareLogger.js | 73 ++ src/modules/ResourceShareUI.js | 264 ++++++ src/utils/config.js | 60 ++ src/utils/utils.js | 67 ++ test.html | 4 + vbuild.py | 46 + 18 files changed, 3954 insertions(+) create mode 100644 DOC.MD create mode 100644 README.MD create mode 100644 TOOLS.MD create mode 100644 app.py create mode 100644 build/ResourceShare-1.3.7.4.js create mode 100644 build/ResourceShare-1.3.7.4.min.js create mode 100644 build/ResourceShare-1.3.7.5.js create mode 100644 build/ResourceShare-1.3.7.5.min.js create mode 100644 src/Copyright.js create mode 100644 src/build.json create mode 100644 src/build/output.js create mode 100644 src/modules/Diagnostics.js create mode 100644 src/modules/ResourceShareLogger.js create mode 100644 src/modules/ResourceShareUI.js create mode 100644 src/utils/config.js create mode 100644 src/utils/utils.js create mode 100644 test.html create mode 100644 vbuild.py diff --git a/DOC.MD b/DOC.MD new file mode 100644 index 0000000..4455acd --- /dev/null +++ b/DOC.MD @@ -0,0 +1,235 @@ +# ResourceShare.js 系统原理文档 (V1.3.7.4) + +**版本:** V1.3.7.5 +**发布日期:** 2026 +**开发团队:** GVSDS Team +**许可协议:** MIT License + +--- + +## 1. 系统概述 + +`ResourceShare.js` 是一个高性能的跨域资源共享系统,专门设计用于解决复杂 Web 应用(特别是包含大量 iframe 嵌套的单页应用)中的资源重复加载、依赖管理混乱以及脚本执行顺序不可控等问题。 + +### 1.1 核心特性 +* **跨级资源共享:** 利用 `postMessage` 和 `Blob URL` 技术,使得同源下的子页面可以直接复用父页面已加载的 JS/CSS 资源,极大减少网络请求。 +* **智能脚本阻塞:** 在资源加载期间自动阻塞页面上的业务脚本,确保核心依赖(如 jQuery, Layui)先于业务代码执行。 +* **虚拟路径映射:** 为内联脚本和远程加载的脚本生成带 `VM_` 前缀的 SourceURL,解决调试时代码定位混乱的问题。 +* **可视化 UI 面板:** 提供原生 JavaScript 编写的加载日志、进度条和错误诊断面板,无需依赖第三方 UI 库。 +* **自动诊断系统:** 内置规则引擎,能够识别常见的错误(如 jQuery 未定义、CORS 错误)并给出修复建议。 + +--- + +## 2. 架构设计 + +系统采用模块化类结构设计,主要分为以下几个核心部分: + +### 2.1 类结构概览 +1. **`ResourceShareManager` (核心管理器)**: 负责资源加载、缓存管理、脚本拦截、跨页面通信协调。 +2. **`ResourceShareUI` (UI 管理器)**: 负责 DOM 元素的渲染(启动页、进度条、日志面板、错误弹窗)。 +3. **`ResourceShareLogger` (日志系统)**: 统一日志输出入口,负责根据配置过滤日志,并分发到 DevTools 控制台和 UI 面板。 +4. **`ResourceShareElement` (Web Components)**: 自定义标签 ``,用于声明页面需要加载的依赖资源。 + +### 2.2 初始化流程 +1. **配置合并**: 脚本加载时,首先执行 `deepMerge`,将用户定义的 `window.RS_CONFIG` 与系统默认配置合并。 +2. **单例检测**: 检查 `window.resourceShareManager` 是否存在,若不存在则实例化。 +3. **环境检测**: 判断当前页面是 `Top Level` (顶级父页面) 还是 `Sub Level` (子页面)。 +4. **组件初始化**: + * 初始化 Logger。 + * 若 `ENABLE_UI` 为 true,初始化 UI 并显示启动屏。 +5. **DOM 扫描**: 监听 `DOMContentLoaded`,扫描页面中的 `` 标签,构建加载队列。 + +--- + +## 3. 核心机制详解 + +### 3.1 资源加载与缓存策略 + +系统采用“源驱动,缓存优先”的策略。 + +* **队列机制**: 扫描到的 `` 标签会被推入 `resourceExecutionQueue`。系统严格按顺序处理队列,确保依赖关系(例如 jQuery 必须在业务插件前加载)。 +* **顶级页面**: + 1. 检查本地内存缓存 (`this.cache`)。 + 2. 若未缓存,发起 `fetch` 请求。 + 3. **重试机制**: 内置请求失败重试逻辑(默认 3 次,间隔 1.5s),提高弱网环境下的成功率。 + 4. **缓存决策**: + * 小于 `POST_MESSAGE_LIMIT` (1MB):存储为字符串文本。 + * 大于阈值:转换为 `Blob URL` 并存储,防止 `postMessage` 数据过大导致报错。 +* **子页面**: + 1. 先通过 `postMessage` 向父页面请求资源 (`resource-request`)。 + 2. 父页面若缓存,直接返回数据(文本或 Blob URL)。 + 3. 父页面若未缓存,子页面回退到直接 `fetch`,并将结果同步给父页面更新缓存。 + +### 3.2 智能脚本阻塞系统 + +为了防止业务脚本在依赖库加载完成前执行,系统劫持了 DOM 操作。 + +1. **拦截目标**: + * 页面初始化时已存在的 ` + + + + + + + + + + +``` + +### 7.2 iframe 子页面自动共享 + +**父页面**: +```html + + + +``` + +**子页面**: +```html + + + +``` + +--- + +## 8. 注意事项与最佳实践 + +1. **同源限制**: 资源共享主要基于 `postMessage`,在严格跨域(Top-Level Domain 不同)场景下,子页面将回退到独立加载模式,但不会报错。 +2. **Blob URL 清理**: 系统在页面卸载 (`beforeunload`) 时会自动清理生成的 Blob URL,防止内存泄漏。 +3. **脚本顺序**: 请严格按照依赖顺序在 HTML 中编写 `` 标签,系统不会自动分析依赖拓扑。 +4. **调试建议**: 开发环境下建议设置 `RS_CONFIG.LOG_LEVEL_DEVTOOLS = 'debug'` 以查看详细的加载链路日志。 \ No newline at end of file diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..13aa856 --- /dev/null +++ b/README.MD @@ -0,0 +1,218 @@ +# ResourceShare.js - 高性能跨资源共享系统 + +**版本:** V1.3.7.5 +**Copyright:** © 2026 GVSDS Team +**License:** MIT License + +## 📖 简介 + +`ResourceShare.js` 是一个专为现代 Web 应用设计的高性能资源管理与共享系统。它通过拦截脚本加载、智能缓存、跨iframe/页面通信以及虚拟源映射技术,解决了复杂 Web 应用中资源加载顺序混乱、重复请求浪费带宽以及内联代码难以调试等问题。 + +**核心优势:** +* **跨域/跨页面资源共享**:顶级页面加载一次资源,同源子页面直接复用,极大减少流量消耗。 +* **精准的加载控制**:使用 `` 标签明确定义加载顺序,确保依赖库(如 jQuery)先于业务代码执行。 +* **智能调试支持**:自动生成带有 `VM_` 前缀的虚拟 SourceURL,让原本混淆或内联的代码在浏览器开发者工具中拥有清晰的文件路径。 +* **可视化管理面板**:内置splash屏、进度条、日志控制台和错误诊断界面,开发体验极佳。 +* **健壮的错误处理**:内置自动重试机制和智能诊断系统(如检测 jQuery 缺失、CORS 错误等)。 + +--- + +## 🚀 快速开始 + +### 1. 引入脚本 + +将 `ResourceShare.js` 文件放入您的项目目录,并在 HTML 中尽可能早地引入它(建议在 `` 中)。 + +```html + + + + + ResourceShare Demo + + + + + ... + + +``` + +### 2. 定义资源加载列表 + +使用自定义的 `` 标签来声明需要加载的资源。系统会严格按照标签出现的顺序进行加载。 + +**示例:** + +```html + + + + + + + +``` + +### 3. 正常编写业务代码 + +除了引入资源的方式改变外,您的业务代码不需要做任何修改。系统会自动拦截 ` +``` + +--- + +## ⚙️ 配置选项 + +`ResourceShare.js` 提供了一个全局配置对象 `RS_CONFIG`。您可以在引入 `ResourceShare.js` **之前** 定义它来覆盖默认设置。 + +```html + + +``` + +### 配置参数详解 + +| 参数名 | 类型 | 默认值 | 说明 | +| :--- | :--- | :--- | :--- | +| **VERSION** | String | '1.3.7.4' | 系统版本号(只读) | +| **ENABLE_UI** | Boolean | `true` | 是否显示内置的 Splash 加载屏、进度条和日志面板。生产环境建议设为 `false`。 | +| **POST_MESSAGE_LIMIT** | Number | 1048576 (1MB) | 使用 postMessage 传输数据的最大阈值。超过此大小将自动使用 Blob URL。 | +| **BLOB_LIMIT** | Number | 1073741824 (1GB) | 单个资源允许的最大大小。 | +| **SCRIPT_TIMEOUT** | Number | 300000 (5分钟) | 资源加载的超时时间,超时后强制释放被阻塞的脚本。 | +| **RETRY.COUNT** | Number | `3` | 网络请求失败时的重试次数。 | +| **RETRY.DELAY** | Number | `1500` | 重试间隔(毫秒)。 | +| **LOG_LEVEL_UI** | String | `'debug'` | 屏幕日志面板的显示级别 (`'debug'`, `'info'`, `'error'`, `'none'`)。 | +| **LOG_LEVEL_DEVTOOLS** | String | `'error'` | 浏览器控制台 的日志级别。 | + +--- + +## 🔧 高级用法 + +### 1. 跨 Iframe 资源共享 + +这是本系统的核心功能之一。当您的页面包含多个同源 iframe 时,只需在父页面(Top Level)加载一次资源,子页面即可直接读取父页面缓存。 + +**父页面:** +```html + + + +``` + +**子页面:** +```html + + + + +``` + +若父页面并未加载 large-library.js,但有一个子页面加载了 large-library.js,第二个子页面再次尝试加载 large-library.js 时即可直接读取父页面缓存。 + +### 2. 虚拟文件名映射 (V1.3.7.4 更新) + +系统会自动为加载的脚本生成 SourceURL,以便在 Chrome DevTools 的 Sources 面板中调试。 + +* **外部资源:** 如果加载 `https://example.com/libs/jquery.min.js`,在 Sources 中将显示为 `https://example.com/libs/VM_jquery.min.js`。这有助于区分这是由 ResourceShare 接管加载的文件。 +* **内联脚本:** 如果是页面内直接执行的脚本,将被映射为 `./RS_VM/VM_pageName_index_randomStr.js`。 + +### 3. 禁用特定脚本的接管 + +如果您希望某个脚本不被 ResourceShare 阻塞(即希望它立即执行),可以添加 `DisableRS` 属性。 + +```html + + +``` + +### 4. 错误诊断系统 + +当发生严重错误(如 jQuery 未定义)导致加载停止时,系统会自动弹出一个诊断模态框。该模态框会根据错误堆栈提供解决建议(例如:“脚本依赖 jQuery,但似乎未加载...”)。 + +--- + +## 🐛 调试与日志 + +### 屏幕日志面板 +默认情况下,页面左下角会出现一个悬浮面板,显示资源加载的实时日志。 +* **蓝色:** 普通信息 / 请求 +* **绿色:** 加载成功 / 缓存命中 +* **黄色:** 警告 / 重试中 +* **红色:** 错误 / 加载失败 + +### 控制台日志 +在浏览器控制台中,日志以彩色前缀输出,方便过滤: +* `[INFO]` +* `[SUCCESS]` +* `[WARNING]` +* `[ERROR]` +* `[CACHE]` - 表示命中了父页面缓存或本地缓存 + +--- + +## 🏗️ 工作原理 + +1. **初始化**: 脚本加载后,立即覆盖原生的 `appendChild` 和 `insertBefore` 方法,拦截所有 ` + + \ No newline at end of file diff --git a/vbuild.py b/vbuild.py new file mode 100644 index 0000000..243a0d3 --- /dev/null +++ b/vbuild.py @@ -0,0 +1,46 @@ +# VBuild +import json +import sys + +def main(): + if len(sys.argv) < 2: + print("Error: No config file path provided") + sys.exit(1) + cfg_path = sys.argv[1] + print(f"Reading config file: {cfg_path}") + try: + with open(cfg_path, 'r', encoding='utf-8') as f: + cfg = json.load(f) + except FileNotFoundError: + print(f"Error: Config file {cfg_path} does not exist") + sys.exit(1) + except json.JSONDecodeError: + print(f"Error: {cfg_path} is not a valid JSON file") + sys.exit(1) + project = cfg['project'] + order = cfg['order'] + output = cfg['output'] + + content = [] + total_files = len(order) + print(f"Starting JS file concatenation, {total_files} files to process") + for idx, path in enumerate(order, 1): + file_path = f"{project}/{path}.js" + print(f"[{idx}/{total_files}] Reading file: {file_path}") + try: + with open(file_path, 'r', encoding='utf-8') as f: + content.append(f.read()) + except FileNotFoundError: + print(f"Error: File {file_path} not found, terminating concatenation") + sys.exit(1) + print(f"All files read successfully, writing to output file: {output}") + combined_content = '\n'.join(content) + + # 写入未压缩的文件 + with open(output, 'w', encoding='utf-8') as f: + f.write(combined_content) + total_size = len(combined_content) / 1024 + print(f"Concatenation completed! Output file size: {total_size:.2f} KB") + +if __name__ == "__main__": + main() \ No newline at end of file