@yangyongtao/gaea 1.1.30 → 1.1.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.1.32] - 2026-09-09
4
+
5
+ ### Changed
6
+ - 引擎大文件(`Gaea.pck` / `Gaea.wasm`)改为从外部资源服务器加载:默认 `executable` 指向 `http://172.20.176.100:7072/gaea/Gaea`。可通过宿主站点 `config.js` 设置 `window.__GAEA_ASSETS_URL__`(运行时覆盖,换地址无需重新打包),或构建环境变量 `VITE_GAEA_EXECUTABLE` 覆盖
7
+ - Vite 插件 `closeBundle` 默认不再把 `Gaea.pck` / `Gaea.wasm` 复制到输出目录(引擎从外部服务器加载,dist 体积大幅减小);可用 `gaeaVitePlugin({ skipEngineFiles: [...] })` 覆盖
8
+ - 屏幕图标(`.gaea-iconGif` / `.gaea-iconscreen` / `.gaea-locationLineStyle`)z-index 统一改为 `11`
9
+
10
+ ## [1.1.31] - 2026-09-09
11
+
12
+ ### Added
13
+ - Vite 插件 `transformIndexHtml` 自动给外部跨域 `<script src="http(s)://...">` 补 `crossorigin="anonymous"`:解决跨域隔离(COEP: require-corp)下第三方脚本因缺少 CORP 响应头被拦截(`NotSameOriginAfterDefaultedToSameOriginByCoep`)并阻塞页面加载的问题(如 `live.dcyun.com` 的 DcVideo.js 视频库)
14
+ - 注入前置脚本 hook `Node.prototype.appendChild/insertBefore`:第三方脚本内部 `document.createElement('script')` 动态加载的跨域子脚本自动补 `crossorigin`(DcVideo.js 内部的 jquery / DCHls / EasyWasmPlayer / ezuikit 等均可正常加载)
15
+ - 新增 `gaeaVitePlugin({ skipExternalScripts: [...] })` 配置:构建期移除匹配的外部脚本(字符串子串或正则),用于跳过跨域隔离下无法正常工作且当前未使用的第三方脚本
16
+
3
17
  ## [1.1.30] - 2026-09-09
4
18
 
5
19
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yangyongtao/gaea",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "description": "Gaea 3D visualization component library - Vue 3 components based on Godot WASM engine. Includes WMTS layer loading, camera view control, Vite plugin auto-injection, etc.",
5
5
  "type": "module",
6
6
  "main": "src/index.cjs",
@@ -56,7 +56,7 @@ import Gaea from '../public/index.js';
56
56
  #gaea-layertree-btn:hover { background: rgba(0,0,0,0.7); }
57
57
  /* 屏幕图标样式(对齐 ht_3dview) */
58
58
  .gaea-locationLineStyle {
59
- position: absolute; overflow: hidden; z-index: 99; pointer-events: auto;
59
+ position: absolute; overflow: hidden; z-index: 11; pointer-events: auto;
60
60
  user-select: none; -webkit-user-select: none;
61
61
  }
62
62
  .gaea-locationLineStyle .text-wrapper {
@@ -75,7 +75,7 @@ import Gaea from '../public/index.js';
75
75
  }
76
76
  .gaea-iconscreen {
77
77
  position: absolute; overflow: hidden; width: 169px; height: 55px;
78
- user-select: none; -webkit-user-select: none; z-index: 99; pointer-events: auto;
78
+ user-select: none; -webkit-user-select: none; z-index: 11; pointer-events: auto;
79
79
  }
80
80
  .gaea-iconscreen img {
81
81
  position: absolute; width: 100%; height: 100%;
@@ -92,7 +92,7 @@ import Gaea from '../public/index.js';
92
92
  }
93
93
  .gaea-iconGif {
94
94
  position: absolute; overflow: hidden; width: 48px; height: 48px;
95
- user-select: none; -webkit-user-select: none; z-index: 999; pointer-events: auto;
95
+ user-select: none; -webkit-user-select: none; z-index: 11; pointer-events: auto;
96
96
  }
