Skip to content

Commit 7986851

Browse files
committed
feat: 插件懒加载
1 parent 2318703 commit 7986851

2 files changed

Lines changed: 56 additions & 25 deletions

File tree

src/core/pluginManager/index.ts

Lines changed: 55 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,23 @@ import { ToastAndroid } from "react-native";
2121
import { copyFile, readDir, readFile, unlink, writeFile } from "react-native-fs";
2222
import { devLog, errorLog, trace } from "../../utils/log";
2323
import pluginMeta from "./meta";
24-
import { ILazyProps, localFilePlugin, Plugin, PluginState } from "./plugin";
24+
import { localFilePlugin, Plugin, PluginState } from "./plugin";
2525
import i18n from "../i18n";
2626
import getOrCreateMMKV from "@/utils/getOrCreateMMKV";
2727
import { safeParse } from "@/utils/jsonUtil";
2828
import { IInjectable } from "@/types/infra";
2929
import { IAppConfig } from "@/types/core/config";
30+
import delay from "@/utils/delay";
3031

3132
const pluginsAtom = atom<Plugin[]>([]);
32-
const pluginStore = getOrCreateMMKV("plugin.cache");
33+
const pluginCacheStore = getOrCreateMMKV("plugin.cache");
3334

3435
const ee = new EventEmitter<{
3536
"order-updated": () => void;
3637
"enabled-updated": (pluginName: string, enabled: boolean) => void;
3738
}>();
3839

3940
class PluginManager implements IPluginManager, IInjectable {
40-
4141
private appConfigService!: IAppConfig;
4242

4343
injectDependencies(config: IAppConfig): void {
@@ -59,23 +59,32 @@ class PluginManager implements IPluginManager, IInjectable {
5959
private setPlugins(plugins: Plugin[]) {
6060
getDefaultStore().set(pluginsAtom, plugins);
6161

62-
const cache: Record<string, ILazyProps> = {};
63-
plugins.forEach(it => {
64-
if (it.path) {
65-
cache[it.path] = {
66-
name: it.name,
67-
hash: it.hash,
68-
path: it.path,
69-
instance: it.instance,
70-
supportedMethods: [...it.supportedMethods],
71-
};
62+
// 清理缓存中已卸载的插件
63+
const cachedKeys = pluginCacheStore.getAllKeys();
64+
cachedKeys.forEach(key => {
65+
if (!plugins.find(it => it.path === key)) {
66+
pluginCacheStore.delete(key);
7267
}
7368
});
7469

75-
pluginStore.set(
76-
"plugins",
77-
JSON.stringify(cache),
78-
);
70+
plugins.forEach(it => {
71+
this.updatePluginCache(it);
72+
});
73+
}
74+
75+
private updatePluginCache(plugin: Plugin) {
76+
if (plugin.path && plugin.state === PluginState.Mounted) {
77+
pluginCacheStore.set(
78+
plugin.path,
79+
JSON.stringify({
80+
name: plugin.name,
81+
hash: plugin.hash,
82+
path: plugin.path,
83+
instance: plugin.instance,
84+
supportedMethods: [...plugin.supportedMethods],
85+
}),
86+
);
87+
}
7988
}
8089

8190
/**
@@ -90,8 +99,6 @@ class PluginManager implements IPluginManager, IInjectable {
9099
const pluginsFileItems = await readDir(pathConst.pluginPath);
91100
const allPlugins: Array<Plugin> = [];
92101

93-
const cachePlugins = (safeParse(pluginStore.getString("plugins")) ??
94-
{}) as Record<string, ILazyProps>;
95102

96103
for (let i = 0; i < pluginsFileItems.length; ++i) {
97104
const pluginFileItem = pluginsFileItems[i];
@@ -104,12 +111,21 @@ class PluginManager implements IPluginManager, IInjectable {
104111
// 如果存在缓存信息
105112
let plugin: Plugin;
106113
let isLazyLoad = false;
107-
if (this.appConfigService.getConfig("basic.lazyLoadPlugin") && cachePlugins[pluginFileItem.path]) {
108-
const lazyProps = cachePlugins[pluginFileItem.path];
114+
if (
115+
this.appConfigService.getConfig(
116+
"basic.lazyLoadPlugin",
117+
) &&
118+
pluginCacheStore.contains(pluginFileItem.path)
119+
) {
109120
isLazyLoad = true;
121+
const lazyProps = safeParse(pluginCacheStore.getString(pluginFileItem.path));
110122
lazyProps.loadFuncCode = async () =>
111123
await readFile(pluginFileItem.path, "utf8");
112-
plugin = new Plugin(null, pluginFileItem.path, lazyProps);
124+
plugin = new Plugin(
125+
null,
126+
pluginFileItem.path,
127+
lazyProps,
128+
);
113129
} else {
114130
const funcCode = await readFile(
115131
pluginFileItem.path,
@@ -125,12 +141,25 @@ class PluginManager implements IPluginManager, IInjectable {
125141
// 重复插件,直接忽略
126142
continue;
127143
}
128-
if ((plugin.state === PluginState.Mounted) || isLazyLoad) {
144+
if (plugin.state === PluginState.Mounted || isLazyLoad) {
129145
allPlugins.push(plugin);
130146
}
131147
}
132148
}
149+
133150
this.setPlugins(allPlugins);
151+
// 异步初始化插件
152+
153+
delay(10_000, true).then(async () => {
154+
for (let i = 0; i < allPlugins.length; ++i) {
155+
const plugin = allPlugins[i];
156+
157+
if (plugin.state === PluginState.Initializing) {
158+
await plugin.ensureMounted();
159+
this.updatePluginCache(plugin);
160+
}
161+
}
162+
});
134163
} catch (e: any) {
135164
ToastAndroid.show(
136165
`插件初始化失败:${e?.message ?? e}`,
@@ -352,7 +381,6 @@ class PluginManager implements IPluginManager, IInjectable {
352381
async uninstallPlugin(hash: string) {
353382
let plugins = [...this.getPlugins()];
354383
const targetIndex = plugins.findIndex(_ => _.hash === hash);
355-
console.log("卸载", targetIndex);
356384
if (targetIndex !== -1) {
357385
try {
358386
const pluginName = plugins[targetIndex].name;
@@ -508,7 +536,9 @@ class PluginManager implements IPluginManager, IInjectable {
508536
*/
509537
getPluginsWithAbility(ability: keyof IPlugin.IPluginInstanceMethods) {
510538
return this.getPlugins().filter(
511-
it => pluginMeta.isPluginEnabled(it.name) && it.supportedMethods.has(ability),
539+
it =>
540+
pluginMeta.isPluginEnabled(it.name) &&
541+
it.supportedMethods.has(ability),
512542
);
513543
}
514544

src/core/pluginManager/plugin.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,7 @@ export class Plugin {
889889

890890
async ensureMounted() {
891891
if ((this.state === PluginState.Initializing) && this.lazyProps) {
892+
this.state = PluginState.Loading;
892893
// 懒加载
893894
const loadFuncCode = this.lazyProps.loadFuncCode ?? (() => "");
894895
try {

0 commit comments

Comments
 (0)