标签 Node.js 下的文章

在这篇文章中,我们将逐步解释如何在 RHEL 9 系统上安装 Node.js。

Node.js 基于谷歌的 V8 JavaScript 引擎构建,它是一个自由开源的跨平台 JavaScript 运行时环境,主要用于构建服务器端应用。它使用事件驱动和异步模型,帮助开发人员构建高度可扩展的数据密集型的实时应用(RTA)。你可以使用 NodeJS 来构建前端和后端应用。

Node.js 通常用于构建以下应用:

  • 聊天应用
  • 流媒体应用
  • 浏览器游戏
  • 命令行工具
  • 嵌入式系统

在其技术栈中使用 NodeJS 的顶级公司包括 PayPal、NetFlix 和 Uber 等等。

安装 Node.js 主要有以下三种方式:

  • 从 NodeSource 仓库安装 Node.js
  • 从发行版的官方仓库安装 Node.js
  • 使用 NVM 安装 Node.js

让我们看看如何使用这些方法在 RHEL 9 上安装 Node.js。

先决条件:

  • 最小化安装的 RHEL 9 系统
  • 具有管理员权限的 sudo 用户
  • 互联网连接
  • Red Hat 订阅或本地配置的仓库

从 NodeSource 存储库安装 Node.js

NodeSource 是一家技术公司,旨在帮助组织运行生产就绪的 Node.js 应用,关注资源使用以及增强的安全性和应用程序性能。它提供了最新版本的 Node.js 和 NPM。

要从 NodeSource 安装 Node.js,首先,按如下所示更新系统包。

$ sudo dnf update -y

接下来,安装这期间所需的构建工具。其中包括 GCC C/C++ 编译器、Perl 和 Python 调试器等等。

$ sudo dnf groupinstall 'Development Tools' -y

接下来,我们将从 NodeSource 安装 Node.js 18.x。为此,请下载并运行 NodeSource 设置脚本,如下所示。

$ curl -fsSL https://rpm.nodesource.com/setup_18.x | sudo bash -

该脚本在其他任务中将 NodeSource 仓库添加到你的系统。

在输出的末尾,你将看到一些关于如何安装 Node.js 和 NPM 的附加说明。

因此,要安装 Node.js 和 NPM(Node 包管理器),请运行以下命令:

$ sudo dnf install nodejs -y

安装完成后,按如下所示验证 Node.js 和 NPM 的版本。

$ node -v
$ npm -v

输出显示我们正在运行 Node v18.12,它是最新的 LTS 版本和 NPM 8.19.2。

从官方 RHEL 仓库安装 Node.js

安装 NodeJS 和 NPM 的另一种方法是从发行版的官方仓库中安装它们。但是,这种方法不提供最新版本。

如果你不介意不安装最新版本的 Node 和 NPM。 那么在命令行上运行以下命令。

$ sudo dnf update -y
$ sudo dnf install nodejs npm -y

使用 NVM 安装 Node.js

最后,你可以使用 NVM(Node 版本管理器)安装 Node.js,这是一种用于管理系统上 Node 版本的工具。该工具可帮助开发人员在需要不同版本 Node.js 的不同项目上高效工作。

默认情况下没安装 NVM。你需要通过运行 官方 GitHub 页面 上提供的 Shell 脚本来安装它。

$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash

这会下载 NVM 并将其保存在主目录的 .nvm 目录中。

安装后,关闭终端会话并打开一个新终端。然后运行以下命令确认 NVM 已经安装。

$ command -v nvm

接下来,你可以使用以下命令列出所有可用的 Node.js 版本:

$ nvm ls-remote

或者,你可以列出 Node.js 版本的所有最新 LTS 版本,如图所示。

$ nvm ls-remote | grep -i latest

要安装最新版本的 Node.js(当前为 v19.0.0),请运行以下命令:

$ nvm install node

然后,你可以验证安装的 Node.js 版本,如下所示。

$ node -v

此外,你可以安装特定版本的 Node.js。例如,要安装 v18.2.0,请运行以下命令:

$ nvm install v18.12.0

要列出系统上所有已安装的 NodeJS 版本,请运行以下命令:

$ nvm ls

第一行带有 “->” 符号的条目指向当前使用的 Node.js 版本。然后是其他版本。

要切换到另一个版本的 Node.js,请使用以下语法:

$ nvm use <version>

例如,要使用 Node 版本 19.0.0,请运行以下命令:

$ nvm use 19.0.0

再次检查已安装的 Node.js 版本,这次“->” 符号将指向 v19.0.0。

总结

在本指南中,我们演示了如何使用三种不同的方法安装 Node.js。此外,我们还提供了几种使用 NVM 管理 Node 版本的方法。我们希望可以帮助你轻松地在 RHEL 上安装 NodeJS,并选择你想要在项目中使用的版本。


via: https://www.linuxtechi.com/how-to-install-nodejs-on-rhel/

作者:James Kiarie 选题:lkxed 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在众多可用于简化 Node.js 开发的工具中,以下 9 种是最佳选择。

 title=

我最近在 StackOverflow 上读到了一项调查,该调查称超过 49% 的开发人员在其项目中使用了 Node.js。这结果对我来说并不意外。

作为一个狂热的技术使用者,我可以肯定地说 Node.js 的引入引领了软件开发的新时代。现在,它是软件开发最受欢迎的技术之一,仅次于JavaScript。

Node.js 是什么,为什么如此受欢迎?

Node.js 是一个跨平台的开源运行环境,用于在浏览器之外执行 JavaScript 代码。它也是建立在 Chrome 的 JavaScript 运行时之上的首选运行时环境,主要用于构建快速、可扩展和高效的网络应用程序。

我记得当时我们要花费几个小时来协调前端和后端开发人员,他们分别编写不同脚本。当 Node.js 出现后,所有这些都改变了。我相信,促使开发人员采用这项技术是因为它的双向效率。

使用 Node.js,你可以让你的代码同时运行在客户端和服务器端,从而加快了整个开发过程。Node.js 弥合了前端和后端开发之间的差距,并使开发过程更加高效。

Node.js 工具浪潮

对于 49% 的开发人员(包括我)来说,Node.js 处于在前端和后端开发的金字塔顶端。有大量的 Node.js 用例 帮助我和我的团队在截止日期之内交付复杂的项目。幸运的是,Node.js 的日益普及也产生了一系列开源项目和工具,以帮助开发人员使用该环境。

近来,对使用 Node.js 构建的项目的需求突然增加。有时,我发现管理这些项目,并同时保持交付高质量项目的步伐非常具有挑战性。因此,我决定使用为 Node.js 开发人员提供的许多开源工具中一些最高效的,使某些方面的开发自动化。

根据我在 Node.js 方面的丰富经验,我使用了许多的工具,这些工具对整个开发过程都非常有帮助:从简化编码过程,到监测再到内容管理。

