目标:支持根据某些安全性或定义的用户角色要求动态加载 Javascript 模块,这样即使在开发工具中识别了模块的名称,也无法通过控制台成功导入。
JavaScript 模块可以轻松上传到 Firebase (#AskFirebase) 等云存储服务,并且可以firebase.functions().httpsCallable("ghost");
根据自定义声明或类似测试的存在使用 Firebase 云函数有条件地检索代码。
export const ghost = functions.https.onCall(async (data, context) => {
if (! context.auth.token.restrictedAccess === true) {
throw new functions.https.HttpsError('failed-precondition', 'The function must be called while authenticated.');
}
const storage = new Storage();
const bucketName = 'bucket-name.appspot.com';
const srcFilename = 'RestrictedChunk.chunk.js';
// Downloads the file
const response = await storage
.bucket(bucketName)
.file(srcFilename).download();
const code = String.fromCharCode.apply(String, response[0])
return {source: code};
})
最后,我想做的事...
...就是把一个 webpack 的 React 组件放到云端,经过服务器端安全检查后有条件的下载到客户端,然后import()
放到用户的客户端环境中渲染。
将 Javascript 存储在云中并有条件地下载到客户端很容易。一旦我在客户端中获得了 webpack 的代码,我就可以像使用Function(downloadedRestrictedComponent)
一样将它添加到用户的环境中,import('./RestrictedComponent')
但我不知道如何从组件中获取默认导出,以便我可以实际渲染事情。
import(pathToComponent)
返回加载的模块,据我所知,没有传递import()
字符串或流的选项,只有模块的路径。并将Function(downloadedComponent)
下载的代码添加到客户端环境中,但我不知道如何访问模块的导出以呈现动态加载的 React 组件。
有没有办法从下载的流中动态导入 Javascript 模块?
编辑添加:感谢您的回复。不熟悉 Blob 和URL.createObjectURL
. 知道为什么找不到吗?
const ghost = firebase.functions().httpsCallable("ghost");
const LoadableRestricted = Loadable({
// loader: () => import(/* webpackChunkName: "Restricted" */ "./Restricted"),
loader: async () => {
const ghostContents = await ghost();
console.log(ghostContents);
const myBlob = new Blob([ghostContents.data.source], {
type: "application/javascript"
});
console.log(myBlob);
const myURL = URL.createObjectURL(myBlob);
console.log(myURL);
return import(myURL);
},
render(loaded, props) {
console.log(loaded);
let Component = loaded.Restricted;
return <Component {...props} />;
},
loading: Loading,
delay: 2000
});