获得意外的令牌导出

Getting Unexpected Token Export

本文关键字:令牌 意外      更新时间:2023-09-26

我正在尝试在我的项目中运行一些 ES6 代码,但我收到意外的令牌导出错误。

export class MyClass {
  constructor() {
    console.log("es6");
  }
}

2022 年更新

您正在使用 EcmaScript 模块(ESM 或"ES6 模块")语法,但您的环境不支持它。

v14.13.0 之前的 NodeJS 版本不支持 ESM(export关键字语法),而是使用 CommonJS 模块(module.exports属性语法)。NodeJS v14.13.0 及更高版本支持 ESM,但必须先启用。

解决 方案:

  • 如果您使用的是 NodeJS v14.13.0 或更高版本(支持 ESM),您可以通过在项目package.json中设置"type":"module"来启用它
  • 使用 CommonJS 模块语法重构(适用于旧版本的 NodeJS)
  • 考虑将 TypeScript 与 ts-nodets-node-dev 个 npm 包一起使用(用于开发时的即时转译),并在.ts文件中编写 TypeScript
  • 使用 esbuild
  • (npm 上的esbuild包)将 ESM 转译到 CommonJS,该 esbuild 配置为将 ES6 JavaScript 转译到您的环境支持的 CommonJS 目标。(不再推荐使用巴别塔)

如果您收到此错误,也可能与您如何将 JavaScript 文件包含在 html 页面中有关。加载模块时,必须显式声明这些文件。下面是一个示例:

//module.js:
function foo(){
   return "foo";
}
var bar = "bar";
export { foo, bar };

当您包含如下所示的脚本时:

<script src="module.js"></script>

您将收到错误:

未捕获的语法错误:意外的令牌导出

您需要包含类型属性设置为"模块"的文件:

<script type="module" src="module.js"></script>

然后它应该按预期工作,并且您已准备好在另一个模块中导入模块:

import { foo, bar } from  "./module.js";
console.log( foo() );
console.log( bar );

我的两分钱

出口

ES6

我的班级.js

export class MyClass1 {
}
export class MyClass2 {
}

其他.js

import { MyClass1, MyClass2 } from './myClass';

CommonJS 替代方案

我的班级.js

class MyClass1 {
}
class MyClass2 {
}
module.exports = { MyClass1, MyClass2 }
// or
// exports = { MyClass1, MyClass2 };

其他.js

const { MyClass1, MyClass2 } = require('./myClass');

导出默认值

ES6

我的班级.js

export default class MyClass {
}

其他.js

import MyClass from './myClass';

CommonJS 替代方案

我的班级.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 模块导出。查看完整教程

消息.js

module.exports = 'Hello world';

应用.js

var msg = require('./Messages.js');
console.log(msg); // Hello World

要使用 ES6,请添加babel-preset-env

在您的.babelrc中:

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

答案更新了,这要归功于@ghanbari评论以应用 babel 7。

安装 babel 软件包 @babel/core@babel/preset 这将 ES6 转换为 commonjs 目标,因为节点 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关键字必须位于文件的顶层。

所以:

if (true) {
    export function foo() {}
}

也是非法的。当解析器遇到这种情况时,它会在那里停止解析,模糊地宣布滥用export,给出与加载使用 export 关键字的"非模块"JavaScript 文件时相同的错误。它从不报告潜在的缺少大括号错误。

我花了很长时间才弄清楚,所以我在这里发帖是为了帮助任何未来的患者。

理想情况下,解析器将报告仅在文件的顶层允许export

我遇到了这个问题,我花了一个小时才找到我的问题。

问题是我正在将代码从非模块更改为模块,而忘记删除导入的脚本文件。

我的"表.js"文件有以下行。这是模块文件。