为了帮助我的 Node.js 开发同道,我整理了这个列表,其中包括我最喜欢的 9 个简化 Node.js 开发的开源工具。

Webpack

Webpack 是一个容易使用的 JavaScript 模块捆绑程序 module bundler ,用于简化前端开发。它会检测具有依赖的模块,并将其转换为描述模块的静态 素材 asset

可以通过软件包管理器 npm 或 Yarn 安装该工具。

利用 npm 命令安装如下:

npm install --save-dev webpack

利用 Yarn 命令安装如下:

yarn add webpack --dev

Webpack 可以创建在运行时异步加载的单个捆绑包或多个素材链。不必单独加载。使用 Webpack 工具可以快速高效地打包这些素材并提供服务,从而改善用户整体体验,并减少开发人员在管理加载时间方面的困难。

Strapi

Strapi 是一个开源的 无界面 headless 内容管理系统(CMS)。无界面 CMS 是一种基础软件,可以管理内容而无需预先构建好的前端。它是一个使用 RESTful API 函数的只有后端的系统。

可以通过软件包管理器 Yarn 或 npx 安装 Strapi。

利用 Yarn 命令安装如下:

yarn create strapi-app my-project --quickstart

利用 npx 命令安装如下:

npx create-strapi-app my-project --quickstart

Strapi 的目标是在任何设备上以结构化的方式获取和交付内容。CMS 可以使你轻松管理应用程序的内容,并确保它们是动态的,可以在任何设备上访问。

它提供了许多功能,包括文件上传、内置的电子邮件系统、JSON Web Token(JWT)验证和自动生成文档。我发现它非常方便,因为它简化了整个 CMS,并为我提供了编辑、创建或删除所有类型内容的完全自主权。

另外,通过 Strapi 构建的内容结构非常灵活,因为你可以创建和重用内容组和可定制的 API。

Broccoli

Broccoli 是一个功能强大的构建工具,运行在 ES6 模块上。构建工具是一种软件,可让你将应用程序或网站中的所有各种素材(例如图像、CSS、JavaScript 等)组合成一种可分发的格式。Broccoli 将自己称为 “雄心勃勃的应用程序的素材管道”。

使用 Broccoli 你需要一个项目目录。有了项目目录后,可以使用以下命令通过 npm 安装 Broccoli:

npm install --save-dev broccoli
npm install --global broccoli-cli

你也可以使用 Yarn 进行安装。

当前版本的 Node.js 就是使用该工具的最佳版本,因为它提供了长期支持。它可以帮助你避免进行更新和重新安装过程中的麻烦。安装过程完成后,可以在 Brocfile.js 文件中包含构建规范。

在 Broccoli 中,抽象单位是“树”,该树将文件和子目录存储在特定子目录中。因此,在构建之前,你必须有一个具体的想法,你希望你的构建是什么样子的。

最好的是,Broccoli 带有用于开发的内置服务器,可让你将素材托管在本地 HTTP 服务器上。Broccoli 非常适合流线型重建,因为其简洁的架构和灵活的生态系统可提高重建和编译速度。Broccoli 可让你井井有条,以节省时间并在开发过程中最大限度地提高生产力。

Danger

Danger 是一个非常方便的开源工具,用于简化你的 拉取请求 pull request (PR)检查。正如 Danger 库描述所说,该工具可通过管理 PR 检查来帮助 “正规化” 你的代码审查系统。Danger 可以与你的 CI 集成在一起,帮助你加快审核过程。

将 Danger 与你的项目集成是一个简单的逐步过程:你只需要包括 Danger 模块,并为每个项目创建一个 Danger 文件。然而,创建一个 Danger 帐户(通过 GitHub 或 Bitbucket 很容易做到),并且为开源软件项目设置访问令牌更加方便。

可以通过 NPM 或 Yarn 安装 Danger。要使用 Yarn,请添加 danger -Dpackage.JSON 中。

将 Danger 添加到 CI 后,你可以:

  • 高亮显示重要的创建工件
  • 通过强制链接到 Trello 和 Jira 之类的工具来管理 sprint
  • 强制生成更新日志
  • 使用描述性标签
  • 以及更多

例如,你可以设计一个定义团队文化并为代码审查和 PR 检查设定特定规则的系统。根据 Danger 提供的元数据及其广泛的插件生态系统,可以解决常见的 议题 issue

Snyk

网络安全是开发人员的主要关注点。Snyk 是修复开源组件中漏洞的最著名工具之一。它最初是一个用于修复 Node.js 项目漏洞的项目,并且已经演变为可以检测并修复 Ruby、Java、Python 和 Scala 应用程序中的漏洞。Snyk 主要分四个阶段运行:

  • 查找漏洞依赖性
  • 修复特定漏洞
  • 通过 PR 检查预防安全风险
  • 持续监控应用程序

Snyk 可以集成在项目的任何阶段,包括编码、CI/CD 和报告。我发现这对于测试 Node.js 项目非常有帮助,可以测试或构建 npm 软件包时检查是否存在安全风险。你还可以在 GitHub 中为你的应用程序运行 PR 检查,以使你的项目更安全。Synx 还提供了一系列集成,可用于监控依赖关系并解决特定问题。

要在本地计算机上运行 Snyk,可以通过 NPM 安装它:

npm install -g snyk

Migrat

Migrat 是一款使用纯文本的数据迁移工具,非常易于使用。 它可在各种软件堆栈和进程中工作,从而使其更加实用。你可以使用简单的代码行安装 Migrat:

$ npm install -g migrat

Migrat 并不需要特别的数据库引擎。它支持多节点环境,因为迁移可以在一个全局节点上运行,也可以在每个服务器上运行一次。Migrat 之所以方便,是因为它便于向每个迁移传递上下文。

你可以定义每个迁移的用途(例如,数据库集、连接、日志接口等)。此外,为了避免随意迁移,即多个服务器在全局范围内进行迁移,Migrat 可以在进程运行时进行全局锁定,从而使其只能在全局范围内运行一次。它还附带了一系列用于 SQL 数据库、Slack、HipChat 和 Datadog 仪表盘的插件。你可以将实时迁移状况发送到这些平台中的任何一个。

Clinic.js

Clinic.js 是一个用于 Node.js 项目的开源监视工具。它结合了三种不同的工具 Doctor、Bubbleprof 和 Flame,帮助你监控、检测和解决 Node.js 的性能问题。

你可以通过运行以下命令从 npm 安装 Clinic.js:

$ npm install clinic

你可以根据要监视项目的某个方面以及要生成的报告,选择要使用的 Clinic.js 包含的三个工具中的一个:

  • Doctor 通过注入探针来提供详细的指标,并就项目的总体运行状况提供建议。
  • Bubbleprof 非常适合分析,并使用 async_hooks 生成指标。
  • Flame 非常适合发现代码中的热路径和瓶颈。

