ES6中的动态导入与运行时变量

20

最近偶然发现了动态导入提案以及这个Youtube视频。想着用它来实现React组件的按需导入是一个好主意。

但我遇到了一个问题,当import传递字符串字面量作为运行时变量时,无法“解析”路径。

例如:

<div>
  <button onClick={this._fetchComp.bind(this, "../component/Counter")}>Get Async Comp</button>
</div>

尝试了多种_fetchComp选项,但似乎传递参数不起作用。以下是尝试的各种选项的分解。

  1. 模板字符串 不起作用:在单击时出现以下错误

错误:无法找到模块“../components/Counter”。在webpackAsyncContext(^.* $: 53)

代码

    _fetchComp(res) {
    import(`${res}`).then(() => {
        console.log("Loaded")
    },(err)=>{
        console.log("Error",err)
    })}
  1. 变量 无法正常工作: 在webpack构建过程中出现错误,位置为55:12-23

关键性依赖项:一个依赖项的请求是一个表达式

**Code**

    _fetchComp(res) {
    import(res).then(() => {
        console.log("Loaded")
    },(err)=>{
        console.log("Error",err)
    })}
  1. 字符串字面值 运作良好:仅传递纯字符串字面量。单击时,我能够在开发工具的网络选项卡中看到正在下载的代码块。

    代码

    _fetchComp(res) {
    import("../components/Counter").then(() => {
        console.log("Loaded")
    },(err)=>{
        console.log("Error",err)
    })}
    

根据规范,

import()接受任意字符串(这里展示了动态确定的模板字符串),而不仅仅是静态字符串字面量。

因此我原本希望使用字符串字面量来完成,但似乎并不是这种情况。

我在flow问题追踪器上遇到了类似的问题。但所提出的解决方案再次倡导使用字符串字面量。

我会留下一个CodeSandbox链接。


好的,这只是一个提议(绝对不是ES6!),你怎么能认为webpack已经支持它了呢?此外,它需要一个客户端设置来支持动态模块加载。 - Bergi
@Bergi: "webpack已经支持它了" - 啊,我很担心这个!:(。我已经在本地使用create-react-app进行了测试,这不是一个很好的客户端设置来处理动态导入吗? - semuzaboi
1个回答

40
import("./path/to/module.js")

instead of

import("module-name")

因为webpack处理import()的规则与规范不同,Webpack需要能够至少大致猜测出import()的引用是什么。这就是为什么你的import("../components/Counter")示例有效的原因,因为Webpack可以100%确信需要加载什么。

对于您的用例,您可以使用import("./path/to/module.js")而不是import("module-name")

_fetchComp(res) {
  import(`../components/${res}`).then(() => {
    console.log("Loaded")
  }, (err)=>{
    console.log("Error", err)
  })
}
this._fetchComp.bind(this, "Counter")

现在Webpack知道路径以../components/开头,它可以自动捆绑每个组件,然后加载您所需的组件。这里的缺点是,因为它不知道您要加载哪个组件,它必须全部加载,并且不能保证它们都实际使用。这就是动态导入的权衡。


1
我注意到如果使用import(\../components/${res}`)`,webpack也会以半随机的顺序捆绑css文件,导致混乱不堪。 - Ciantic
7
那么考虑使用import(`../components/${res}.js`),这样Webpack就知道你只会加载JS文件。 - loganfsmyth
1
@loganfsmyth:我一直在开发动态仪表板功能,卡了很长时间,但是你的解决方案非常好用。将“pages/”添加到动态导入中就可以了。谢谢! - www.amitpatil.me

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接