我试图在Node.js中获得ES6导入的窍门,并试图使用本示例中提供的语法:

Cheatsheet链接

我正在查看支持表,但我无法找到支持新的导入语句的版本(我尝试寻找文本import/require)。我目前正在运行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));
}

我错过了什么,我如何才能让节点识别我的导入语句?


当前回答

回到Jonathan002最初的问题

“…什么版本支持新的ES6导入语句?”

根据Dr. Axel Rauschmayer的文章,在Node.js 10中有一个默认支持它的计划(没有实验性的命令行标志)。x LTS。根据node.js在2018年3月29日的发布计划,它很可能在2018年4月之后可用,而它的LTS将在2018年10月开始。

其他回答

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 <= v12

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

node --experimental-modules my-app.mjs

使用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扩展名,只要它的包中有这个字段。json文件:

"type": "module"

所以一定要放一个这样的包。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

父文件夹需要这个包。Json文件,该脚本不抱怨导入语法:

{
  "type": "module"
}

如果您想要使用的模块还没有更新到支持使用import语法导入,那么您除了使用require别无选择(但对于上面的解决方案,这不是问题)。

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

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

你可以试试esm。

这里有一些介绍:esm

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

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

就是这样。

However and this is a big however, while your shinny pure ES6 code will run in an environment like Node.js (e.g., 9.5.0) you will still have the craziness of transpilling just to test. Also bear in mind that Ecma has stated that release cycles for JavaScript are going to be faster, with newer features delivered on a more regular basis. Whilst this will be no problems for single environments like Node.js, it's a slightly different proposition for browser environments. What is clear is that testing frameworks have a lot to do in catching up. You will still need to probably transpile for testing frameworks. I'd suggest using Jest.

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

解决方案

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应用程序中工作得很好。