如何在 Node.js 中使用 ES6 导入? [复制]

Posted

技术标签:

【中文标题】如何在 Node.js 中使用 ES6 导入? [复制]【英文标题】:How can I use an ES6 import in Node.js? [duplicate] 【发布时间】:2018-02-01 21:31:10 【问题描述】:

我正在尝试在 Node.js 中掌握 ES6 导入的窍门,并尝试使用此示例中提供的语法:

Cheatsheet Link

我正在查看the support table,但找不到支持新导入语句的版本(我尝试查找文本导入/要求)。我目前正在运行 Node.js 8.1.2,并且还相信由于备忘单指的是 .js 文件,因此它应该适用于 .js 文件。

当我运行代码时(取自备忘单的第一个示例):

import  square, diag  from 'lib';

我得到错误:

SyntaxError:意外的令牌导入。

对我正在尝试导入的库的引用:

//------ lib.js ------
export const sqrt = Math.sqrt;
export function square(x) 
    return x * x;

export function diag(x, y) 
    return sqrt(square(x) + square(y));

我缺少什么以及如何让node 识别我的import 声明?

【问题讨论】:

使用这种语法,当你在一半教程的第一行卡住时,“到处都是相同的语言”就这么多了。 我们到了吗?? @Larrydx 之类的。 Nodejs v13 需要在当前或父目录中的某个位置有 package.json 和 "type": "module",您可以使用 ES6 导入。来自文档:Files ending with .js or lacking any extension will be loaded as ES modules when the nearest parent package.json file contains a top-level field "type" with a value of "module". 在此处查看更多信息:nodejs.org/api/esm.html#esm_package_json_type_field @Madeo 似乎不再需要转译了? 为此创建了一个仓库:github.com/jasonjin220/es6-express-rest-api-boilerplate 【参考方案1】:

Node.js 包含对 ES6 支持的实验性支持。 在此处阅读更多信息:https://nodejs.org/docs/latest-v13.x/api/esm.html#esm_enabling。

TLDR;

Node.js >= v13

在 Node.js 13 及更高版本中非常简单。您需要:

.mjs 扩展名保存文件,或 在最近的package.json中添加 "type": "module"

您只需执行上述操作之一即可使用 ECMAScript 模块。

Node.js

如果您使用的是 Node.js 版本 9.6 - 12,保存 带有扩展名为 .mjs 的 ES6 模块的文件并运行它:

node --experimental-modules my-app.mjs

【讨论】:

@tbking,谢谢你的文章。了解我们的工作很重要。对不起,请您添加工作示例吗?它应该只有 2-3 行:依赖项的导入,然后是目标类的导入,然后创建实例。 工作示例见***.com/a/50641589/984471 好吧,我试过这个方法,但是在 .mjs 文件中有一个 require 语句,然后抛出一个错误'require is not defined'或其他东西 如果您在 package.json 中包含 "type": "module" 以及标志 node --experimental-modules my-app.js,您也可以使用 .js 文件扩展名 那个答案对我有帮助!如果有人需要,我添加了一个使用 Typescript 的示例:github.com/Urigo/typescript-node-es-modules-example【参考方案2】:

你可以试试esm

这里有一些介绍:esm

【讨论】:

这是一个不错的选择,尤其是在 TC39 还悬而未决的时候。【参考方案3】:

如果您在服务器端使用模块系统,则根本不需要使用Babel。要在 Node.js 中使用模块,请确保:

    使用支持 --experimental-modules 标志的节点版本 您的 *.js 文件必须重命名为 *.mjs

就是这样。

然而,这是一个很大的问题,虽然您的纯 ES6 代码将在 Node.js 之类的环境中运行(例如,9.5.0),但您仍然会疯狂地进行转换以进行测试。还要记住,Ecma 已经声明 javascript 的发布周期将会更快,并且会更定期地提供更新的功能。虽然这对于像 Node.js 这样的单一环境来说没有问题,但对于浏览器环境来说这是一个稍微不同的主张。很明显,测试框架在迎头赶上方面有很多工作要做。您可能仍然需要为测试框架进行转换。我建议使用Jest。

还要注意捆绑框架。你会在那里遇到问题。

【讨论】:

你有这方面的文件吗? 这适用于节点 9.X 但将适用于 v8.6 我相信nodejs.org/dist/latest-v9.x/docs/api/all.html#esm_enabling 你为什么推荐 Jest?我对 Jest 也有同样的问题。例如,不能将此库与 Jest 一起使用:github.com/mrichar1/jsonapi-vuex/issues/104。你有办法让它工作吗?【参考方案4】:

回到Jonathan002原来的问题

"...什么版本支持新的 ES6 import 语句?"

基于 article by Dr. Axel Rauschmayer,计划在 Node.js 10.x LTS 中默认支持它(不带实验性命令行标志)。根据node.js's release plan 的消息,它于 2018 年 3 月 29 日发布,它可能会在 2018 年 4 月之后上市,而 LTS 将于 2018 年 10 月开始。

【讨论】:

已经添加了吗:? @RanaTallal Node 10 api 仍然显示标志 @RanaTallal:我也想知道。节点确实仍然有标志。但我目前正在学习 Angular 6 课程,我一直使用像 import FormsModule from '@angular/forms'; 这样的导入。 Angular 在节点上运行。我很困惑。 从 10x 开始支持这种称为 es6 的导入。现在在 LTS 中,所以您可能正在使用 10x 或 11x。这就是你使用这些导入没有任何并发​​症的原因......所以我猜他们在 10 的某个地方删除了它。“x”【参考方案5】:

解决方案

https://www.npmjs.com/package/babel-register

// This is to allow ES6 export syntax
// to be properly read and processed by node.js application
require('babel-register')(
  presets: [
    'env',
  ],
);

// After that, any line you add below that has typical ES6 export syntax
// will work just fine

const utils = require('../../utils.js');
const availableMixins = require('../../../src/lib/mixins/index.js');

下面是文件 *mixins/index.js 的定义

export  default as FormValidationMixin  from './form-validation'; // eslint-disable-line import/prefer-default-export

这在我的 Node.js CLI 应用程序中运行良好。

【讨论】:

虽然这可行,但这不是答案。最终这应该是不需要的。【参考方案6】:

我只是想在 JavaScript 文件中使用 importexport

每个人都说不可能。但是,截至 2018 年 5 月,可以在纯 Node.js 中使用上述内容,无需任何模块,如 Babel 等。

这是一个简单的方法。

创建以下文件,运行,然后自己查看输出。

别忘了在下方查看Explanation

文件 myfile.mjs

function myFunc() 
    console.log("Hello from myFunc")


export default myFunc;

文件 index.mjs

import myFunc from "./myfile.mjs"  // Simply using "./myfile" may not work in all resolvers

myFunc();

运行

node  --experimental-modules  index.mjs

输出

(node:12020) ExperimentalWarning: The ESM module loader is experimental.

Hello from myFunc

解释:

    由于是实验模块,.js 文件命名为 .mjs 文件 在运行时,您会将--experimental-modules 添加到node index.mjs 在输出中使用实验模块运行时,您将看到:“(node:12020) ExperimentalWarning: E​​SM 模块加载器是实验性的。 " 我有当前版本的 Node.js,所以如果我运行 node --version,它会给我“v10.3.0”,尽管 LTE/稳定/推荐版本是 8.11.2 LTS。 将来的某一天,您可以使用 .js 代替 .mjs,因为这些功能变得稳定而不是实验性的。 有关实验功能的更多信息,请参阅:https://nodejs.org/api/esm.html

【讨论】:

传递这个标志不允许我从样板文件中运行我的 ./bin/www... 你确定 5 号吗?我的印象是 .mjs 并不是将其表示为实验性的,而是因为模块规范没有提供一种有效的方法来判断文件应该使用模块加载器还是仅通过阅读代码就需要加载器。跨度> 这在 Node 10.15.1 中对我有用 我认为,文件后缀确实必须是 .mjs 才能正常工作(Windows,节点 10.15.3) 在节点 v12.6.0 中工作。但很遗憾看到这仍然是实验性的【参考方案7】:

我不知道这是否适用于您的情况,但我正在运行 Express.js 服务器:

nodemon --inspect ./index.js --exec babel-node --presets es2015,stage-2

这使我能够导入和使用扩展运算符,即使我只使用 Node.js 版本 8。

你需要安装 babel-cli、babel-preset-es2015 和 babel-preset-stage-2 来做我正在做的事情。

【讨论】:

谢谢,但@babel/node 应该存在于devDependencies【参考方案8】:

用途:

  "devDependencies": 
    "@babel/core": "^7.2.0",
    "@babel/preset-env": "^7.2.0",
    "@babel/register": "^7.0.0"
  

文件.babelrc


  "presets": ["@babel/preset-env"]

Node.js 应用程序的入口点:

require("@babel/register")()

// Import the rest of our application.
module.exports = require('./index.js')

How To Enable ES6 Imports in Node.js

【讨论】:

