目標:モジュールの名前が開発ツールで識別されたとしても、コンソール経由で正常にインポートできないなど、一部のセキュリティまたは定義されたユーザー ロール要件を条件とする Javascript モジュールの動的読み込みをサポートすること。
JavaScript モジュールは、Firebase (#AskFirebase) などのクラウド ストレージ サービスに簡単にアップロードできます。コードfirebase.functions().httpsCallable("ghost");
は、カスタム クレームまたは同様のテストの存在に基づいて、Firebase Cloud Function を使用して条件付きで取得できます。
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
});