【问题标题】:to add .default or not?: dynamic imports in react router 3 for webpack code-splitting添加 .default 与否?:react router 3 中用于 webpack 代码拆分的动态导入
【发布时间】:2021-03-19 15:26:38
【问题描述】:

最近我正在将我的项目从 webpack 3 (v. 3.3.0) 升级到 webpack 4 (v. 4.44.2)。编译和构建工作完美,但结果显示屏幕上什么也没有。

在比较了 webpack 3 和 webpack 4 的两个项目之间传递给 RouterContext 的参数后,我将根本原因缩小到动态导入的组件。

以下脚本是我如何使用 react-router 3 (v. 3.0.5) getComponent 导入组件,在升级到 webpack 4 之前可以使用:

const loadRoute = callback => module => callback(null, module);

const forceToReload = (err) => {
  Logger.error(err);
  window.location.reload();
};

export default (loadRoute, forceToReload) => (
  <Route name="Subscribe" path={appUtils.getRoutePath('/sample')}
         getComponent={(location, callback) => import('./index.jsx').then(loadRoute(callback)).catch(forceToReload)}/>
);

幸运的是,经过几天的反复试验,我终于让我的项目正确渲染了。 在 webpack 4 版本中,我必须将 .default 附加到 loadRoute 中的模块,如下所示:

const loadRoute = callback => module => callback(null, module.default);

问题是

即使问题解决了,我仍然想知道是否有人可以解释一下何时添加.default
webpack 4 在动态导入时编译是否不同?有什么想法吗?

【问题讨论】:

  • 感谢您提出这个问题。我需要从 require.ensure 转换为 import() 因为 webpack 5 把它踢掉了。至于默认,这可能是一个反应路由器的事情。获取组件时,我总是将其添加到我的 require.ensure 语句中。
  • 其实来自 webpack 文档:我们需要 default 的原因是,从 webpack 4 开始,在导入 CommonJS 模块时,import 将不再解析为 module.exports 的值,而是创建一个CommonJS 模块的人工命名空间对象。并参考这篇文章:medium.com/webpack/webpack-4-import-and-commonjs-d619d626b655 我看到你发现了。

标签: javascript reactjs webpack react-router


【解决方案1】:

经过几天的研究,我终于找到了我的问题的答案,希望我能以某种方式帮助未来有同样问题的人。

Webpack官网(Code-Splitting: Dynamic Import)有如下描述:

我们需要默认的原因是,从 webpack 4 开始,在导入 CommonJS 模块时,导入将不再解析为 module.exports 的值,而是为 CommonJS 模块创建一个人工命名空间对象。

出于好奇,我做了一些实验,将动态导入的内容注销:

// exportObject.js
export default {a: 1, b: 2};
export const c = 3;

// exportString.js
export default "TEST_STRING";

// exportComponent.js
import React, {Component} from "react";
export default class exportComponent extends Component {
  constructor(props) {
    super(props);
    this.a = 1;
    this.b = 2;
  }
}

// exportFunction.js
export default () => ({a: 1, b: 2});
// index.js
componentDidMount() {
 import('./exportObject').then(module => {
    console.group('Object');
    console.warn('module', module);
    console.warn('module.a:', module.a);
    console.warn('module.b:', module.b);
    console.warn('module.default', module.default);
    console.warn('module.c', module.c);
    console.groupEnd();
  });

  import('./exportString').then(module => {
    console.group('String');
    console.warn('module', module);
    console.warn('module.default', module.default);
    console.groupEnd();
  });

  import('./exportComponent').then(module => {
    console.group('Component');
    console.warn('module', module);
    console.warn('module.default', module.default);
    console.groupEnd();
  });

  import('./exportFunction').then(module => {
    console.group('Function');
    try {
      console.warn('module()', module());
    } catch (e) {
      console.warn('module()', e);
    }
    try {
      console.warn('module.default()', module.default());
    } catch (e) {
      console.warn('module.default()', e);
    }
    console.groupEnd();
  });
}

这是 Webpack 3 项目的结果:

来自 Webpack 4 项目:

如您所见,非对象有不同的结果。这个发现和这个article的描述相符(由webpack官方提供)

导出对象时没有那么问题。但是将 module.exports 与非对象一起使用时会遇到麻烦。

我在我的代码中使用export default 而不是module.exports,那为什么我仍然得到结果? 实际上,Babel@6 会进行如下转换:(reference)

Babel@6 转换如下文件

export default 'foo'

进入

'use strict';
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = 'foo';

现在,一切都清楚了。

我使用的包是:

node: 11.15.0

babel-core: "^6.23.1",
babel-loader: "7.1.4",
webpack: "4.44.2",
webpack-cli: "^4.2.0",

【讨论】:

    猜你喜欢
    • 2017-09-30
    • 2017-03-28
    • 2020-03-03
    • 1970-01-01
    • 2017-07-16
    • 2018-09-21
    • 2017-06-04
    • 2016-08-14
    • 1970-01-01
    相关资源
    最近更新 更多