Skip to content

等待条件配置

injectsWaitConditionexternalsWaitCondition 允许您配置代码执行前的等待条件,确保依赖的资源已经准备就绪。

功能介绍

在某些场景下,网站可能有异步加载的模块或资源,如果直接执行 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 代码执行前的等待条件
      injectsWaitCondition: {
        condition: `!!window["my-extension_externals"]`,
        timeoutSeconds: 5,
        checkInterval: 50,
      },
    }),
  ],
});
// 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 代码执行前的等待条件
      injectsWaitCondition: {
        condition: `!!window["my-extension_externals"]`,
        timeoutSeconds: 5,
        checkInterval: 50,
      },
    }),
  ],
});

配置参数

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 代码执行前的等待条件
      injectsWaitCondition: {
        condition: `!!window["my-extension_externals"]`,
        timeoutSeconds: 5,
        checkInterval: 50,
      },
    }),
  ],
});
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 代码执行前的等待条件
      injectsWaitCondition: {
        condition: `!!window["my-extension_externals"]`,
        timeoutSeconds: 5,
        checkInterval: 50,
      },
    }),
  ],
});

使用场景

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. 确保 externals 在 injects 之前加载

injects 代码通常依赖 externals 中的库,可以配置等待条件确保加载顺序:

typescript
injectsWaitCondition: {
  condition: `!!window["${extensionId}_externals"]`,
  timeoutSeconds: 10,
  checkInterval: 100
}
injectsWaitCondition: {
  condition: `!!window["${extensionId}_externals"]`,
  timeoutSeconds: 10,
  checkInterval: 100
}

3. 等待 DOM 特定状态

等待页面特定元素或状态就绪:

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
}

生成的代码示例

配置等待条件后,生成的代码会被包装在等待函数中:

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 内容
    })();
  });
})();

注意事项

  1. 条件表达式:必须是可以被 eval 执行的 JavaScript 表达式,返回布尔值
  2. 超时处理:超时后代码不会执行,会在控制台输出错误信息
  3. 性能影响:检查间隔不宜太小,建议 50-500ms 之间
  4. 错误处理:条件表达式执行出错会被捕获,视为条件未满足

Powered by Vitepress