从'react'导入*作为React; vs从'react'导入React;

时间:2019-03-21 17:08:28

标签: javascript reactjs typescript react-native ecmascript-6

我注意到React可以这样导入:

import * as React from 'react';

...或者像这样:

import React from 'react';

第一个导入react模块中的所有内容(请参阅:Import an entire module's contents

第二个仅导入default模块导出(请参阅:Importing defaults


这两种方法似乎是不同的,而且根本不兼容。

为什么它们都起作用?


请参考源代码并解释该机制...我有兴趣了解其工作原理。


更新

这不是What is the difference between import * as react from 'react' vs import react from 'react'

的副本。

使用一般的ES6模块信息回答了该问题。

我正在询问使react模块像这样工作的机制。它似乎与“ hacky”导出机制in the source here有关,但目前尚不清楚如何将 entire 模块导入和仅将 default 导出到{{ 1}},并同时使用这两种方法来编译JSX等。

2 个答案:

答案 0 :(得分:4)

TL; DR

独立的ES导入语句import defaultimport *并不相同,在这种情况下它们的行为相同是React作者选择发布库和兼容性层的方式的结合。 TypeScript(使用esModuleInterop)或Babel和您的捆绑软件以使其“正常工作”。它可能不应该根据ES6规范工作,但是今天我们仍然在一个JS模块混乱的时代工作,因此Babel,TypeScript,Webpack等工具试图规范行为。

更多详细信息:

React不是ES6库。如果您查看the source code,则会在index.js中看到以下内容:

const React = require('./src/React');

// TODO: decide on the top-level export form.
// This is hacky but makes it work with both Rollup and Jest.
module.exports = React.default || React;

(请注意注释,即使在React源代码中,它们也难以与ES6默认导出兼容性兼容。)

module.exports =语法为CommonJS(NodeJS)。浏览器不会理解这一点。这就是为什么我们使用Webpack,Rollup或Parcel之类的捆绑器的原因。他们了解各种模块语法,并生成应在浏览器中使用的捆绑软件。

但是,尽管React不是ES库,但TypeScript和Babel都可以像导入它一样(使用import语法,而不是require()等)来导入它,但是两者之间存在差异必须解决的CJS和ES。其中一个事实是export = 可以给您的东西是ES没有符合规范的导入方式,例如函数或类作为模块。为了解决这些不兼容问题,Babel允许您暂时导入CJS模块,就像默认情况下它们正在导出内容一样, import作为命名空间。 TypeScript暂时没有执行此操作,但最近在esModuleInterop下将其作为选项添加。因此,现在Babel和TypeScript都可以非常一致地允许使用默认或名称空间ES导入来导入CJS模块。

使用TypeScript,它还取决于实际定义库的类型定义的方式。我不会对此进行介绍,但是您可以想象这样的情况:由于使用了编译器和捆绑器,特定的导入在运行时有效,但是TypeScript不会没有错误地进行编译。

值得一提的另一件事是,如果您查看React的内置代码,则有一个UMD module版本和CJS版本。 UMD版本包含一些粗糙的运行时代码,以尝试使其在任何模块环境(包括浏览器)中均可工作。如果您只想在运行时包含React(即您不使用捆绑程序),则主要用于此。 Example

令人困惑?是的,我是这样认为的。 :)

答案 1 :(得分:2)

您很可能在"allowSyntheticDefaultImports": true,中设置了tsconfig.json,这实际上使编译器无法使用它认为无效的默认导入。 Typescript添加了esModuleInterop,其本质上与babel进行模块加载一样。

即使您要导入的源代码未导出任何默认内容,这也允许您使用ES6默认导入

打字稿对此非常严格(遵循规则),这就是为什么它们要求您import * as React from 'react'。或者要求您告诉它在其基本配置中允许合成默认导入。

More On That Here