javascript - 在动态加载的 es 模块中使用 React
问题描述
我一直在加载可以简化为的本机 ES 模块src/test.tsx
:
export default class Test {
constructor() {
console.log('loaded');
}
}
我可以在我的浏览器中加载它并初始化它,a la:
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 捆绑所有内容,但无法弄清楚如何以这种方式生成可动态导入的模块
解决方案
问题
在构建你的打字稿文件之后,在你的组件的顶部,你将有一些如下的导入语句(假设你的目标是 es2015)
import React from "react";
浏览器本身不知道如何解决“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 正在对此进行试验,最终浏览器 javascript 将不得不提供一种解析导入模块的方法。
解决方案
您可以执行运行时解决方案或编译时解决方案:
运行时解决方案
我将使用systemjs,因为它已经被 typescript 开箱即用支持,你想"module"
在里面更改为“system” compilerOptions
,比如
"compilerOptions": {
....
"module":"system"
}
这将使 typescript 编译为与 systemjs 兼容的代码,在您想要包含 systemjs 文件的根索引 html 文件中,您还必须告诉 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 内联图像等等。
推荐阅读
- php - 如何在 wordpress 网站上将访客用户变成注册用户
- c - 使用 CreateThreadpoolWork/SubmitThreadpoolWork 时向回调函数传递不同的值
- postgresql - 我的查询未显示所需结果并在未知情况下省略了值
- hyperledger-fabric - 超级账本背书政策和调用链码错误(不更新账本)
- redux - 如何使用 redux 更新/删除对象中的值
- algorithm - 用 invmap 代替 fmap 和 contramap 的推导
- javascript - 使用 iframe 时会使用什么 url?
- salesforce - Salesforce 动态操作缺少编辑按钮突出显示面板
- reactjs - 使用 React 调用模拟键盘事件和测试 stopImmediatePropagation
- azure - 如何将多个 CloudBlockBlob 对象连接到 Azure 中的一个 CloudBlockBlob 对象?