PM2

监视是后端开发过程中最重要的方面之一。PM2 是一款 Node.js 的进程管理工具,可帮助开发人员监视项目的多个方面,例如日志、延迟和速度。该工具与 Linux、MacOS 和 Windows 兼容,并支持从 Node.js 8.X 开始的所有 Node.js 版本。

你可以使用以下命令通过 npm 安装 PM2:

$ npm install pm2 --g

如果尚未安装 Node.js,则可以使用以下命令安装:

wget -qO- https://getpm2.com/install.sh | bash

安装完成后,使用以下命令启动应用程序:

$ pm2 start app.js

关于 PM2 最好的地方是可以在集群模式下运行应用程序。可以同时为多个 CPU 内核生成一个进程。这样可以轻松增强应用程序性能并最大程度地提高可靠性。PM2 也非常适合更新工作,因为你可以使用 “热重载” 选项更新应用程序并以零停机时间重新加载应用程序。总体而言,它是为 Node.js 应用程序简化进程管理的好工具。

Electrode

Electrode 是 Walmart Labs 的一个开源应用程序平台。该平台可帮助你以结构化方式构建大规模通用的 React/Node.js 应用程序。

Electrode 应用程序生成器使你可以构建专注于代码的灵活内核,提供一些出色的模块以向应用程序添加复杂功能,并附带了广泛的工具来优化应用程序的 Node.js 包。

可以使用 npm 安装 Electrode。安装完成后,你可以使用 Ignite 启动应用程序,并深入研究 Electrode 应用程序生成器。

你可以使用 NPM 安装 Electrode:

npm install -g electrode-ignite xclap-cli

你最喜欢哪一个?

这些只是不断增长的开源工具列表中的一小部分,在使用 Node.js 时,这些工具可以在不同阶段派上用场。你最喜欢使用哪些开源 Node.js 工具?请在评论中分享你的建议。


via: https://opensource.com/article/20/1/open-source-tools-nodejs

作者:Hiren Dhadhuk 选题:lujun9972 译者:stevenzdg988 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

使用 Node.js 构建一个根据询问创建文件的命令行工具。

当用于构建命令行界面(CLI)时,Node.js 十分有用。在这篇文章中,我将会教你如何使用 Node.js 来构建一个问一些问题并基于回答创建一个文件的命令行工具。

开始

首先,创建一个新的 npm 包(NPM 是 JavaScript 包管理器)。

mkdir my-script
cd my-script
npm init

NPM 将会问一些问题。随后,我们需要安装一些包。

npm install --save chalk figlet inquirer shelljs

这是我们需要的包:

  • Chalk:正确设定终端的字符样式
  • Figlet:使用普通字符制作大字母的程序(LCTT 译注:使用标准字符,拼凑出图片)
  • Inquirer:通用交互式命令行用户界面的集合
  • ShellJS:Node.js 版本的可移植 Unix Shell 命令行工具

创建一个 index.js 文件

现在我们要使用下述内容创建一个 index.js 文件。

#!/usr/bin/env node

const inquirer = require("inquirer");
const chalk = require("chalk");
const figlet = require("figlet");
const shell = require("shelljs");

规划命令行工具

在我们写命令行工具所需的任何代码之前,做计划总是很棒的。这个命令行工具只做一件事:创建一个文件

它将会问两个问题:文件名是什么以及文件后缀名是什么?然后创建文件,并展示一个包含了所创建文件路径的成功信息。

// index.js

const run = async () => {
  // show script introduction
  // ask questions
  // create the file
  // show success message
};

run();

第一个函数只是该脚本的介绍。让我们使用 chalkfiglet 来把它完成。

const init = () => {
  console.log(
    chalk.green(
      figlet.textSync("Node JS CLI", {
        font: "Ghost",
        horizontalLayout: "default",
        verticalLayout: "default"
      })
    )
  );
}

const run = async () => {
  // show script introduction
  init();

  // ask questions
  // create the file
  // show success message
};

run();

然后,我们来写一个函数来问问题。

const askQuestions = () => {
  const questions = [
    {
      name: "FILENAME",
      type: "input",
      message: "What is the name of the file without extension?"
    },
    {
      type: "list",
      name: "EXTENSION",
      message: "What is the file extension?",
      choices: [".rb", ".js", ".php", ".css"],
      filter: function(val) {
        return val.split(".")[1];
      }
    }
  ];
  return inquirer.prompt(questions);
};

// ...

const run = async () => {
  // show script introduction
  init();

  // ask questions
  const answers = await askQuestions();
  const { FILENAME, EXTENSION } = answers;

  // create the file
  // show success message
};

注意,常量 FILENAMEEXTENSIONS 来自 inquirer 包。

下一步将会创建文件。

const createFile = (filename, extension) => {
  const filePath = `${process.cwd()}/${filename}.${extension}`
  shell.touch(filePath);
  return filePath;
};

// ...

const run = async () => {
  // show script introduction
  init();

  // ask questions
  const answers = await askQuestions();
  const { FILENAME, EXTENSION } = answers;

  // create the file
  const filePath = createFile(FILENAME, EXTENSION);

  // show success message
};

最后,重要的是,我们将展示成功信息以及文件路径。

const success = (filepath) => {
  console.log(
    chalk.white.bgGreen.bold(`Done! File created at ${filepath}`)
  );
};

// ...

const run = async () => {
  // show script introduction
  init();

  // ask questions
  const answers = await askQuestions();
  const { FILENAME, EXTENSION } = answers;

  // create the file
  const filePath = createFile(FILENAME, EXTENSION);

  // show success message
  success(filePath);
};

来让我们通过运行 node index.js 来测试这个脚本,这是我们得到的:

完整代码

下述代码为完整代码:

#!/usr/bin/env node

const inquirer = require("inquirer");
const chalk = require("chalk");
const figlet = require("figlet");
const shell = require("shelljs");

const init = () => {
  console.log(
    chalk.green(
      figlet.textSync("Node JS CLI", {
        font: "Ghost",
        horizontalLayout: "default",
        verticalLayout: "default"
      })
    )
  );
};

const askQuestions = () => {
  const questions = [
    {
      name: "FILENAME",
      type: "input",
      message: "What is the name of the file without extension?"
    },
    {
      type: "list",
      name: "EXTENSION",
      message: "What is the file extension?",
      choices: [".rb", ".js", ".php", ".css"],
      filter: function(val) {
        return val.split(".")[1];
      }
    }
  ];
  return inquirer.prompt(questions);
};

const createFile = (filename, extension) => {
  const filePath = `${process.cwd()}/${filename}.${extension}`
  shell.touch(filePath);
  return filePath;
};

const success = filepath => {
  console.log(
    chalk.white.bgGreen.bold(`Done! File created at ${filepath}`)
  );
};

