我试图在我的项目中运行一些ES6代码,但是出现了意外令牌导出错误。
export class MyClass {
constructor() {
console.log("es6");
}
}
我试图在我的项目中运行一些ES6代码,但是出现了意外令牌导出错误。
export class MyClass {
constructor() {
console.log("es6");
}
}
2022年更新
你正在使用EcmaScript模块(ESM或'ES6 Modules')语法,但你的环境不支持它。
在v14.13.0之前的NodeJS版本不支持ESM(export
关键字语法),而使用CommonJS模块(module.exports
属性语法)。NodeJS v14.13.0及更高版本支持ESM,但必须先启用它。
解决方案:
package.json
中设置"type": "module"
来启用它。.ts
文件中使用TypeScript和ts-node
或ts-node-dev
npm包(用于开发时即时转译)编写TypeScriptesbuild
包),并将其配置为将你的ES6 javascript转译为受你的环境支持的CommonJS目标。(不再推荐使用babel)import
?我以为 v10.0.0 版本已经支持了,但显然并没有。 - chovy如果您遇到此错误,可能与您将JavaScript文件包含到html页面的方式有关。加载模块时,您必须明确声明这些文件。这是一个例子:
//module.js:
function foo(){
return "foo";
}
var bar = "bar";
export { foo, bar };
当您像这样包含脚本时:
<script src="module.js"></script>
你会看到以下错误:
Uncaught SyntaxError: Unexpected token export
你需要在引入文件时设置type属性为"module":
<script type="module" src="module.js"></script>
然后它应该像预期的那样工作,您现在可以将您的模块导入到另一个模块中:
import { foo, bar } from "./module.js";
console.log( foo() );
console.log( bar );
<script type="module">import ...</script>
。我在最近版本的Chromium中进行了测试。 - Vladimir S.import ...
? - pirtype="module"
也将被延迟加载,这在某些情况下可能会破坏您所依赖的加载顺序。 - Kobato我的看法
ES6
myClass.js
export class MyClass1 {
}
export class MyClass2 {
}
其他.js
import { MyClass1, MyClass2 } from './myClass';
CommonJS替代方案
myClass.js
class MyClass1 {
}
class MyClass2 {
}
module.exports = { MyClass1, MyClass2 }
// or
// exports = { MyClass1, MyClass2 };
其他.js
const { MyClass1, MyClass2 } = require('./myClass');
ES6
myClass.js
export default class MyClass {
}
other.js
import MyClass from './myClass';
CommonJS替代方案
myClass.js
module.exports = class MyClass1 {
}
其他.js
const MyClass = require('./myClass');
我通过创建一个入口文件来解决了这个问题,如下所示。
// index.js
require = require('esm')(module)
module.exports = require('./app.js')
我导入到app.js
内部及其之后的任何文件都可以使用imports/exports
,现在只需像这样运行它:node index.js
注意:如果app.js
使用export default
,则在使用入口点文件时变为require('./app.js').default
。
此时无需使用Babel(JS已经变得非常强大),您可以简单地使用默认的JavaScript模块导出。 查看完整教程
Message.js
module.exports = 'Hello world';
app.js
var msg = require('./Messages.js');
console.log(msg); // Hello World
若要使用ES6,请添加babel-preset-env
并在您的.babelrc
文件中:
{
"presets": ["@babel/preset-env"]
}
由于 @ghanbari 的评论,回答已更新以应用 Babel 7.
@babel/core
和@babel/preset-env
,这将把ES6转换为commonjs目标,因为node.js不能直接理解ES6目标格式。
使用以下命令安装:npm install --save-dev @babel/core @babel/preset-env
然后在项目的根目录中创建名为.babelrc
的配置文件,并添加以下代码:
{ "presets": ["@babel/preset-env"] }
我曾经有一段时间成功运行了模块,但后来出现了Uncaught SyntaxError: Unexpected token export
错误。
结果发现,我加了一个开括号但没有闭括号。类似这样:
if (true) {
/* } missing here */
export function foo() {}
尽管忘记结尾的大错误是遗漏 }
符号,但解析器首先在大括号内找到一个 export,这是不允许的。
export
关键字必须在文件的顶层。
因此:
if (true) {
export function foo() {}
}
同时,这也是非法的。当解析器遇到这种情况时,它会停止解析,并模糊地宣布export
的误用,给出与加载使用export
关键字的“非模块”JavaScript文件时相同的错误。它从不报告潜在的缺少括号错误。
我花了很长时间才弄清楚这一点,所以我在这里发布帖子,以帮助任何未来的受害者。
理想情况下,解析器应该报告只允许在文件顶层使用export
。
tsx
替代node
作为运行时,即可使用常规的导入语句,无需将项目切换到type: module
并且无需处理type: module
的恶劣后果。此外,您还将获得TypeScript支持。
从CommonJS
导入ES6模块的另一种方法是将您的ES6模块文件重命名为.mjs
扩展名。这是向后兼容的一种方式。然后在您的CommonJS代码中,您可以像这样导入:
文件顶部导入:
import myClass from "./MyClass.mjs"
或者在代码中的任何位置使用动态导入:
const myClass = await import("./MyClass.mjs");
请注意,您的CommonJS
文件不需要重命名为.mjs
。此处有更多信息。
export
只在 ES6 中可用,而这些模块提供了 ES6 支持。 - Claiesmodule.exports = MyClass
,而不是export class MyClass
。 - onmyway133