NodeJS module.exports =require('other ')和带临时变量的module.exports =require('other')有什么区别?

pod7payv  于 2023-01-01  发布在  Node.js
关注(0)|答案(2)|浏览(220)

复制链接https://stackblitz.com/edit/node-sp5xay?file=index.mjs
假设我们有这样一个项目:

.
├── dep
│   ├── a.mjs
│   ├── b.js
│   └── c.js
└── entry.mjs

// entry.mjs
import { foo } from "./dep/a.mjs";
console.log(foo);

// dep/a.mjs
export * from './b.js'

// dep/b.js
module.exports = require("./c.js"); // 💯

// why this not working ❌
// const m = require("./c.js"); 
// module.exports = m;

// dep/c.js
exports.foo = "foo";

我们在终点站

node entry.mjs

如果在dep/b.js中使用以下语句,则会抛出错误,这非常令人困惑:

// why this not working ❌
const m = require("./c.js"); 
module.exports = m;

如果在dep/b.js中我们用途:

module.exports = require("./c.js");

它将工作预期!

module.exports=require有一些神奇的东西吗?比如符号链接?如果我错过了任何文档?
这个问题的根源是我看到了vue 3的源代码vue3 core source code export

ehxuflar

ehxuflar1#

module.exports=require有什么神奇的东西吗?
是的,它确实有一些魔力。问题是你正在把一个CommonJS模块导入到一个ES模块中。后者需要导出名称的静态声明,而前者没有提供。参见node.js文档:

  • 导入CommonJS模块时,module.exports对象作为默认导出提供。*

因此,不要执行export * from './b.js',而是先执行import b from './b.js',然后在CommonJS模块对象上引用b.foo
但是,

  • 为了更好地兼容JS生态系统中的现有用法,Node.js还尝试确定每个导入的CommonJS模块的CommonJS命名导出,以使用静态分析过程将它们作为单独的ES模块导出提供。*
  • [...]*
    • 指定导出的检测基于常见语法模式,但并不总是正确检测指定导出**。在这些情况下,使用上述默认导入表单可能是更好的选择。*
  • 命名导出检测涵盖了许多常见的导出模式、再导出模式以及构建工具和转发器输出。请参阅cjs-module-lexer了解实现的确切语义。*

(着重号是我的)
事实上

module.exports = require("./c.js");

是检测到的"重新导出模式"之一,但使用临时变量

const m = require("./c.js"); 
module.exports = m;

你只是不能使用CommonJS模块中的命名导入,解决这个问题的正确方法当然是将模块重写为ESM语法,并使用export * from "./c.js";,而不是任何module.exports赋值。

nr9pn0ug

nr9pn0ug2#

在Node.js中,module.exports对象用于指定当使用require导入模块时,模块应提供哪些内容。
第一条语句module.exports = require('module')将module.exports对象设置为使用require导入的模块对象的值。这意味着由module模块导出的任何内容都将对导入它的代码可用。
另一方面,module.exports = {...}将module.exports对象设置为一个对象文本,该对象文本包含导入模块的代码应该可以使用的属性和值。这允许您准确地指定模块中应该提供的内容,而不是依赖于另一个模块的导出。
例如,假设您有一个名为myModule的模块,它导出单个函数:

module.exports = {
  myFunction: () => {
  console.log('Hello, world!');
 }
};

然后可以导入并使用此模块,如下所示:

const myModule = require('myModule');
myModule.myFunction(); // prints 'Hello, world!'

另一方面,如果将module.exports设置为另一个模块的exports的值,如下所示:

module.exports = require('anotherModule');

然后,anotherModule的导出将可用于导入myModule的代码。例如:

const myModule = require('myModule');
myModule.someFunction(); // calls a function exported by anotherModule

相关问题