const run = async () => {
  // show script introduction
  init();

  // ask questions
  const answers = await askQuestions();
  const { FILENAME, EXTENSION } = answers;

  // create the file
  const filePath = createFile(FILENAME, EXTENSION);

  // show success message
  success(filePath);
};

run();

使用这个脚本

想要在其它地方执行这个脚本,在你的 package.json 文件中添加一个 bin 部分,并执行 npm link

{
  "name": "creator",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node index.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "chalk": "^2.4.1",
    "figlet": "^1.2.0",
    "inquirer": "^6.0.0",
    "shelljs": "^0.8.2"
  },
  "bin": {
    "creator": "./index.js"
  }
}

执行 npm link 使得这个脚本可以在任何地方调用。

这就是是当你运行这个命令时的结果。

/usr/bin/creator -> /usr/lib/node_modules/creator/index.js
/usr/lib/node_modules/creator -> /home/hugo/code/creator

这会连接 index.js 作为一个可执行文件。这是完全可能的,因为这个 CLI 脚本的第一行是 #!/usr/bin/env node

现在我们可以通过执行如下命令来调用。

$ creator

总结

正如你所看到的,Node.js 使得构建一个好的命令行工具变得非常简单。如果你希望了解更多内容,查看下列包。

  • meow:一个简单的命令行助手工具
  • yargs:一个命令行参数解析工具
  • pkg:将你的 Node.js 程序包装在一个可执行文件中。

在评论中留下你关于构建命令行工具的经验吧!


via: https://opensource.com/article/18/7/node-js-interactive-cli

作者:Hugo Dias 选题:lujun9972 译者:bestony 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

NPM 是 Node Package Manager (node 包管理器)的缩写,它是用于安装 NodeJS 软件包或模块的命令行软件包管理器。我们发布过一个指南描述了如何使用 NPM 管理 NodeJS 包。你可能已经注意到,使用 Npm 管理 NodeJS 包或模块并不是什么大问题。但是,如果你不习惯用 CLI 的方式,这有一个名为 NDM 的桌面 GUI 程序,它可用于管理 NodeJS 程序/模块。 NDM,代表 NPM Desktop Manager (npm 桌面管理器),是 NPM 的自由开源图形前端,它允许我们通过简单图形桌面安装、更新、删除 NodeJS 包。

在这个简短的教程中,我们将了解 Linux 中的 Ndm。

安装 NDM

NDM 在 AUR 中可用,因此你可以在 Arch Linux 及其衍生版(如 Antergos 和 Manjaro Linux)上使用任何 AUR 助手程序安装。

使用 Pacaur

$ pacaur -S ndm

使用 Packer

$ packer -S ndm

使用 Trizen

$ trizen -S ndm

使用 Yay

$ yay -S ndm

使用 Yaourt

$ yaourt -S ndm

在基于 RHEL 的系统(如 CentOS)上,运行以下命令以安装 NDM。

$ echo "[fury] name=ndm repository baseurl=https://repo.fury.io/720kb/ enabled=1 gpgcheck=0" | sudo tee /etc/yum.repos.d/ndm.repo && sudo yum update &&

在 Debian、Ubuntu、Linux Mint:

$ echo "deb [trusted=yes] https://apt.fury.io/720kb/ /" | sudo tee /etc/apt/sources.list.d/ndm.list && sudo apt-get update && sudo apt-get install ndm

也可以使用 Linuxbrew 安装 NDM。首先,按照以下链接中的说明安装 Linuxbrew。

安装 Linuxbrew 后,可以使用以下命令安装 NDM:

$ brew update
$ brew install ndm

在其他 Linux 发行版上,进入 NDM 发布页面,下载最新版本,自行编译和安装。

NDM 使用

从菜单或使用应用启动器启动 NDM。这就是 NDM 的默认界面。

在这里你可以本地或全局安装 NodeJS 包/模块。

本地安装 NodeJS 包

要在本地安装软件包,首先通过单击主屏幕上的 “Add projects” 按钮选择项目目录,然后选择要保留项目文件的目录。例如,我选择了一个名为 “demo” 的目录作为我的项目目录。

单击项目目录(即 demo),然后单击 “Add packages” 按钮。

输入要安装的软件包名称,然后单击 “Install” 按钮。

安装后,软件包将列在项目目录下。只需单击该目录即可在本地查看已安装软件包的列表。

同样,你可以创建单独的项目目录并在其中安装 NodeJS 模块。要查看项目中已安装模块的列表,请单击项目目录,右侧将显示软件包。

全局安装 NodeJS 包

要全局安装 NodeJS 包,请单击主界面左侧的 “Globals” 按钮。然后,单击 “Add packages” 按钮,输入包的名称并单击 “Install” 按钮。

管理包

单击任何已安装的包,不将在顶部看到各种选项,例如:

  1. 版本(查看已安装的版本),
  2. 最新(安装最新版本),
  3. 更新(更新当前选定的包),
  4. 卸载(删除所选包)等。

NDM 还有两个选项,即 “Update npm” 用于将 node 包管理器更新成最新可用版本, 而 “Doctor” 会运行一组检查以确保你的 npm 安装有所需的功能管理你的包/模块。

总结

NDM 使安装、更新、删除 NodeJS 包的过程更加容易!你无需记住执行这些任务的命令。NDM 让我们在简单的图形界面中点击几下鼠标即可完成所有操作。对于那些懒得输入命令的人来说,NDM 是管理 NodeJS 包的完美伴侣。

干杯!


via: https://www.ostechnix.com/ndm-a-desktop-gui-application-for-npm/

作者:SK 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

超过 3 亿用户正在使用 Stream。这些用户全都依赖我们的框架,而我们十分擅长测试要放到生产环境中的任何东西。我们大部分的代码库是用 Go 语言编写的,剩下的部分则是用 Python 编写。

我们最新的展示应用,Winds 2.0,是用 Node.js 构建的,很快我们就了解到测试 Go 和 Python 的常规方法并不适合它。而且,创造一个好的测试套件需要用 Node.js 做很多额外的工作,因为我们正在使用的框架没有提供任何内建的测试功能。

不论你用什么语言,要构建完好的测试框架可能都非常复杂。本文我们会展示 Node.js 测试过程中的困难部分,以及我们在 Winds 2.0 中用到的各种工具,并且在你要编写下一个测试集合时为你指明正确的方向。

为什么测试如此重要

我们都向生产环境中推送过糟糕的提交,并且遭受了其后果。碰到这样的情况不是好事。编写一个稳固的测试套件不仅仅是一个明智的检测,而且它还让你能够完全地重构代码,并自信重构之后的代码仍然可以正常运行。这在你刚刚开始编写代码的时候尤为重要。

