如何检测ES模块是否是主模块?

问题描述 投票:0回答:3

如何检测 ECMAScript 模块是否是主模块?这对于 CommonJS 模块来说很容易(请参阅检测是否通过 require 调用或直接通过命令行调用)。

  • 没有

    require
    require.main

  • 没有

    process.mainModule

  • import.meta
    没有任何线索,只有
    url

javascript node.js es6-modules
3个回答
8
投票

您可以使用

es-main

来自包自述文件:

import esMain from 'es-main';
 
if (esMain(import.meta)) {
  // Module run directly.
}

注意:该模块只能在 Node.JS 环境中工作,因为模块代码使用原生 Node.JS 模块。


4
投票

在浏览器中我不知道,但在带有

.mjs
模块的节点中,以下似乎可以工作:

const isMainModule = import.meta.url.endsWith(process.argv[1])

说明:

import.meta.url
以协议开头
file://
例如:

file:///path/to/my/module.mjs

但是在node中,process.argv[1]更短,例如:

/path/to/my/module.mjs

所以

endsWith
在这里很有用。


0
投票

在网络浏览器中,目前严格来说这不可能通过 JS 实现,但在 HTML 的帮助下,这是可以做到的。

例如,如果您有一个页面

foo.html
导入脚本,

<!-- foo.html -->

<body>
  <script type="module" src="./foo.js"></script>
</body>

你可以在模块中这样写:

// foo.js

function main() {
  // code specifically for foo.html, for example a demo of some APIs
  if (exampleA) doSomething()
  if (exampleB) doSomethingElse()
}

// Run the demo code only on the foo.html page.
if (location.pathname.endsWith('foo.html')) main()

// Export some APIs that some other page (or users of a library) might use:

export function doSomething() { ... }

export function doSomethingElse() { ... }

现在,在其他一些文件中,例如

bar.html
可能会实现一些不同的演示,它可以从
doSomething()
导入
foo.js
而无需
foo.js
运行其演示代码:

<!-- bar.html -->

<script type="module" src="./bar.js"></script>
// bar.js

import {doSomething} from './foo.js'

if (location.pathname.endsWith('bar.html')) {
  // ... run bar.js demo only on bar.js ...
}

// bar.js may export other APIs for other demos or end users:

export function doAnotherThing() { ... }

这是 CodePen 上的一个实例,用于将内容从一支笔共享到另一支笔:

以下笔有一个演示,并导出一些可重用的功能:

https://codepen.io/trusktr/pen/YzGbeKG

注意它是如何

exports
一些事情的。然后下面的笔从前面的笔导入JS文件来创建一个稍微高级的例子:

https://codepen.io/trusktr/pen/oNzRKJN

另一个例子在这里:

https://rawcdn.githack.com/trusktr/bmesh/ef32c00f72370013c796833ccecc0e4826d9edf5/prototypes/ops/003_delete.html

注意它是从

001_create.js
002_traverse_edges.js
导入的。

它导入的那些JS文件也有演示,例如:

https://rawcdn.githack.com/trusktr/bmesh/ef32c00f72370013c796833ccecc0e4826d9edf5/prototypes/ops/001_create.html

https://rawcdn.githack.com/trusktr/bmesh/ef32c00f72370013c796833ccecc0e4826d9edf5/prototypes/ops/002_traverse_edges.html

这些演示都可以在这里找到:

https://github.com/trusktr/bmesh/tree/ef32c00f72370013c796833ccecc0e4826d9edf5/prototypes/ops/

如果您粘贴索引文件,

https://github.com/trusktr/bmesh/tree/ef32c00f72370013c796833ccecc0e4826d9edf5/prototypes/ops/index.html

进入 raw.githack.com,你会得到一个可查看的 URL:

https://rawcdn.githack.com/trusktr/bmesh/tree/ef32c00f72370013c796833ccecc0e4826d9edf5/prototypes/ops/index.html

在那里可以查看的所有演示都使用相同的概念,仅根据 HTML 文件运行顶级模块代码。

提示:我将在主分支上更新这些演示,

https://github.com/trusktr/bmesh/tree/main/prototypes/ops/

并且带有分支名称而不是提交哈希(dev而不是prod)的raw.githack.com URL可用于查看最新的,f.e.

https://raw.githack.com/trusktr/bmesh/main/prototypes/ops/index.html

但我建议始终与提交哈希值共享 URL,以便 StackOverflow 上的此类答案始终是可重复的(尽管主分支可能会继续发展,但某些演示可能会被删除/移动或工作方式与以前不同)。

© www.soinside.com 2019 - 2024. All rights reserved.