在动态加载的es模块中使用React

时间:2018-07-20 13:23:13

标签: javascript reactjs typescript webpack ecmascript-6

我一直在加载本机ES模块,该模块可以简化为src/test.tsx

export default class Test {
    constructor() {
        console.log('loaded');
    }
}

我可以在浏览器中加载它并对其进行初始化,就像这样:

import('http://127.0.0.1:8085/').then(m => { 
  const instance = new m.default();
});

但是..如果我想添加任何外部依赖,在这种情况下是React,我似乎无法弄清楚如何以es6为目标,以及如何将React与tsc捆绑在一起。因此,我的dist文件包含import React from 'react';,浏览器不知道如何解决该问题,并生成:

(index):1 Uncaught (in promise) TypeError: Failed to resolve module specifier "react". Relative references must start with either "/", "./", or "../".

我的tsconfig如下:

{
    "compilerOptions": {
        "baseUrl": ".",
        "rootDir": "src",
        "module": "es6",
        "target": "es2015",
        "lib": ["es6", "dom"],
        "declaration": true,
        "jsx": "react",
        "outDir": "dist",
        "strict": true,
        "noImplicitAny": false,
        "allowSyntheticDefaultImports": true,
        "esModuleInterop": true,
        "experimentalDecorators": true,
        "moduleResolution": "node",
        "skipLibCheck": true
    },
    "include": ["./src/**/*"]
}

运行节点v9.5.0,打字稿v2.9.2

我还尝试使用webpack捆绑所有内容,但无法弄清楚如何以这种方式生成可动态导入的模块

2 个答案:

答案 0 :(得分:1)

问题

构建打字稿文件后,在组件顶部,您将具有如下所示的导入语句(假设您的目标是es2015)

import React from "react";

浏览器本机不知道如何解决“反应”,因此,它认为您将其误认为是另一个相对路径,例如“ ./react.js”,因此错误了

(index):1 Uncaught (in promise) TypeError: Failed to resolve module specifier "react". Relative references must start with either "/", "./", or "../".

当前有一个提案import-maps,该提案将使浏览器能够本地支持这些导入语句。 Chrome为此experimenting,最终浏览器Javascript必须提供一种解析导入模块的方法。

解决方案

您可以执行运行时解决方案或编译时解决方案:

运行时解决方案

我将使用systemjs,因为开箱即用的打字稿已支持它,您想将"module"内的compilerOptions更改为“ system”,例如

 "compilerOptions": {
   ....
   "module":"system"
  }

这将使打字稿编译为与systemjs兼容的代码,在您的根索引html文件中要包含systemjs文件,并且您还必须告诉systemjs在哪里寻找这些模块

// root index.html
 <script src="https://unpkg.com/systemjs@6.3.2/dist/system.js"></script>
 <script type="systemjs-importmap">
      {
        // for each library you add u have to include it here
        // documentation is here [systemjs import maps][3]d
        "imports": {
          "react": "https://unpkg.com/react@16/umd/react.production.min.js",
          "react-dom": "https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"
        }
      }
  </script>

然后您可以动态加载所需的模块

// load your module later
System.import("./dist/index.js").catch()

编译时间解决方案

您可以使用webpack,parcel或任何其他javascript捆绑程序,它们将在编译时为您解析这些模块,并为您提供捆绑了这些模块的捆绑软件。

我建议使用编译时解决方案,因为它不仅为您提供解析模块,还可以使用css预处理器,css模块,base64内联映像以及许多其他功能。

答案 1 :(得分:-1)

请按以下方式使用tsconfig.json:-

@Override
public void onBackPressed() {
    int count = getSupportFragmentManager().getBackStackEntryCount();
    if (count == 0) {
        super.onBackPressed();
    } else {
        int index = ((getSupportFragmentManager().getBackStackEntryCount()) -1);
        getSupportFragmentManager().popBackStack();
        FragmentManager.BackStackEntry backEntry = getSupportFragmentManager().getBackStackEntryAt(index);
        int stackId = backEntry.getId();
        mBottomNavigationView.getMenu().getItem(stackId).setChecked(true);
    }
}