fallback to handle plugins as commonjs if dynamic import fails

Summary: This should help us to make flipper more reliable and avoid failing loading plugins if they are loaded from cache(old ones)

Reviewed By: lblasa

Differential Revision: D50081726

fbshipit-source-id: edef9999ad44660331153a082e15c6f3f5de9b05
This commit is contained in:
Anton Kastritskiy
2023-10-10 03:37:21 -07:00
committed by Facebook GitHub Bot
parent 76cb3190fd
commit 5a5a509d4d

View File

@@ -185,11 +185,48 @@ export function initializeRenderHost(
// Typescript transpiles dynamic import calls to `require` in the browser bundle
// We want to explicilty use dynamic import here
const importStr = `import('/${staticPath}?ts=${Date.now()}')`;
const nonEsmPluginSymbol = Symbol.for('nonEsmPlugin');
const source = await flipperServer.exec('plugin-source', path);
// eslint-disable-next-line no-eval
const importRes = await eval(importStr);
const importRes = await eval(importStr).catch((e: unknown) => {
if (
e instanceof ReferenceError &&
e.message.includes('module is not defined')
) {
return nonEsmPluginSymbol;
} else {
throw e;
}
});
return {plugin: importRes, css: source.css};
if (importRes !== nonEsmPluginSymbol) {
return {plugin: importRes, css: source.css};
}
// handle commonjs plugin
else {
console.log(
'[browser-ui][requirePlugin] handle plugin js as CJS',
// only log path inside of flipper project
path.split('/desktop/', 2).pop(),
);
let js = source.js;
// append source url (to make sure a file entry shows up in the debugger)
js += `\n//# sourceURL=file://${path}`;
if (isProduction()) {
// and source map url (to get source code if available)
js += `\n//# sourceMappingURL=file://${path}.map`;
}
// Plugins are compiled as typical CJS modules, referring to the global
// 'module', which we'll make available by loading the source into a closure that captures 'module'.
// Note that we use 'eval', and not 'new Function', because the latter will cause the source maps
// to be off by two lines (as the function declaration uses two lines in the generated source)
// eslint-disable-next-line no-eval
const cjsLoader = eval('(module) => {' + js + '\n}');
const theModule = {exports: {}};
cjsLoader(theModule);
return {plugin: theModule.exports, css: source.css};
}
},
getStaticResourceUrl(path): string {
// the 'static' folder is mounted as static middleware in Express at the root