如果你是与团队共事,达到测试覆盖率极其重要。没有它,团队中的其他开发者几乎不可能知道他们所做的工作是否导致重大变动(或破坏)。

编写测试同时会促进你和你的队友把代码分割成更小的片段。这让别人去理解你的代码和修改 bug 变得容易多了。产品收益变得更大,因为你能更早的发现 bug。

最后,没有测试,你的基本代码还不如一堆纸片。基本不能保证你的代码是稳定的。

困难的部分

在我看来,我们在 Winds 中遇到的大多数测试问题是 Node.js 中特有的。它的生态系统一直在变大。例如,如果你用的是 macOS,运行 brew upgrade(安装了 homebrew),你看到你一个新版本的 Node.js 的概率非常高。由于 Node.js 迭代频繁,相应的库也紧随其后,想要与最新的库保持同步非常困难。

以下是一些马上映入脑海的痛点:

  1. 在 Node.js 中进行测试是非常主观而又不主观的。人们对于如何构建一个测试架构以及如何检验成功有不同的看法。沮丧的是还没有一个黄金准则规定你应该如何进行测试。
  2. 有一堆框架能够用在你的应用里。但是它们一般都很精简,没有完好的配置或者启动过程。这会导致非常常见的副作用,而且还很难检测到;所以你最终会想要从零开始编写自己的 测试执行平台 test runner 测试执行平台。
  3. 几乎可以保证你 需要 编写自己的测试执行平台(马上就会讲到这一节)。

以上列出的情况不是理想的,而且这是 Node.js 社区应该尽管处理的事情。如果其他语言解决了这些问题,我认为也是作为广泛使用的语言, Node.js 解决这些问题的时候。

编写你自己的测试执行平台

所以……你可能会好奇test runner测试执行平台 什么,说实话,它并不复杂。测试执行平台是测试套件中最高层的容器。它允许你指定全局配置和环境,还可以导入配置。可能有人觉得做这个很简单,对吧?别那么快下结论。

我们所了解到的是,尽管现在就有足够多的测试框架了,但没有一个测试框架为 Node.js 提供了构建你的测试执行平台的标准方式。不幸的是,这需要开发者来完成。这里有个关于测试执行平台的需求的简单总结:

  • 能够加载不同的配置(比如,本地的、测试的、开发的),并确保你 永远不会 加载一个生产环境的配置 —— 你能想象出那样会出什么问题。
  • 播种数据库——产生用于测试的数据。必须要支持多种数据库,不论是 MySQL、PostgreSQL、MongoDB 或者其它任何一个数据库。
  • 能够加载配置(带有用于开发环境测试的播种数据的文件)。

开发 Winds 的时候,我们选择 Mocha 作为测试执行平台。Mocha 提供了简单并且可编程的方式,通过命令行工具(整合了 Babel)来运行 ES6 代码的测试。

为了进行测试,我们注册了自己的 Babel 模块引导器。这为我们提供了更细的粒度,更强大的控制,在 Babel 覆盖掉 Node.js 模块加载过程前,对导入的模块进行控制,让我们有机会在所有测试运行前对模块进行模拟。

此外,我们还使用了 Mocha 的测试执行平台特性,预先把特定的请求赋给 HTTP 管理器。我们这么做是因为常规的初始化代码在测试中不会运行(服务器交互是用 Chai HTTP 插件模拟的),还要做一些安全性检查来确保我们不会连接到生产环境数据库。

尽管这不是测试执行平台的一部分,有一个 配置 fixture 加载器也是我们测试套件中的重要的一部分。我们试验过已有的解决方案;然而,我们最终决定编写自己的助手程序,这样它就能贴合我们的需求。根据我们的解决方案,在生成或手动编写配置时,通过遵循简单专有的协议,我们就能加载数据依赖很复杂的配置。

Winds 中用到的工具

尽管过程很冗长,我们还是能够合理使用框架和工具,使得针对后台 API 进行的适当测试变成现实。这里是我们选择使用的工具:

Mocha

Mocha,被称为 “运行在 Node.js 上的特性丰富的测试框架”,是我们用于该任务的首选工具。拥有超过 15K 的星标,很多支持者和贡献者,我们知道对于这种任务,这是正确的框架。

Chai

然后是我们的断言库。我们选择使用传统方法,也就是最适合配合 Mocha 使用的 —— Chai。Chai 是一个用于 Node.js,适合 BDD 和 TDD 模式的断言库。拥有简单的 API,Chai 很容易整合进我们的应用,让我们能够轻松地断言出我们 期望 从 Winds API 中返回的应该是什么。最棒的地方在于,用 Chai 编写测试让人觉得很自然。这是一个简短的例子:

describe('retrieve user', () => {
    let user;

    before(async () => {
        await loadFixture('user');
        user = await User.findOne({email: authUser.email});
        expect(user).to.not.be.null;
    });

    after(async () => {
        await User.remove().exec();
    });

    describe('valid request', () => {
        it('should return 200 and the user resource, including the email field, when retrieving the authenticated user', async () => {
            const response = await withLogin(request(api).get(`/users/${user._id}`), authUser);

            expect(response).to.have.status(200);
            expect(response.body._id).to.equal(user._id.toString());
        });

        it('should return 200 and the user resource, excluding the email field, when retrieving another user', async () => {
            const anotherUser = await User.findOne({email: '[email protected]'});

            const response = await withLogin(request(api).get(`/users/${anotherUser.id}`), authUser);

            expect(response).to.have.status(200);
            expect(response.body._id).to.equal(anotherUser._id.toString());
            expect(response.body).to.not.have.an('email');
        });

    });

    describe('invalid requests', () => {

        it('should return 404 if requested user does not exist', async () => {
            const nonExistingId = '5b10e1c601e9b8702ccfb974';
            expect(await User.findOne({_id: nonExistingId})).to.be.null;

            const response = await withLogin(request(api).get(`/users/${nonExistingId}`), authUser);
            expect(response).to.have.status(404);
        });
    });

});

Sinon

拥有与任何单元测试框架相适应的能力,Sinon 是模拟库的首选。而且,精简安装带来的超级整洁的整合,让 Sinon 把模拟请求变成了简单而轻松的过程。它的网站有极其良好的用户体验,并且提供简单的步骤,供你将 Sinon 整合进自己的测试框架中。

Nock

对于所有外部的 HTTP 请求,我们使用健壮的 HTTP 模拟库 nock,在你要和第三方 API 交互时非常易用(比如说 Stream 的 REST API)。它做的事情非常酷炫,这就是我们喜欢它的原因,除此之外关于这个精妙的库没有什么要多说的了。这是我们的速成示例,调用我们在 Stream 引擎中提供的 personalization

nock(config.stream.baseUrl)
    .get(/winds_article_recommendations/)
    .reply(200, { results: [{foreign_id:`article:${article.id}`}] });

Mock-require