export function tableize(tableIdentifier) {

我的"订单查询.js"文件有以下行。

import { tableize, changeColumnSizesDynamic } from '../common/table.js';

我的"订单查询.html"有以下两行。

<script src='/resources/js/common/table.js'></script>
<script type='module' src='/resources/js/client/orderinquiry.js'></script>

虽然第二行很好,宣布type='module.但是第一行直接链接到表.js并导致意外错误。当我删除第一<script>时,一切都开始工作。

通常导入在.js扩展中不起作用,因为默认情况下 js 表示 javascript 的 cjs 版本。如果要使用es6功能,则需要将.js扩展名重命名为.mjs扩展名

parent.mjs

export default class Car {
   constructor(brand) {
   this.carname = brand;
}
 present() {
   return 'I have a ' + this.carname;
  }
}

儿童.MJS

import Car from './parent.mjs'
export default class Model extends Car {
constructor(brand, mod , country) {
  super(brand);
  this.model = mod;
  this.country = country;
}
show() {
  return this.present() + ', it is a ' + this.model + "i am from " + 
  this.country;
  }
}

索引.html

<!DOCTYPE html>
 <html lang="en" class="no-js">
  <head>
  <meta charset="utf-8">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, 
shrink-to-fit=no">
  <title>Quick Start Pack Template</title>
 </head>
 <div class="demo"></div>
 <script type="module">
   import Model from './child.mjs'
   let value = new Model("Ford", "Mustang", "bangladesh")
   document.querySelector(".demo").innerHTML = value.show()
 </script>
 </body>
 </html>

最后在实时服务器上运行此代码

只需使用 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 。更多信息在这里。

解决了

这个问题:浏览器只支持 ES 语法,不理解 CommonJS 中使用的requireexports。导入扩展名为.ts的文件时会出现此问题。要解决此问题,请在文件中使用 ES6 模块导入。

例:文件夹结构

dist
src
|-app.ts
|-components
  |-button.ts
|-helper
  |-eventHander.ts
tsconfig.json
index.html
  1. 在 tsconfig 文件中,设置"module": "ES2015"
  2. 在 tsconfig 文件中,设置"outDir": "./dist"
  3. 在 HTML 文件中,添加属性<script type="module" src="./dist/app.js"></script>

您可以在此处阅读有关模块的更多信息:JavaScript 模块

  • 事件汉德.ts 文件
type Handler<T> = (e: T) => void;
const eventHander: Handler<Event> = (e: Event) => {
  e.preventDefault();
  alert("You Clicked");
};
export default eventHander;
  • 在按钮中.ts
import eventHander from "../helper/eventHander.js"
function createButton(): HTMLElement {
  let button: HTMLElement;
  button = document.createElement("button");
  button.addEventListener("click", eventHander);
  button.innerText = "Click Me"
return button 
}
export default createButton 
  • 在 app.ts 文件中
import createButton from "./components/button.js";
const hostElement: HTMLElement = document.getElementById("app")!;
hostElement.insertAdjacentElement("beforeend", createButton());

你的 HTML 代码应该是这样的:

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>
</body>
<script type="module" src="./dist/app.js"></script>

当我尝试在我的项目中导入本地 javascript 模块时,我也遇到了意外的令牌导出错误。我通过在索引.html文件中添加脚本标记时将类型声明为模块来解决它。

<script src = "./path/to/the/module/" type = "module"></script>

在最新版本的 Nodejs (v17?) 中,您可以使用 .mjs 文件扩展名使用顶级"导入"、"异步"、"等待" - 而不是转译或解决方法。

   // > node my.mjs
   
   import {MyClass} from 'https://someurl'
   async func () {
     // return some promise
   }
   await func ()
<</div> div class="answers">

对于那些在 2022 年查看此内容的人,我遇到了同样的错误,但是我将代码更改为如下所示:

    module.exports = () => {
    getUsers: () => users;
    addUser: (user) => users.push(user);
  };

使用 ES6 语法在 node 中不起作用,不幸的是,显然你必须有 babel 才能让编译器理解导出或导入等语法。

npm install babel-cli --save

现在我们需要创建一个 .babelrc 文件,在 babelrc 文件中,我们将 babel 设置为在编译到 ES5 时使用我们安装的 es2015 预设作为其预设。

在应用的根目录下,我们将创建一个 .babelrc 文件。 $ npm install babel-preset-es2015 --save

在应用的根目录下,我们将创建一个 .babelrc 文件。

{  "presets": ["es2015"] }

希望它有效... :)

//✅ 使用 module.exports 而不是 export模块导出 = {人};

我实际上想添加简单的解决方案。 使用 const 和反引号(')。

const model = `<script type="module" src="/"></<script>`