未捕获的错误:对 JavaScript 使用动态导入时找不到模块

Posted

技术标签:

【中文标题】未捕获的错误:对 JavaScript 使用动态导入时找不到模块【英文标题】:Uncaught Error: Cannot Find Module When Using Dynamic Import for JavaScript 【发布时间】:2017-10-25 06:30:12 【问题描述】:

我正在使用 Create-React-App 并希望使用 webpack 2.0 支持的动态 import() 来基于变量字符串导入模块。

我查看了官方提案 (https://github.com/tc39/proposal-dynamic-import),似乎可以这样做:

import(`./language-packs/$navigator.language.js`)

但是当我尝试类似的东西时它会中断。

AppRoutes.js

import LazyLoad from 'services/LazyLoad';

export class AppRoutes extends React.Component 
  render() 
    return (
      <Switch>
        <Route
          exact path="/"
          render=(matchProps) => (
            <LazyLoad
              absoluteModulePath='pages/default/HomePage'
              getComponent=() => import('pages/default/HomePage')
              ...matchProps
            />
          )
        />
      </Switch>
    );
  


export default AppRoutes;

pages/default/HomePage/index.js

import React from 'react';

export const HomePage = () => 
  return (
    <div>
      I'm the default HomePage
    </div>
  );


export default HomePage;

损坏 services/LazyLoad/index.js

import React from 'react';

export class LazyLoad extends React.Component 
  ...

  componentDidMount() 
    import(this.props.absoluteModulePath)  // Critical dependency: the request of a dependency is an expression
      .then(module => module.default)
      .then(AsyncModule => this.setState(AsyncModule))
  

  ...


export default LazyLoad;

错误:

但是当我将 LazyLoader 更改为

工作中 services/LazyLoad/index.js

import React from 'react';

export class LazyLoad extends React.Component 
  ...

  componentDidMount() 
    this.props.getComponent()
      .then(module => module.default)
      .then(AsyncModule => this.setState(AsyncModule))
  

  ...


export default LazyLoad;

它有效。

绝对路径是在环境变量的帮助下内置在 create-react-app 中的。

.env

NODE_PATH=src/

我需要以这种方式动态加载模块来构建多租户的概念证明。如何修复损坏的 LazyLoad 以便我可以将字符串作为道具传递并让 LazyLoad 组件从该字符串道具动态加载组件?

【问题讨论】:

你试过用'./pages/default/HomePage'代替pages/default/HomePage作为路径字符串吗? 刚刚用 ./pages 和 ../pages 和 ../../pages 试了一下,它给了我同样的错误。 嗯,也许没有句号,/pages...,否则我不知道。对于捆绑拆分,我在 React-Router 的 getComponent 中使用 require.ensure。没有通过导入延迟加载的经验,抱歉。 您是否发现 require.ensure 适用于插值字符串或表达式而不是纯字符串? 是的,我刚刚尝试了一个可以正确评估的字符串文字。你想从哪里获取这个字符串?构建环境变量?在客户端基于 API 调用?这里有一个很好的例子:Github 【参考方案1】:

import() 只允许部分动态语句。

在您的 AppRoutes.js 中,您可以这样做:

...
<LazyLoad
    modulePath='HomePage'
    getComponent=() => import('pages/default/HomePage')
    ...matchProps
/>

然后在您的 LazyLoad 组件中执行以下操作:

componentDidMount() 
  import(`pages/default/$this.props.modulePath/index.js`)
    .then(module => module.default)
    .then(AsyncModule => this.setState(AsyncModule))

完全动态的语句,例如 import(foo),会失败,因为 webpack 至少需要一些文件位置信息。 import() 必须至少包含一些关于模块所在位置的信息,因此捆绑可以限制为特定目录或文件集。

https://webpack.js.org/api/module-methods/#import-

【讨论】:

以防万一有人想知道,同样的规则也适用于动态 require 语句。

以上是关于未捕获的错误:对 JavaScript 使用动态导入时找不到模块的主要内容,如果未能解决你的问题,请参考以下文章

Bootstrap 设置错误:未捕获 ReferenceError:未定义 jQuery 和未捕获错误:Bootstrap 的 JavaScript 需要 jQuery

未捕获的错误:Bootstrap 的 JavaScript 在 Angular 4 上需要 jQuery

Javascript Handsontable - 未捕获的类型错误:无法读取未定义的属性“insertBefore”

使用输入表单标记中的onclick属性的JavaScript未捕获引用错误

未捕获的类型错误:无法读取 null 的属性“样式”。在同一页面中使用两个 Javascript 函数

直接访问 application.cfc 会产生未捕获的 ColdFusion 错误