谢谢。我不确定所有其他答案如何帮助任何人,因为在项目中使用的 50% 的 node_modules 上打开 "modules": true 失败。 esm 假设您直接从节点调用入口脚本,而不是例如通过另一个库命令。这个答案只是让所有的痛苦都消失了,并为您提供了您所追求的语法。【参考方案9】:

您还可以使用名为 esm 的 npm 包,它允许您在 Node.js 中使用 ES6 模块。它不需要配置。使用 esm,您将能够在 JavaScript 文件中使用导出/导入。

在终端上运行以下命令

yarn add esm

npm install esm

之后,您需要在使用 node.js 启动服务器时需要此包。例如,如果您的节点服务器运行 index.js 文件,您将使用命令

node -r esm index.js

你也可以像这样将它添加到你的 package.json 文件中


  "name": "My-app",
  "version": "1.0.0",
  "description": "Some Hack",
  "main": "index.js",
  "scripts": 
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node -r esm index.js"
  ,


然后从终端运行这个命令来启动你的节点服务器

npm start

查看this link了解更多详情。

【讨论】:

似乎我在使用星号符号导入时遇到问题。例如。 import * as log from 'loglevel'; 我希望您在尝试使用 import * as log 'loglevel' 之前从 'loglevel' 导出函数 这是王牌!不幸的是,这对 Jest 不起作用 这是与 Typescript 一起使用的最佳选择,因为 ts-node 加载程序使 .mjs 扩展不可行。 node -r esm -r ts-node/register index.ts 注意:破坏 TS 反射元数据:github.com/standard-things/esm/issues/809【参考方案10】:

使用 .mjs 扩展名(如已接受的答案中所建议)以启用 ECMAScript 模块。但是,使用 Node.js v12,您还可以在 package.json 文件中全局启用此功能。

official documentation states:

如果最近的父 package.json 包含 "type": "module",则 .js 和无扩展名文件的导入语句被视为 ES 模块。


  "type": "module",
  "main": "./src/index.js"

(当然,在启动应用程序时您仍然需要提供标志--experimental-modules。)

【讨论】:

【参考方案11】:

使用 Node.js v12.2.0,我可以像这样导入所有标准模块:

import * as Http from 'http'
import * as Fs from 'fs'
import * as Path from 'path'
import * as Readline from 'readline'
import * as Os from 'os'

与我之前所做的相比:

const
  Http = require('http')
  ,Fs = require('fs')
  ,Path = require('path')
  ,Readline = require('readline')
  ,Os = require('os')

任何属于 ECMAScript 模块的模块都可以导入而无需使用 .mjs 扩展名,只要它的 package.json 文件中有此字段即可:

"type": "module"

因此,请确保将这样的 package.json 文件放在与您正在制作的模块相同的文件夹中。

要导入未使用 ECMAScript 模块支持更新的模块,您可以这样做:

// Implement the old require function
import  createRequire  from 'module'
const require = createRequire(import.meta.url)

// Now you can require whatever
const
  WebSocket = require('ws')
  ,Mime = require('mime-types')
  ,Chokidar = require('chokidar')

当然,不要忘记这是使用模块导入实际运行脚本所必需的(v13.2 之后不需要):

node --experimental-modules my-script-that-use-import.js

并且父文件夹需要这个 package.json 文件才能让该脚本不抱怨导入语法:


  "type": "module"

如果您要使用的模块尚未更新以支持使用导入语法导入,那么您别无选择,只能使用 require(但使用我上面的解决方案,这不是问题)。

我还想分享这段代码,它实现了模块中缺少的 __filename__dirname 常量:

import fileURLToPath from 'url'
import dirname from 'path'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)

【讨论】:

v12.11.1 不支持无调整导入 @AlexeySh。我上面描述的方法在那个版本中运行良好,我刚刚测试过。 如果你仔细阅读我最初的评论,你会看到下面的词“导入没有调整”。这意味着没有标志和配置。这是我评论的重点。 @AlexeySh。嗯,评论我写的东西是一件很奇怪的事情,因为我没有说明其他任何事情。 从 Node v.13 开始,不需要实验标志。 nodejs.org/api/esm.html

以上是关于如何在 Node.js 中使用 ES6 导入? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

使用Node.js需要与ES6导入/导出

如何正确配置实验性 ECMAScript 模块,以便在 Node.js 中使用导入/导出

Node.js 的 commonJS 规范 ES6 导入 js 文件

Node.js 的 commonJS 规范 ES6 导入 js 文件

在 ES6 Node.js 中导入“.json”扩展会引发错误

es6和node.js模块的区别