mock-require 库允许依赖外部代码。用一行代码,你就可以替换一个模块,并且当代码尝试导入这个库时,将会产生模拟请求。这是一个小巧但稳定的库,我们是它的超级粉丝。

Istanbul

Istanbul 是 JavaScript 代码覆盖工具,在运行测试的时候,通过模块钩子自动添加覆盖率,可以计算语句,行数,函数和分支覆盖率。尽管我们有相似功能的 CodeCov(见下一节),进行本地测试时,这仍然是一个很棒的工具。

最终结果 — 运行测试

有了这些库,还有之前提过的测试执行平台,现在让我们看看什么是完整的测试(你可以在 这里 看看我们完整的测试套件):

import nock from 'nock';
import { expect, request } from 'chai';

import api from '../../src/server';
import Article from '../../src/models/article';
import config from '../../src/config';
import { dropDBs, loadFixture, withLogin } from '../utils.js';

describe('Article controller', () => {
    let article;

    before(async () => {
        await dropDBs();
        await loadFixture('initial-data', 'articles');
        article = await Article.findOne({});
        expect(article).to.not.be.null;
        expect(article.rss).to.not.be.null;
    });

    describe('get', () => {
        it('should return the right article via /articles/:articleId', async () => {
            let response = await withLogin(request(api).get(`/articles/${article.id}`));
            expect(response).to.have.status(200);
        });
    });

    describe('get parsed article', () => {
        it('should return the parsed version of the article', async () => {
            const response = await withLogin(
                request(api).get(`/articles/${article.id}`).query({ type: 'parsed' })
            );
            expect(response).to.have.status(200);
        });
    });

    describe('list', () => {
        it('should return the list of articles', async () => {
            let response = await withLogin(request(api).get('/articles'));
            expect(response).to.have.status(200);
        });
    });

    describe('list from personalization', () => {
        after(function () {
            nock.cleanAll();
        });

        it('should return the list of articles', async () => {
            nock(config.stream.baseUrl)
                .get(/winds_article_recommendations/)
                .reply(200, { results: [{foreign_id:`article:${article.id}`}] });

            const response = await withLogin(
                request(api).get('/articles').query({
                    type: 'recommended',
                })
            );
            expect(response).to.have.status(200);
            expect(response.body.length).to.be.at.least(1);
            expect(response.body[0].url).to.eq(article.url);
        });
    });
});

持续集成

有很多可用的持续集成服务,但我们钟爱 Travis CI,因为他们和我们一样喜爱开源环境。考虑到 Winds 是开源的,它再合适不过了。

我们的集成非常简单 —— 我们用 [.travis.yml] 文件设置环境,通过简单的 npm 命令进行测试。测试覆盖率反馈给 GitHub,在 GitHub 上我们将清楚地看出我们最新的代码或者 PR 是不是通过了测试。GitHub 集成很棒,因为它可以自动查询 Travis CI 获取结果。以下是一个在 GitHub 上看到 (经过了测试的) PR 的简单截图:

除了 Travis CI,我们还用到了叫做 CodeCov 的工具。CodeCov 和 [Istanbul] 很像,但它是个可视化的工具,方便我们查看代码覆盖率、文件变动、行数变化,还有其他各种小玩意儿。尽管不用 CodeCov 也可以可视化数据,但把所有东西囊括在一个地方也很不错。

我们学到了什么

在开发我们的测试套件的整个过程中,我们学到了很多东西。开发时没有所谓“正确”的方法,我们决定开始创造自己的测试流程,通过理清楚可用的库,找到那些足够有用的东西添加到我们的工具箱中。

最终我们学到的是,在 Node.js 中进行测试不是听上去那么简单。还好,随着 Node.js 持续完善,社区将会聚集力量,构建一个坚固稳健的库,可以用“正确”的方式处理所有和测试相关的东西。

但在那时到来之前,我们还会接着用自己的测试套件,它开源在 Winds 的 GitHub 仓库

局限

创建配置没有简单的方法

有的框架和语言,就如 Python 中的 Django,有简单的方式来创建配置。比如,你可以使用下面这些 Django 命令,把数据导出到文件中来自动化配置的创建过程:

以下命令会把整个数据库导出到 db.json 文件中:

./manage.py dumpdata > db.json

以下命令仅导出 django 中 admin.logentry 表里的内容:

./manage.py dumpdata admin.logentry > logentry.json

以下命令会导出 auth.user 表中的内容:

./manage.py dumpdata auth.user > user.json

Node.js 里面没有创建配置的简单方式。我们最后做的事情是用 MongoDB Compass 工具导出数据到 JSON 中。这生成了不错的配置,如下图(但是,这是个乏味的过程,肯定会出错):

使用 Babel,模拟模块和 Mocha 测试执行平台时,模块加载不直观

为了支持多种 node 版本,和获取 JavaScript 标准的最新附件,我们使用 Babel 把 ES6 代码转换成 ES5。Node.js 模块系统基于 CommonJS 标准,而 ES6 模块系统中有不同的语义。

Babel 在 Node.js 模块系统的顶层模拟 ES6 模块语义,但由于我们要使用 mock-require 来介入模块的加载,所以我们经历了罕见的怪异的模块加载过程,这看上去很不直观,而且能导致在整个代码中,导入的、初始化的和使用的模块有不同的版本。这使测试时的模拟过程和全局状态管理复杂化了。

在使用 ES6 模块时声明的函数,模块内部的函数,都无法模拟

当一个模块导出多个函数,其中一个函数调用了其他的函数,就不可能模拟使用在模块内部的函数。原因在于当你引用一个 ES6 模块时,你得到的引用集合和模块内部的是不同的。任何重新绑定引用,将其指向新值的尝试都无法真正影响模块内部的函数,内部函数仍然使用的是原始的函数。

最后的思考

测试 Node.js 应用是复杂的过程,因为它的生态系统总在发展。掌握最新和最好的工具很重要,这样你就不会掉队了。

如今有很多方式获取 JavaScript 相关的新闻,导致与时俱进很难。关注邮件新闻刊物如 JavaScript WeeklyNode Weekly 是良好的开始。还有,关注一些 reddit 子模块如 /r/node 也不错。如果你喜欢了解最新的趋势,State of JS 在测试领域帮助开发者可视化趋势方面就做的很好。

最后,这里是一些我喜欢的博客,我经常在这上面发文章:

觉得我遗漏了某些重要的东西?在评论区或者 Twitter @NickParsons 让我知道。

还有,如果你想要了解 Stream,我们的网站上有很棒的 5 分钟教程。点 这里 进行查看。


作者简介:

Nick Parsons

Dreamer. Doer. Engineer. Developer Evangelist https://getstream.io.


via: https://hackernoon.com/testing-node-js-in-2018-10a04dd77391

