如何将脚本加载到node.js REPL中?


137

我有一个脚本foo.js,其中包含一些我想在REPL中使用的功能。

有没有办法让节点执行我的脚本,然后使用所有声明的全局变量跳入REPL,就像我可以使用python -i foo.pyor一样ghci foo.hs

Answers:


179

仍然没有内置功能可以提供您描述的确切功能。但是,也可以使用require它来在REPL中使用.load命令,例如:

.load foo.js

它会逐行加载文件,就像您在REPL中键入文件一样。与require此不同,这会使用您加载的命令污染REPL历史记录。但是,它具有可重复的优势,因为它没有像一样被缓存require

哪种对您更好,将取决于您的用例。


编辑:它的适用性有限,因为它不能在严格模式下工作,但是三年后,我了解到,如果您的脚本没有'use strict',您可以使用它eval来加载脚本而不会污染REPL历史记录:

var fs = require('fs');
eval(fs.readFileSync('foo.js').toString())

如果我想放入异步回调内部的repl怎么办?
Chet

2
@Chet如果您的问题与现有问题不匹配,您可以写一个新的StackOverflow问题:-)
vossad01

@Chet您可以使用(async()=> {更多代码})();来加载另一个文件。它将共享相同的全局变量。
nurettin

提示,如果您使用的是macOS(也可能是其他)。您可以在REPL中键入“ .load”(注意空格),然后将文件从Finder拖放到终端中,以为命令添加正确的路径。如果您正在使用的文件向下几个级别,则这非常方便。
jamesnotjim

35

我总是用这个命令

node -i -e "$(< yourScript.js)"

完全像Python中一样,没有任何包。


1
有谁知道如何在Windows cmd中使用它?我让它在bash中工作,但不在Windows中。
Sharpiro '18

@Sharpiro:如果安装Git,则可以选择将mini-UNIX安装到Windows PC中。我的意思是Windows的Git正态分布。
Juan Lanus

令人讨厌的一件事是Node.js将打印repl提示符,然后运行您的脚本,因此任何输出都会在提示符后卡住。stackoverflow.com/a/45893494/3538165不存在此问题,但是对于该解决方案,必须将函数显式分配给变量,以使其最终出现在repl命名空间中,因此也不是很好。
Radon Rosborough

10

我制作了Vorpal.js,它通过将您的节点添加到交互式CLI中来处理此问题。它支持REPL扩展,可将您带入正在运行的应用程序上下文中的REPL。

var vorpal = require('vorpal')();
var repl = require('vorpal-repl');

vorpal
  .delimiter('myapp>')
  .use(repl)
  .show()
  .parse(process.argv); 

然后,您可以运行该应用程序,它将放入REPL中。

$ node myapp.js repl
myapp> repl: 

8

另一种方法是将这些功能定义为全局功能。

global.helloWorld = function() { console.log("Hello World"); }

然后以以下方式将文件预加载到REPL中:

node -r ./file.js

然后helloWorld可以在REPL中直接访问该功能。


8

我创建replpad是因为我厌倦了重复加载脚本。

只需通过以下方式安装: npm install -g replpad

然后通过运行使用它: replpad

如果希望它监视当前目录和所有子目录中的所有文件,并在它们更改时将它们通过管道传递给repl,请执行以下操作: replpad .

观看网站上的视频,以更好地了解其工作原理,并了解其其他一些不错的功能,例如:

  • 通过dox()添加到每个核心功能的功能来访问repl中的核心模块文档,即fs.readdir.dox()
  • 通过dox()添加到通过npm安装的每个模块中的功能访问repl中的用户模块自述文件,即marked.dox()
  • 通过添加到每个函数的属性访问访问函数突出显示的源代码,有关在何处定义函数的信息(文件,行号)以及函数注释和/或jsdocssrc,即express.logger.src
  • 脚本对讲机支持 (请参阅.talk命令)
  • 添加命令和键盘快捷键
  • vim键绑定
  • 按键图支持
  • 括号匹配经由匹配令牌插件
  • 通过键盘快捷键或.append命令将在repl中输入的代码附加回文件

参见:https : //github.com/thlorenz/replpad


我必须CXX=clang++ npm install replpad解决该错误g++: error: unrecognized command line option '-stdlib=libc++'
ShadSterling

但是,当我运行它时,它失败了# # Fatal error in ../deps/v8/src/api.cc, line 1248 # Check failed: !value_obj->IsJSReceiver() || value_obj->IsTemplateInfo(). # Illegal instruction: 4
ShadSterling

5

为什么不将文件加载到交互式节点repl中?

node -h
-e, --eval script          evaluate script
-i, --interactive          always enter the REPL even if stdin

node -e 'var client = require("./build/main/index.js"); console.log("Use `client` in repl")' -i

然后您可以添加到package.json脚本

"repl": "node -e 'var client = require(\"./build/main/index.js\"); console.log(\"Use `client` in repl\")' -i",

使用节点v8.1.2进行了测试


2
为什么不只是node -i -r "./build/main/index.js"
Z. Khullah

4

当前,您不能直接执行此操作,但是可以mylib = require('./foo.js')在REPL中执行。请记住,方法是导出的,而不是声明为全局变量。


.load my_work.js尽管需要一些额外的exports.working_var = ...声明,但我发现这对它更可取,因为REPL在某些完全有效的javascript上使用barfs,例如多行注释(至少在我的readline配置中)。
chbrown 2015年

4

replpad 很酷,但是对于将文件加载到节点,导入其变量并启动repl的快速简便的方法,您可以将以下代码添加到.js文件的末尾

if (require.main === module){
    (function() {
        var _context = require('repl').start({prompt: '$> '}).context;
        var scope = require('lexical-scope')(require('fs').readFileSync(__filename));
        for (var name in scope.locals[''] )
            _context[scope.locals[''][name]] = eval(scope.locals[''][name]);
        for (name in scope.globals.exported)
            _context[scope.globals.exported[name]] = eval(scope.globals.exported[name]);
    })();
}

现在,如果您的文件为src.js,则运行node src.js将启动节点,加载文件,启动REPL,并复制var在顶层声明的所有对象以及所有导出的全局变量。的if (require.main === module),如果这个代码将不会被执行,确保src.js通过包括require声明。实际上,您可以src.jsif语句中添加要在调试时独立运行的任何代码。


4

这是乔治回答的bash函数版本 :

noderepl() {
    FILE_CONTENTS="$(< $1 )"
    node -i -e "$FILE_CONTENTS"
}

如果将其放在自己~/.bash_profile的文件夹中,则可以像别名一样使用它,即:

noderepl foo.js

2
我已经使用了几个月了,在过渡到新的shell环境时,我丢失了一些设置,不得不再次跟踪。因此,由于我在这里,所以我想感谢您提供这一非常有用的功能。
Xaekai '19

3

我在这里看不到的另一条建议:尝试这段代码

#!/usr/bin/env node
'use strict';

const repl = require('repl');
const cli = repl.start({ replMode: repl.REPL_MODE_STRICT });
cli.context.foo = require('./foo'); // injects it into the repl

然后,您可以简单地运行此脚本,它将包含foo为变量


1

旧答案

type test.js|node -i

将打开节点REPL并在test.js的所有行中键入REPL,但是由于某种原因,节点将在文件结束后退出

另一个问题是,功能不会被提升。

更好的答案

node -e require('repl').start({useGlobal:true}); -r ./test2.js

然后在test2.js中声明为无var的所有全局变量将在REPL中可用

不确定为什么全局范围内的var a将不可用


8
请为您的答案添加一些解释
-mechnicov
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.