97
97
  .gaea-iconGif img {
98
98
  width: 100%; height: 100%; object-fit: contain; display: block;
@@ -119,11 +119,33 @@ function hideLoading() {
119
119
 
120
120
  // ==================== 配置 ====================
121
121
 
122
+ /** 默认引擎资源服务器地址(Gaea.pck / Gaea.wasm 等大文件),可在运行时/环境变量覆盖 */
123
+ const DEFAULT_ENGINE_ASSETS_URL = 'http://172.20.176.100:7072/gaea/Gaea';
124
+
125
+ /**
126
+ * 解析默认 executable:
127
+ * 优先级:运行时全局变量 window.__GAEA_ASSETS_URL__(宿主站点 config.js 可设置,
128
+ * 换地址无需重新打包)> 构建环境变量 VITE_GAEA_EXECUTABLE > 内置默认地址。
129
+ */
130
+ function resolveDefaultExecutable() {
131
+ if (typeof window !== 'undefined' && window.__GAEA_ASSETS_URL__) {
132
+ return window.__GAEA_ASSETS_URL__;
133
+ }
134
+ try {
135
+ if (import.meta.env && import.meta.env.VITE_GAEA_EXECUTABLE) {
136
+ return import.meta.env.VITE_GAEA_EXECUTABLE;
137
+ }
138
+ } catch (e) {
139
+ /* 非 vite 环境忽略 */
140
+ }
141
+ return DEFAULT_ENGINE_ASSETS_URL;
142
+ }
143
+
122
144
  const defaultConfig = {
123
145
  serveUrl: '',
124
146
  serveLocal: '',
125
147
  // Engine 配置
126
- executable: '/Gaea',
148
+ executable: resolveDefaultExecutable(),
127
149
  fileSizes: { 'Gaea.pck': 450751936, 'Gaea.wasm': 16580215 },
128
150
  canvasResizePolicy: 2,
129
151
  experimentalVK: false,
@@ -55,7 +55,42 @@ const COEP_HEADERS = {
55
55
  'Cross-Origin-Embedder-Policy': 'require-corp',
56
56
  };
57
57
 
58
- export default function gaeaVitePlugin() {
58
+ /**
59
+ * 给外部跨域 <script src="http(s)://..."> 自动补 crossorigin="anonymous"。
60
+ *
61
+ * 背景:Gaea 引擎要求跨域隔离(COEP: require-corp)。在 COEP 下,普通 no-cors
62
+ * 跨域脚本因缺少 Cross-Origin-Resource-Policy 响应头会被浏览器拦截(
63
+ * NotSameOriginAfterDefaultedToSameOriginByCoep),且同步脚本会挂起阻塞页面加载。
64
+ * 补上 crossorigin 后改为 CORS 模式加载,只要服务器返回 Access-Control-Allow-Origin
65
+ * 即可通过 COEP 检查。
66
+ */
67
+ function addCrossOriginToExternalScripts(html) {
68
+ return html.replace(/<script\b([^>]*?)>/g, (match, attrs) => {
69
+ if (!/\bsrc="https?:\/\//.test(attrs)) return match;
70
+ if (/\bcrossorigin(=|[\s>])/i.test(attrs)) return match;
71
+ return match.replace(/^<script/, '<script crossorigin="anonymous"');
72
+ });
73
+ }
74
+
75
+ /**
76
+ * 移除 HTML 中匹配的外部 <script src="http(s)://..."> 标签。
77
+ * 用于跳过某些在跨域隔离(COEP)下无法正常工作、且当前项目并未使用的第三方脚本
78
+ * (如第三方视频播放库),避免它们拖慢首屏、产生无意义报错。
79
+ * @param {string} html
80
+ * @param {Array<string|RegExp>} rules 匹配规则:字符串按子串匹配 src,正则直接 test
81
+ */
82
+ function skipExternalScriptTags(html, rules) {
83
+ if (!rules?.length) return html;
84
+ return html.replace(/<script\b([^>]*?src="(https?:\/\/[^"]+)"[^>]*)>[\s\S]*?<\/script>/g, (match, attrs, src) => {
85
+ const hit = rules.some((rule) => (rule instanceof RegExp ? rule.test(src) : String(src).includes(rule)));
86
+ return hit ? '' : match;
87
+ });
88
+ }
89
+
90
+ export default function gaeaVitePlugin(options = {}) {
91
+ const skipScripts = options.skipExternalScripts || [];
92
+ // 构建时不复制到输出目录的引擎大文件(引擎默认从外部资源服务器加载,可配置 skipEngineFiles 覆盖)
93
+ const skipEngineFiles = options.skipEngineFiles || ['Gaea.pck', 'Gaea.wasm'];
59
94
  let resolvedOutDir = '';
60
95
 
61
96
  return {
@@ -155,6 +190,7 @@ export default function gaeaVitePlugin() {
155
190
 
156
191
  fs.mkdirSync(outRoot, { recursive: true });
157
192
  for (const name of BUILD_TOP_FILES) {
193
+ if (skipEngineFiles.includes(name)) continue;
158
194
  const src = path.join(pkgPublic, name);
159
195
  if (fs.existsSync(src)) copyFile(src, path.join(outRoot, name));
160
196
  }
@@ -166,6 +202,12 @@ export default function gaeaVitePlugin() {
166
202
  },
167
203
 
168
204
  transformIndexHtml(html) {
205
+ // 跳过配置中匹配的外部脚本(如项目未使用的第三方视频库)
206
+ html = skipExternalScriptTags(html, skipScripts);
207
+
208
+ // 外部跨域脚本自动补 crossorigin(绕过 COEP 拦截,避免阻塞页面)
209
+ html = addCrossOriginToExternalScripts(html);
210
+
169
211
  // 自动注入 Gaea.js(消费者无需在 HTML 中手动写 <script src="/Gaea.js">)
170
212
  if (!html.includes('/Gaea.js')) {
171
213
  html = html.replace(
@@ -174,10 +216,31 @@ export default function gaeaVitePlugin() {
174
216
  );
175
217
  }
176
218
 
177
- // 跨域隔离检测
219
+ // 跨域隔离检测 + 动态跨域脚本自动补 crossorigin(必须在 body 脚本执行前注入到 head)
178
220
  html = html.replace(
179
221
  '</head>',
180
222
  `<script>
223
+ // 动态创建的跨域 <script> 自动补 crossorigin="anonymous":
224
+ // 跨域隔离(COEP)下,第三方脚本内部 document.createElement('script') 动态加载的子脚本
225
+ // 若不带 crossorigin 会被拦截(NotSameOriginAfterDefaultedToSameOriginByCoep)并阻塞页面。
226
+ (function () {
227
+ if (!window.crossOriginIsolated) return;
228
+ function fix(el) {
229
+ if (el && el.tagName === 'SCRIPT' && el.src && !el.crossOrigin) {
230
+ try {
231
+ if (new URL(el.src, location.href).origin !== location.origin) {
232
+ el.crossOrigin = 'anonymous';
233
+ }
234
+ } catch (e) {}
235
+ }
236
+ }
237
+ var oa = Node.prototype.appendChild;
238
+ var oi = Node.prototype.insertBefore;
239
+ Node.prototype.appendChild = function (el) { fix(el); return oa.call(this, el); };
240
+ Node.prototype.insertBefore = function (el, ref) { fix(el); return oi.call(this, el, ref); };
241
+ })();
242
+ </script>
243
+ <script>
181
244
  if (!window.crossOriginIsolated) {
182
245
  if (!location.search.includes('gaea_isolated=1')) {
183
246
  location.replace(location.href.split('?')[0] + '?gaea_isolated=1');