作者:Nick Parsons 译者:BriFuture 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在 XO 公司,我们最初使用 Node 和 Ruby 构建相互连接的服务系统。我们享受 Node 带来的明显性能优势,以及可以访问已有的大型软件包仓库。我们也可以轻松地在公司内部发布并复用已有的插件和模块。极大地提高了开发效率,使得我们可以快速编写出可拓展的和可靠的应用。而且,庞大的 Node 社区使我们的工程师向开源软件贡献更加容易(比如 BunnyBusFelicity)。

虽然我在大学时期和刚刚工作的一些时间在使用更严谨的编译语言,比如 C++ 和 C#,而后来我开始使用 JavaScript。我很喜欢它的自由和灵活,但是我最近开始怀念静态和结构化的语言,因为当时有一个同事让我对 Go 语言产生了兴趣。

我从写 JavaScript 到写 Go,我发现两种语言有很多相似之处。两者学习起来都很快并且易于上手,都具有充满表现力的语法,并且在开发者社区中都有很多工作机会。没有完美的编程语言,所以你应该总是选择一个适合手头项目的语言。在这篇文章中,我将要说明这两种语言深层次上的关键区别,希望能鼓励没有用过 Go 语言的用户可以有机会使用 Go 。

大体上的差异

在深入细节之前,我们应该先了解一下两种语言之间的重要区别。

Go,或称 Golang,是 Google 在 2007 年创建的自由开源编程语言。它以快速和简单为设计目标。Go 被直接编译成机器码,这就是它速度的来源。使用编译语言调试是相当容易的,因为你可以在早期捕获大量错误。Go 也是一种强类型的语言,它有助于数据完整,并可以在编译时查找类型错误。

另一方面,JavaScript 是一种弱类型语言。除了忽略验证数据的类型和真值判断陷阱所带来的额外负担之外,使用弱类型语言也有自己的好处。比起使用 接口 interfaces 范型 generics 柯里化 currying 可变的形参个数 flexible arity 让函数变得更加灵活。JavaScript 在运行时进行解释,这可能导致错误处理和调试的问题。Node 是一款基于 Google V8 虚拟机的 JavaScript 运行库,这使它成为一个轻量和快速的 Web 开发平台。

语法

作为原来的 JavaScript 开发者,Go 简单和直观的语法很吸引我。由于两种语言的语法可以说都是从 C 语言演变而来的,所以它们的语法有很多相同之处。Go 被普遍认为是一种“容易学习的语言”。那是因为它的对开发者友好的工具、精简的语法和固守惯例(LCTT 译注:惯例优先)。

Go 包含大量有助于简化开发的内置特性。你可以用标准 Go 构建工具把你的程序用 go build 命令编译成二进制可执行文件。使用内置的测试套件进行测试只需要运行 go test 即可。 诸如原生支持的并发等特性甚至在语言层面上提供。

Google 的 Go 开发者认为,现在的编程太复杂了,太多的“记账一样,重复劳动和文书工作”。这就是为什么 Go 的语法被设计得如此简单和干净,以减少混乱、提高效率和增强可读性。它还鼓励开发人员编写明确的、易于理解的代码。Go 只有 25 个保留关键字和一种循环(for 循环),而不像 JavaScript 有 大约 84 个关键字(包括保留关键字字、对象、属性和方法)。

为了说明语法的一些差异和相似之处,我们来看几个例子:

  • 标点符号: Go 去除了所有多余的符号以提高效率和可读性。尽管 JavaScript 中需要符号的地方也不多(参见: Lisp),而且经常是可选的,但我更加喜欢 Go 的简单。
// JavaScript 的逗号和分号
for (var i = 0; i < 10; i++) {
console.log(i);
}

JavaScript 中的标点

// Go 使用最少数量标点
for i := 0; i < 10; i++ {
fmt.Println(i)
}

Go 中的标点

  • 赋值:由于 Go 是强类型语言,所以你在初始化变量时可以使用 := 操作符来进行类型推断,以避免重复声明,而 JavaScript 则在运行时声明类型。
// JavaScript 赋值
var foo = "bar";

JavaScript 中的赋值

// Go 的赋值
var foo string //不使用类型推导
foo = "bar"
foo := "bar" //使用类型推导

Go 的赋值

  • 导出:在 JavaScript 中,你必须从某个模块中显式地导出。 在 Go 中,任何大写的函数将被默认导出。
const Bar = () => {};
module.exports = {
Bar
}

JavaScript 中的导出

// Go 中的导出
package foo // 定义包名
func Bar (s string) string {
// Bar 将被导出
}

Go 中的导出

  • 导入:在 JavaScript 中 required 库是导入依赖项和模块所必需的,而 Go 则利用原生的 import 关键字通过包的路径导入模块。另一个区别是,与 Node 的中央 NPM 存储库不同,Go 使用 URL 作为路径来导入非标准库的包,这是为了从包的源码仓库直接克隆依赖。
// Javascript 的导入
var foo = require('foo');
foo.bar();

JavaScript 的导入

// Go 的导入
import (
"fmt" // Go 的标准库部分
"github.com/foo/foo" // 直接从仓库导入
)
foo.Bar()

Go 的导入

  • 返回值:通过 Go 的多值返回特性可以优雅地传递和处理返回值和错误,并且通过传递引用减少了不正确的值传递。在 JavaScript 中需要通过一个对象或者数组来返回多个值。
// Javascript - 返回多值
function foo() {
return {a: 1, b: 2};
}
const { a, b } = foo();

JavaScript 的返回

// Go - 返回多值
func foo() (int, int) {
return 1, 2
}
a, b := foo()

Go 的返回

  • 错误处理:Go 推荐在错误出现的地方捕获它们,而不是像 Node 一样在回调中让错误冒泡。
