7

目标:支持根据某些安全性或定义的用户角色要求动态加载 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
});

在此处输入图像描述

4

2 回答 2

4

将模块文件/流的内容读入 BLOB。用于URL.createObjectURL()创建 BLOB 的动态 URL。现在import按照上面的建议使用:

import(myBlobURL).then(module=>{/*doSomethingWithModule*/});
于 2018-10-19T15:48:06.760 回答
-2

您可以尝试使用React.lazy

import React, {lazy, Suspense} from 'react';

const Example = () => {

    const [userAuthenticated, setUserAuthenticated] = useState(true);

    if (userAthenticated) {

        const RestrictedComponent = lazy(() => import('./RestrictedComponent'));

        return (
            <div>
                <Suspense fallback={<div><p>Loading...</p></div>}>
                    <RestrictedComponent />
                </Suspense>
            </div>
        )
    }

    return (
        <div>
            <h1>404</h1>
            <p>Restricted</p>
        </div>
    );

}

export default Example;
于 2019-11-05T20:03:27.483 回答