等待条件配置
injectsWaitCondition 和 externalsWaitCondition 用于配置代码执行前的等待条件,让依赖的资源准备就绪后再执行代码。
Injects 内置等待条件
injects 代码会自动等待 externals 加载完成后再执行,无需手动配置。内置等待条件为:
javascript
!!window["${extensionId}"] && !!window["${extensionId}_externals"]!!window["${extensionId}"] && !!window["${extensionId}_externals"]也就是说,即使你不配置 injectsWaitCondition,injects 代码也会等 externals 中的库(React、antd 等)加载完成后才执行,避免加载顺序问题导致的运行时错误。
内置条件默认使用 30 秒超时、50ms 检查间隔。
TIP
如果你同时配置了 injectsWaitCondition,你的条件会与内置条件自动合并(AND 关系),最终条件为:(内置条件) && (你的条件),超时和间隔使用你配置的值。
功能介绍
有些网站的模块或资源是异步加载的,直接执行 externals 或 injects 代码可能因为依赖还没加载好而报错。等待条件可以让代码在指定条件满足后再执行。
配置
typescript
// vite.config.ts
import { defineConfig } from "vite";
export default defineConfig({
// ...
plugins: [
// ...
ViteWebExtKits({
// externals 代码执行前的等待条件
externalsWaitCondition: {
condition: "!!window.MyApp && !!window.MyApp.ready",
timeoutSeconds: 10,
checkInterval: 100,
},
// injects 代码执行前的附加等待条件(会与内置 externals 就绪检查自动合并)
injectsWaitCondition: {
condition: "!!document.querySelector('#app')",
timeoutSeconds: 10,
checkInterval: 100,
},
}),
],
});// vite.config.ts
import { defineConfig } from "vite";
export default defineConfig({
// ...
plugins: [
// ...
ViteWebExtKits({
// externals 代码执行前的等待条件
externalsWaitCondition: {
condition: "!!window.MyApp && !!window.MyApp.ready",
timeoutSeconds: 10,
checkInterval: 100,
},
// injects 代码执行前的附加等待条件(会与内置 externals 就绪检查自动合并)
injectsWaitCondition: {
condition: "!!document.querySelector('#app')",
timeoutSeconds: 10,
checkInterval: 100,
},
}),
],
});配置参数
typescript
type WaitCondition = {
// 条件表达式(字符串形式)
condition: string;
// 超时时间(秒)
timeoutSeconds: number;
// 检查间隔(毫秒)
checkInterval: number;
};type WaitCondition = {
// 条件表达式(字符串形式)
condition: string;
// 超时时间(秒)
timeoutSeconds: number;
// 检查间隔(毫秒)
checkInterval: number;
};使用示例
typescript
import { ViteWebExtKits } from "@webextkits/vite-plugins";
export default defineConfig({
plugins: [
ViteWebExtKits({
extensionId: "my-extension",
// externals 代码执行前的等待条件
externalsWaitCondition: {
condition: "!!window.MyApp && !!window.MyApp.ready",
timeoutSeconds: 10,
checkInterval: 100,
},
// injects 附加等待条件(内置的 externals 就绪检查无需手动配)
injectsWaitCondition: {
condition: "!!document.querySelector('#app')",
timeoutSeconds: 10,
checkInterval: 100,
},
}),
],
});import { ViteWebExtKits } from "@webextkits/vite-plugins";
export default defineConfig({
plugins: [
ViteWebExtKits({
extensionId: "my-extension",
// externals 代码执行前的等待条件
externalsWaitCondition: {
condition: "!!window.MyApp && !!window.MyApp.ready",
timeoutSeconds: 10,
checkInterval: 100,
},
// injects 附加等待条件(内置的 externals 就绪检查无需手动配)
injectsWaitCondition: {
condition: "!!document.querySelector('#app')",
timeoutSeconds: 10,
checkInterval: 100,
},
}),
],
});使用场景
1. 等待网站模块加载完成
有些网站(如 Facebook)的模块是异步加载的,需要等特定模块加载完成:
typescript
externalsWaitCondition: {
condition: "!!window.require && !!window.require('react')",
timeoutSeconds: 15,
checkInterval: 200
}externalsWaitCondition: {
condition: "!!window.require && !!window.require('react')",
timeoutSeconds: 15,
checkInterval: 200
}2. 等待 DOM 特定状态
injects 已经会自动等待 externals 就绪。如果还需要等待页面达到特定状态,可以配置 injectsWaitCondition:
typescript
injectsWaitCondition: {
condition: "!!document.querySelector('#app') && !!window.APP_INITIALIZED",
timeoutSeconds: 30,
checkInterval: 500
}injectsWaitCondition: {
condition: "!!document.querySelector('#app') && !!window.APP_INITIALIZED",
timeoutSeconds: 30,
checkInterval: 500
}最终生效的条件为:(!!window["my-extension"] && !!window["my-extension_externals"]) && (!!document.querySelector('#app') && !!window.APP_INITIALIZED)
生成的代码示例
配置等待条件后,生成的代码会被包装在等待函数中:
javascript
// 生成的 externals.js 示例
(function () {
var startTime = Date.now();
var timeoutMs = 10000; // 10秒
var checkInterval = 100; // 100毫秒
function checkCondition() {
try {
return (function () {
return !!window.MyApp && !!window.MyApp.ready;
})();
} catch (e) {
return false;
}
}
function waitingForCondition(callback) {
function check() {
if (Date.now() - startTime > timeoutMs) {
console.error(
'[externals] 等待条件超时: "!!window.MyApp && !!window.MyApp.ready"'
);
console.error("[externals] 超过 10 秒未满足条件,代码未执行");
return; // 超时后不执行代码
}
if (checkCondition()) {
callback();
} else {
setTimeout(check, checkInterval);
}
}
check();
}
waitingForCondition(function () {
// 原始的 externals 代码在这里执行
(function () {
// ... externals 内容
})();
});
})();// 生成的 externals.js 示例
(function () {
var startTime = Date.now();
var timeoutMs = 10000; // 10秒
var checkInterval = 100; // 100毫秒
function checkCondition() {
try {
return (function () {
return !!window.MyApp && !!window.MyApp.ready;
})();
} catch (e) {
return false;
}
}
function waitingForCondition(callback) {
function check() {
if (Date.now() - startTime > timeoutMs) {
console.error(
'[externals] 等待条件超时: "!!window.MyApp && !!window.MyApp.ready"'
);
console.error("[externals] 超过 10 秒未满足条件,代码未执行");
return; // 超时后不执行代码
}
if (checkCondition()) {
callback();
} else {
setTimeout(check, checkInterval);
}
}
check();
}
waitingForCondition(function () {
// 原始的 externals 代码在这里执行
(function () {
// ... externals 内容
})();
});
})();注意事项
- 条件表达式:必须是可以被
eval执行的 JavaScript 表达式,返回布尔值 - 超时处理:超时后代码不会执行,会在控制台输出错误信息
- 性能影响:检查间隔不要太小,建议 50-500ms
- 错误处理:条件表达式执行出错时会被捕获,视为条件未满足
Webextkits Docs