// Node 的错误处理
foo('bar', function(err, data) {
// 处理错误
}

JavaScript 的错误处理

//Go 的错误处理
foo, err := bar()
if err != nil {
// 用 defer、 panic、 recover 或 log.fatal 等等处理错误.
}

Go 的错误处理

  • 可变参数函数:Go 和 JavaScript 的函数都支持传入不定数量的参数。
function foo (...args) {
console.log(args.length);
}
foo(); // 0
foo(1, 2, 3); // 3

JavaScript 中的可变参数函数

func foo (args ...int) {
fmt.Println(len(args))
}
func main() {
foo() // 0
foo(1,2,3) // 3
}

Go 中的可变参数函数

社区

当比较 Go 和 Node 提供的编程范式哪种更方便时,两边都有不同的拥护者。Node 在软件包数量和社区的大小上完全胜过了 Go。Node 包管理器(NPM),是世界上最大的软件仓库,拥有超过 410,000 个软件包,每天以 555 个新软件包的惊人速度增长。这个数字可能看起来令人吃惊(确实是),但是需要注意的是,这些包许多是重复的,且质量不足以用在生产环境。 相比之下,Go 大约有 13 万个包。

Node 和 Go 包的数量

尽管 Node 和 Go 岁数相仿,但 JavaScript 使用更加广泛,并拥有巨大的开发者和开源社区。因为 Node 是为所有人开发的,并在开始的时候就带有一个强壮的包管理器,而 Go 是特地为 Google 开发的。下面的Spectrum 排行榜显示了当前流行的的顶尖 Web 开发语言。

Web 开发语言排行榜前 7 名

JavaScript 的受欢迎程度近年来似乎保持相对稳定,而 Go 一直在保持上升趋势

编程语言趋势

性能

如果你的主要关注点是速度呢?当今似乎人们比以前更重视性能的优化。用户不喜欢等待信息。 事实上,如果网页的加载时间超过 3 秒,40% 的用户会放弃访问您的网站

因为它的非阻塞异步 I/O,Node 经常被认为是高性能的语言。另外,正如我之前提到的,Node 运行在针对动态语言进行了优化的 Google V8 引擎上。而 Go 的设计也考虑到速度。Google 的开发者们通过建立了一个“充满表现力而轻量级的类型系统;并发和垃圾回收机制;强制地指定依赖版本等等”,达成了这一目标。

我运行了一些测试来比较 Node 和 Go 之间的性能。这些测试注重于语言提供的初级能力。如果我准备测试例如 HTTP 请求或者 CPU 密集型运算,我会使用 Go 语言级别的并发工具(goroutines/channels)。但是我更注重于各个语言提供的基本特性(参见 三种并发方法 了解关于 goroutines 和 channels 的更多知识)。

我在基准测试中也加入了 Python,所以无论如何我们对 Node 和 Go 的结果都很满意。

循环/算术

迭代十亿项并把它们相加:

var r = 0;
for (var c = 0; c < 1000000000; c++) {
    r += c;
}

Node

package main
func main() {
    var r int
    for c := 0; c < 1000000000; c++ {
        r += c
    }
}

Go

sum(xrange(1000000000))

Python

结果

这里的输家无疑是 Python,花了超过 7 秒的 CPU 时间。而 Node 和 Go 都相当高效,分别用了 900 ms 和 408 ms。

修正:由于一些评论表明 Python 的性能还可以提高。我更新了结果来反映这些变化。同时,使用 PyPy 大大地提高了性能。当使用 Python 3.6.1 和 PyPy 3.5.7 运行时,性能提升到 1.234 秒,但仍然不及 Go 和 Node 。

I/O

遍历一百万个数字并将其写入一个文件。

var fs = require('fs');
var wstream = fs.createWriteStream('node');

for (var c = 0; c < 1000000; ++c) {
  wstream.write(c.toString());
}
wstream.end();

Node

package main

import (
    "bufio"
    "os"
    "strconv"
)

func main() {
    file, _ := os.Create("go")
    b := bufio.NewWriter(file)
    for c := 0; c < 1000000; c++ {
        num := strconv.Itoa(c)
        b.WriteString(num)
    }
    file.Close()
}

Go

with open("python", "a") as text_file:
    for i in range(1000000):
        text_file.write(str(i))

Python

结果

Python 以 7.82 秒再次排名第三。 这次测试中,Node 和 Go 之间的差距很大,Node 花费大约 1.172 秒,Go 花费了 213 毫秒。真正令人印象深刻的是,Go 大部分的处理时间花费在编译上。如果我们将代码编译,以二进制运行,这个 I/O 测试仅花费 78 毫秒——要比 Node 快 15 倍。

修正:修改了 Go 代码以实现缓存 I/O。

冒泡排序

将含有十个元素的数组排序一千万次。

function bubbleSort(input) {
    var n = input.length;
    var swapped = true;
    while (swapped) {
        swapped = false;
        for (var i = 0; i < n; i++) {
            if (input[i - 1] > input [i]) {
                [input[i], input[i - 1]] = [input[i - 1], input[i]];
                swapped = true;
            }
        }
    }
}

for (var c = 0; c < 1000000; c++) {
    const toBeSorted = [1, 3, 2, 4, 8, 6, 7, 2, 3, 0];
    bubbleSort(toBeSorted);
}

Node

package main

var toBeSorted [10]int = [10]int{1, 3, 2, 4, 8, 6, 7, 2, 3, 0}

func bubbleSort(input [10]int) {
    n := len(input)
    swapped := true
    for swapped {
        swapped = false
        for i := 1; i < n; i++ {
            if input[i-1] > input[i] {
                input[i], input[i-1] = input[i-1], input[i]
                swapped = true
            }
        }
    }
}

func main() {
    for c := 0; c < 1000000; c++ {
        bubbleSort(toBeSorted)
    }
}

Go

def bubbleSort(input):
    length = len(input)
    swapped = True

    while swapped:
        swapped = False
        for i in range(1,length):
            if input[i - 1] > input[i]:
                input[i], input[i - 1] = input[i - 1], input[i]
                swapped = True

for i in range(1000000):
    toBeSorted = [1, 3, 2, 4, 8, 6, 7, 2, 3, 0]
    bubbleSort(toBeSorted)

Python

结果

像刚才一样,Python 的表现是最差的,大约花费 15 秒完成了任务。 Go 完成任务的速度是 Node 的 16 倍。

判决

Go 无疑是这三个测试中的赢家,而 Node 大部分表现都很出色。Python 也表现不错。要清楚,性能不是选择编程语言需要考虑的全部内容。如果您的应用不需要处理大量数据,那么 Node 和 Go 之间的性能差异可能是微不足道的。 有关性能的一些其他比较,请参阅以下内容:

结论

这个帖子不是为了证明一种语言比另一种语言更好。由于各种原因,每种编程语言都在软件开发社区中占有一席之地。 我的意图是强调 Go 和 Node 之间的差异,并且促进展示一种新的 Web 开发语言。 在为一个项目选择语言时,有各种因素需要考虑,比如开发人员的熟悉程度、花费和实用性。 我鼓励在决定哪种语言适合您时进行一次彻底的底层分析。

正如我们所看到的,Go 有如下的优点:接近底层语言的性能,简单的语法和相对简单的学习曲线使它成为构建可拓展和安全的 Web 应用的理想选择。随着 Go 的使用率和社区活动的快速增长,它将会成为现代网络开发中的重要角色。话虽如此,我相信如果 Node 被正确地实现,它正在向正确的方向努力,仍然是一种强大而有用的语言。它具有大量的追随者和活跃的社区,使其成为一个简单的平台,可以让 Web 应用在任何时候启动和运行。

资料

如果你对学习 Go 语言感兴趣,可以参阅下面的资源:


via: https://medium.com/xo-tech/from-node-to-go-a-high-level-comparison-56c8b717324a#.byltlz535

作者:John Stamatakos 译者:trnhoe 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出