在Bash终端中使用Bash heredoc运行ES6代码

3

使用Bash heredoc可以轻松在终端中运行ES5代码:

node <<HEREDOC
  var fs = require("fs");
  ...
HEREDOC

但是,即使使用正确的 --experimental-modules 标志,ES6代码也无法运行:

node --experimental-modules <<HEREDOC
  import fs from "fs";
  ...
HEREDOC

显示的错误是:
(node:4130) ExperimentalWarning: The ESM module loader is experimental.
[stdin]:1
import fs from "fs";
       ^^

SyntaxError: Unexpected identifier
    at new Script (vm.js:83:7)
    at createScript (vm.js:267:10)
    at Proxy.runInThisContext (vm.js:319:10)
    at Object.<anonymous> ([stdin]-wrapper:6:22)
    at Module._compile (internal/modules/cjs/loader.js:722:30)
    at evalScript (internal/bootstrap/node.js:670:27)
    at ReadStream.<anonymous> (internal/bootstrap/node.js:340:15)
    at ReadStream.emit (events.js:187:15)
    at endReadableNT (_stream_readable.js:1098:12)
    at process.internalTickCallback (internal/process/next_tick.js:72:19)

它显示了这个信息“ExperimentalWarning: The ESM module loader is experimental.”,这意味着Node.js正确运行了ES6模块功能,但是关键字import不起作用

如何在终端中使用Bash heredoc内联运行ES6代码?我知道我可以将代码写入文件以正常加载ES6模块,但它只是短暂的临时代码,应该更好地放在heredoc中。


1
--experimental-modules目前还不支持stdin模块,但在Node 12中应该会支持。如果您确实需要ES模块,可以尝试使用https://www.npmjs.com/package/esm。 - Jamesernator
@Jamesernator,它只允许我导入内置模块,“npm i moment”不起作用,“npm i -g moment”也不起作用。 - Dee
1
是的,只有内置模块可以从标准输入中工作。在REPL中有一个关于相同问题的未解决问题,很可能是相同的原因:https://github.com/nodejs/node/issues/19570 - Jamesernator
2个回答

3
更新:
自从Node.js 14版本开始,标志--experimental-modules不再需要,在Node.js中默认支持.mjs文件和heredoc,但是在CLI上仍然需要--input-type标志,因为heredoc仍然需要指定ES5或ES6。
node --input-type module <<HEREDOC
  //example:
  import fs from "fs";
HEREDOC
旧指南:
经过调研,Node 11根本不支持从stdin使用ES模块,如果您想在Node 11中使用模块,则需要将它们放在文件中。
使用Node 12(目前未发布,但可以使用npm i -g node-nightly尝试),您可以使用标志--entry-type=module将stdin用作模块。
使用node-nightly就可以正常使用以下内容:
node-nightly --experimental-modules --entry-type=module <<HEREDOC
  import fs from 'fs'
  console.log(fs);
HEREDOC

编辑:

正如评论区@Jamesernator所指出的,在node-nightly从v13开始,请使用“--input-type”代替“--entry-type”。

仅支持内置模块,即'import'不能找到本地目录中的模块,也不能找到使用'-g'标志安装的全局模块。相关问题:https://github.com/nodejs/node/issues/19570


那个 node-nightly 真是太棒了!谢谢。 - Dee
但是最新的node-nightly现在不再有"--entry-type"选项了,我刚刚用node-nightly v13.0.0-nightly2019042580c0b89bbb进行了检查。它显示了这个错误:bad option: --entry-type=module。 - Dee
1
它已经在几天前更名为--input-type。现在你可以直接使用Node 12,而不是每晚的版本。 - Jamesernator
1
它可能仍然会改变,尽管这是一个持续的讨论:https://github.com/nodejs/modules/issues/312 - Jamesernator
谢谢,我现在可以使用--input-type了,希望它不会再改变。 - Dee
它只允许我导入内置模块,"npm i moment" 不起作用,"npm i -g moment" 也不起作用。 - Dee

1

这是一个很好的问题,让我学到了很多!感谢你的提问。以下是我所学到的:

首先
对于Node来说,Bash heredoc就像简单地执行Node,然后输入在heredoc标签中键入的任何内容。

例如:

node --experimental-modules <<HEREDOC
  import fs from "fs";
  ...
HEREDOC

等同于

node --experimental-modules
> import fs from "fs";

执行节点就像从节点打开REPL一样

其次import语法:

import fs from "fs"

"fs"中没有fs。现在这对你来说不是问题,但如果导入成功,它将无法在"fs"模块中找到它。相反,正确的语法应该是,例如:

import { readFile } from "fs";

然而,这产生的结果是:

SyntaxError: Unexpected token {

最后,问题在于整个功能确实是实验性的。
这方面有一些已经公开的问题:

在Node实现中,import fs from 'fs'import * as fs from 'fs'两者的作用是相同的,因为Node内置模块的默认导出会将整个模块导出。 - Jamesernator
@Adelin,它只允许我导入内置模块,“npm i moment”不起作用,“npm i -g moment”也不起作用。 - Dee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接