require 作为 import 语句被调用

require is called earlier as import statement

我有一个模块 m1 需要先初始化才能导入模块 m2:

import * as m1 from 'm1';
m1.init(...)
import * as m2 from 'm2';

我更新了 browserify 并从 6to5ify 切换到 babelify 变压器。之后,我的捆绑包中的 require 个调用移到了顶部:

...
var _m1 = require('./m1');
var m1 = _interopRequireWildcard(_m1);
var _m2 = require('./m2');
var m2 = _interopRequireWildcard(_m2);
m1.init('init value');
...

为什么 require 来电移到顶部? m1.init调用后可以用ES6模块导入语法导入m2吗?我可以直接用require

import * as m1 from 'm1';
m1.init(...)
const m2 = require('m2');

然后我得到

var _m1 = require('./m1');
var m1 = _interopRequireWildcard(_m1);
m1.init('init value');
var m2 = require('./m2');

但这对我来说似乎是一个 hack。

导入应该被认为是 ES6 中的提升值。它们始终位于模块的顶部。您当前依赖于隐式依赖。如果 m2 依赖于 m1 不仅被加载,而且被初始化,那么你应该有一个模块明确地 returns 一个 m1 的初始化版本,那么它应该是如果您不能直接修改 m2,则明确或通过导入排序,例如

init-m1.js

import * as m1 from 'm1';
m1.init(...)
export default m1;

init-m2.js

import m1 from './init-m1';
import * as m2 from 'm2';

Can I use ES6 module import syntax to import m2 after m1.init is called?

无论 Babel 如何转译这段代码,答案都是:。规范规定所有依赖项在 之前 模块本身被评估 (§15.2.1.16.5).

这意味着当引擎实际执行代码时,import 声明不会被评估。它们是静态分析的,并且此信息以某种方式添加到模块中,以便可以在评估模块本身之前评估依赖关系。


即使您找到了可以满足您要求的转译器,它也不符合规范,您的代码将来可能会出错。