Skip to main content

全量引入

前言

import React from 'react';

// VS

import * as React from 'react';

这两种方式有什么区别?

我们知道React实际上并没有使用ES6定义默认导入的方式,即不是 ES Module。我们发现在配置了 TypeScript 或者配置了 Babel 的项目中使用时,我们就可以把它当作 ES Module default 来导入,为什么呢?如何配置呢?

Typescript 使用

tsconfig.json 文件中有一个选项叫做 allowSyntheticDefaultImports

当设置为 true, 并且模块没有显式指定默认导出时,--allowSyntheticDefaultImports 可以让你这样写导入:

import React from "react";

而不需要:

import * as React from "react";

Typescript 是怎么实现的?

src/compiler/utilities.ts: getAllowSyntheticDefaultImports

export function getAllowSyntheticDefaultImports(compilerOptions: CompilerOptions) {
const moduleKind = getEmitModuleKind(compilerOptions);
return compilerOptions.allowSyntheticDefaultImports !== undefined
? compilerOptions.allowSyntheticDefaultImports
: compilerOptions.esModuleInterop ||
moduleKind === ModuleKind.System;
}

src/services/codefixes/importFixes.ts: getExportEqualsImportKind

function getExportEqualsImportKind(importingFile: SourceFile, compilerOptions: CompilerOptions): ImportKind {
const allowSyntheticDefaults = getAllowSyntheticDefaultImports(compilerOptions);
// 1. 'import =' will not work in es2015+, so the decision is between a default
// and a namespace import, based on allowSyntheticDefaultImports/esModuleInterop.
if (getEmitModuleKind(compilerOptions) >= ModuleKind.ES2015) {
return allowSyntheticDefaults ? ImportKind.Default : ImportKind.Namespace;
}
// 2. 'import =' will not work in JavaScript, so the decision is between a default
// and const/require.
if (isInJSFile(importingFile)) {
return isExternalModule(importingFile) ? ImportKind.Default : ImportKind.CommonJS;
}
// 3. At this point the most correct choice is probably 'import =', but people
// really hate that, so look to see if the importing file has any precedent
// on how to handle it.
for (const statement of importingFile.statements) {
if (isImportEqualsDeclaration(statement)) {
return ImportKind.CommonJS;
}
}
// 4. We have no precedent to go on, so just use a default import if
// allowSyntheticDefaultImports/esModuleInterop is enabled.
return allowSyntheticDefaults ? ImportKind.Default : ImportKind.CommonJS;
}

babel 同理

React团队推荐使用

import * as React from 'react';
import { useState } from 'react';

参考资料

MDN - import

import * as React from 'react'; vs import React from 'react';

import * as React vs. import React

TSconfig allowSyntheticDefaultImports

Github PR#26866 - Enable allowSyntheticDefaultImports if esModuleInterop is enabled

Github PR#18102 - Codemod to import * as React from "react"

spec - es modules