我正在构建一个使用 Parcel 或 Webpack 捆绑的 React 应用程序。
该应用程序应该能够嵌入
由第三方开发并作为现代 javascript module托管在其他地方的外部 React 组件:
// https://example.com/scripts/hello-plugin.js
import React from 'react';
export default class HelloPlugin extends React.Component {
render() {
return "Hello from external plugin!";
}
}
主机应用程序使用异步导入来加载这些组件,例如:
// createAsyncComponent.tsx
import * as React from 'react';
import { asyncComponent } from 'react-async-component';
export default function createAsyncComponent(url: string) {
return asyncComponent({
resolve: () => import(url).then(component => component.default),
LoadingComponent: () => <div>Loading {url}....</div>,
ErrorComponent: ({ error }) => <div>Couldn't load {url}: {error.message}</div>,
})
}
但看起来捆绑器不允许将任意 url 作为外部 javascript module导入。
Webpack 发出构建警告:“依赖项的请求是一个表达式”并且导入不起作用。Parcel 不报告任何错误,但在运行时发生 import(url) 时失败。
Webpack 作者推荐使用 scriptjs 或 little-loader 来加载外部脚本。
有一个从任意 URL 加载 UMD 组件的工作示例,如下所示:
public componentDidMount() {
// expose dependencies as globals
window["React"] = React;
window["PropTypes"] = PropTypes;
// async load of remote UMD component
$script(this.props.url, () => {
const target = window[this.props.name];
if (target) {
this.setState({
Component: target,
error: null,
})
} else {
this.setState({
Component: null,
error: `Cannot load component at ${this.props.url}`,
})
}
});
}
此外,我在一年前看到了一个类似的问题,其中建议的方法还涉及通过窗口对象传递变量。
但我想避免使用全局变量,因为大多数现代浏览器都支持开箱即用的module。
我想知道是否有可能。也许,有任何方法可以指示捆绑器我的 import(url) 不是对主机应用程序的代码拆分块的请求,而是对加载外部 Javascript module的请求。