Node.js - SyntaxError: Nhập mã thông báo không mong muốn


442

Tôi không hiểu điều gì là sai. Nút v5.6.0 NPM v3.10.6

Mật mã:

function (exports, require, module, __filename, __dirname) {
    import express from 'express'
};

Lỗi:

SyntaxError: Unexpected token import
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:387:25)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Function.Module.runMain (module.js:447:10)
    at startup (node.js:140:18)
    at node.js:1001:3

4
Sử dụng bộ chuyển mã như Babel để sử dụng nhập trong Nodejs vì nó không được hỗ trợ nguyên bản trong nodejs. Có yêu cầu thay thế nhập khẩu tốt nhất vì vậy hãy đi với điều đó.
BHUVNESH KUMAR

Câu trả lời:


483

Cập nhật 3: Kể từ Nút 13 , bạn có thể sử dụng phần mở rộng .mjs hoặc đặt "loại": "mô-đun" trong gói.json của bạn. Bạn không cần sử dụng --experimental-modulescờ.

Cập nhật 2: Kể từ Nút 12 , bạn có thể sử dụng .mjstiện ích mở rộng hoặc đặt "type": "module"trong gói.json của mình. Và bạn cần chạy nút với --experimental-modulescờ.

Cập nhật: Trong Nút 9 , nó được bật phía sau cờ và sử dụng .mjstiện ích mở rộng.

node --experimental-modules my-app.mjs

Mặc dù importthực sự là một phần của ES6, nhưng rất tiếc, nó không được hỗ trợ trong NodeJS theo mặc định và chỉ hỗ trợ trong các trình duyệt gần đây.

Xem bảng compat trình duyệt trên MDNvấn đề Node này .

Từ Cập nhật của James M Snell về các Mô-đun ES6 trong Node.js (tháng 2 năm 2017):

Công việc đang được tiến hành nhưng sẽ mất một thời gian - Hiện tại chúng tôi đang xem xét ít nhất là khoảng một năm.

Cho đến khi hỗ trợ xuất hiện tự nhiên, bạn sẽ phải tiếp tục sử dụng các requiretuyên bố cổ điển :

const express = require("express");

Nếu bạn thực sự muốn sử dụng các tính năng ES6 / 7 mới trong NodeJS, bạn có thể biên dịch nó bằng Babel. Đây là một máy chủ ví dụ .


2
Có ai biết nếu nút 10 sẽ giao hàng với sự hỗ trợ được bật theo mặc định không? (dự kiến ​​ra mắt vào tháng tới)
Hartmut

2
@Scimonster ...... nút --experimental-mô-đun my-app.mjs (nút: 12176) ExperimentalWarning: Trình tải mô-đun ESM là thử nghiệm. {Lỗi: Không thể tìm thấy mô-đun /C:/Users/WittyParrot/Document/card-test-project/src/my-app.mjs khi tìm kiếm (nội bộ / mô-đun / esm / DefaultResolve.js: 23: 12) src / my-app.mjs khi tìm kiếm (nội bộ / mô-đun / esm / DefaultResolve.js: 23: 12) .... ném cảnh báo không thể tìm thấy my-app.js .... vui lòng đề xuất .... i cài đặt phiên bản nút 9.11.1
Leo

51
bực bội vì phần lớn các hướng dẫn ngoài kia nói về việc sử dụng nhập khẩu, nhưng hầu như không có hỗ trợ cho nó. (Tôi muốn 2 giờ trong cuộc sống của tôi trở lại lol)
kiwicomb123

9
@ChaimEliyah: gặp vấn đề tương tự ở nút v11.0.0
whoami

5
Vẫn yêu cầu một cờ trong v12 nodejs.org/api/esm.html#esm_ecmascript_modules
ABabin

60

Thật không may, Node.js chưa hỗ trợ ES6 import.

Để thực hiện những gì bạn đang cố gắng thực hiện (nhập mô-đun Express), mã này phải đủ

var express = require("express");

Ngoài ra, hãy chắc chắn rằng bạn đã cài đặt Express bằng cách chạy

$ npm install express

Xem Tài liệu Node.js để biết thêm thông tin về việc học Node.js.


8
importkhông nhất thiết phải là một tính năng của TypeScript. TypeScript là ES6 với các kiểu chữ. Vì vậy, những thứ như nhập khẩu là ES6 bản địa.
borislemke

@borislemke Đúng, tôi đã giải thích OP một chút sai. :) Tôi sẽ thay đổi nó.
baranskistad ngày

xin chào, tôi đã cài đặt express nhưng trong tập lệnh của tệp pack.json chúng ta nên viết gì? Nếu tôi viết "scripts": {"start": "node index.js"} thì nó sẽ hiển thị cùng một lỗi. làm ơn giúp tôi.
Ravi Shah

node index.jslàm việc cho tôi, nhưng khi tôi chạy node dist/main.jstôi cũng nhận được Unexpected token import.
TheFox

@TheFox bạn có thể có một nhập trong tập tin đó. Chỉ vì bạn index.jsđang vượt qua không có nghĩa là bạn dist/main.jscũng sẽ vượt qua.
baranskistad

34

Như đã đề cập trong các câu trả lời khác, Node JS hiện không hỗ trợ nhập ES6.

(Đến bây giờ, hãy đọc EDIT 2)

Cho phép nhập ES6 trong nút js cung cấp giải pháp cho vấn đề này. Tôi đã thử điều này và nó đã làm việc cho tôi.

Chạy lệnh:

    npm install babel-register babel-preset-env --save-dev

Bây giờ bạn cần tạo một tệp mới (config.js) và thêm đoạn mã sau vào nó.

    require('babel-register')({
        presets: [ 'env' ]
    })
    // Import the rest of our application.
    module.exports = require('./your_server_file.js')

Bây giờ bạn có thể viết báo cáo nhập mà không nhận được bất kỳ lỗi nào.

Hi vọng điêu nay co ich.

BIÊN TẬP:

Bạn cần chạy tệp mới mà bạn đã tạo với mã ở trên. Trong trường hợp của tôi, nó đã được config.js. Vì vậy, tôi phải chạy:

    node config.js

EDIT 2:

Trong khi thử nghiệm, tôi tìm thấy một giải pháp dễ dàng cho vấn đề này.

Tạo .babelrctập tin trong thư mục gốc của dự án của bạn.

Thêm sau đây (và bất kỳ cài đặt trước babel nào bạn cần, có thể được thêm vào trong tệp này):

    {
        "presets": ["env"]
    }

Cài đặt babel-preset-envbằng lệnh npm install babel-preset-env --save, và sau đó cài đặt babel-clibằng lệnhnpm install babel-cli -g --save

Bây giờ, hãy chuyển đến thư mục nơi tệp máy chủ hoặc tệp chỉ mục của bạn tồn tại và chạy bằng cách sử dụng: babel-node fileName.js

Hoặc bạn có thể chạy bằng npm startcách thêm mã sau vào package.jsontệp của mình :

    "scripts": {
        "start": "babel-node src/index.js"
    }

Làm thế nào để tôi làm điều này với điện tử? Tôi đã thử như thế này: "start": "babel-node electron .", nhưng không có may mắn
tpbafk

2
@tpbafk Tôi chưa làm việc về điện tử. Nhưng tôi đã tìm thấy một cái gì đó tương tự như vấn đề javascript của bạn - Cách đặt npm start cho ứng dụng điện tử với 'babel-node --presets es2015, giai đoạn 3' . Hy vọng nó sẽ giúp
Neerali Acharya

33

Lỗi: SyntaxError: Nhập mã thông báo không mong muốn hoặc SyntaxError: Xuất mã thông báo không mong muốn


Giải pháp: Thay đổi tất cả hàng nhập của bạn làm ví dụ

const express               = require('express');
const webpack               = require('webpack');
const path                  = require('path');
const config                = require('../webpack.config.dev');
const open                  = require('open');

Và cũng thay đổi export default = foo;thànhmodule.exports = foo;


1
Tôi muốn bạn đã giải thích phần mặc định xuất khẩu thêm một chút. Tôi đang gặp rắc rối với phần đó. Việc nhập khẩu hoạt động tuyệt vời với câu trả lời của bạn.
JoeGalind

Có một câu trả lời trước câu trả lời của tôi có một lời giải thích. Nhưng để làm rõ Node không hỗ trợ cú pháp ES6. Khi bạn nói Nhập ... bạn đang sử dụng cú pháp
ES6

21

Tôi bị sốc esmđã không được đề cập. Gói nhỏ nhưng mạnh mẽ này cho phép bạn sử dụng importhoặc require.

Cài đặt esm trong dự án của bạn

$ npm install --save esm

Cập nhật Node Start Script để sử dụng esm

node -r esm app.js

esmchỉ hoạt động. Tôi đã lãng phí TON thời gian .mjs--experimental-moduleschỉ để tìm ra một .mjstệp không thể nhập tệp sử dụng requirehoặc module.exports. Đây là một vấn đề lớn, trong khi esmcho phép bạn trộn và kết hợp và nó chỉ ra rằng ... esmchỉ hoạt động.


17

Trong trường hợp bạn vẫn không thể sử dụng "nhập" ở đây là cách tôi xử lý nó: Chỉ cần dịch nó sang một nút thân thiện yêu cầu. Thí dụ:

import { parse } from 'node-html-parser';

Giống như:

const parse = require('node-html-parser').parse;

4
không đúng nếu bạn (như có thể là trường hợp) sử dụng exporttừ khóa
Daniel Thompson

@DanielThndry Xin lỗi nếu điều này có thể là sai lầm, tôi chỉ đưa ra một cách giải quyết cho trường hợp này, nếu bạn làm việc mà không có exporttừ khóa, dù sao cũng cảm ơn vì lưu ý hữu ích của bạn!
Alberto

Làm việc cho tôi. Cảm ơn
Ali Azhar

11

đề nghị babel 7 bạn có thể thêm phụ thuộc dev

npm i -D @babel/core @babel/preset-env @babel/register

và thêm một .babelrc trong thư mục gốc

{
"presets": [
  [
    "@babel/preset-env",
    {
      "targets": {
        "node": "current"
     }
    }
  ]
 ]
}

và thêm vào tệp .js

require("@babel/register")

hoặc nếu bạn chạy nó trong cli, bạn có thể sử dụng hook yêu cầu như -r @ babel / register, ví dụ.

$node -r @babel/register executeMyFileWithESModules.js

1
Cài đặt @ babel / preset-env và thêm nó vào .babelrc đã tạo nên mánh khóe. Không cần @ babel / đăng ký plugin trong trường hợp của tôi.
Marcos R

8

nếu bạn có thể sử dụng 'babel', hãy thử thêm tập lệnh xây dựng trong gói.json (- presets = es2015) như bên dưới. nó thực hiện để biên dịch trước mã nhập vào es2015

"build": "babel server --out-dir build --presets=es2015 && webpack"

nhưng npm starttrước tiên tôi sẽ gọi "xây dựng", hay trước tiên là "bắt đầu"? (Bắt đầu hiện được xác định:"nodemon src/app.js --exec \"npm run lint && node\"",
pashute

nếu tôi chạy cmd này, nó cho thấy máy chủ không tồn tại lỗi
kumaresan_sd

6

Kể từ Node.js v12 (và hiện tại có thể khá ổn định, nhưng vẫn được đánh dấu là "thử nghiệm"), bạn có một vài tùy chọn để sử dụng ESM ( E CMA S cript M odules) trong Node.js (đối với các tệp, có một cách thứ ba để trốn tránh chuỗi), đây là những gì tài liệu nói:

Các --experimental-moduleslá cờ có thể được sử dụng để kích hoạt tính năng hỗ trợ cho ECMAScript module (ES module).

Khi được bật, Node.js sẽ coi các mô đun sau là mô đun ES khi được chuyển đến nodelàm đầu vào ban đầu hoặc khi được tham chiếu bởi các importcâu lệnh trong mã mô đun ES:

  • Tập tin kết thúc bằng .mjs.

  • Các tệp kết thúc bằng .jshoặc các tệp không có phần mở rộng, khi package.jsontệp cha gần nhất chứa trường cấp cao nhất "type"có giá trị là "module".

  • Các chuỗi được truyền vào dưới dạng đối số --evalhoặc --printhoặc được dẫn nodequa STDIN, với cờ --input-type=module.

Node.js sẽ coi là CommonJS tất cả các dạng đầu vào khác, chẳng hạn như .jscác tệp trong đó package.jsontệp cha gần nhất không chứa "type" trường cấp cao nhất hoặc đầu vào chuỗi không có cờ --input-type. Hành vi này là để bảo tồn khả năng tương thích ngược. Tuy nhiên, bây giờ Node.js hỗ trợ cả hai mô-đun CommonJS và ES, tốt nhất nên nói rõ bất cứ khi nào có thể. Node.js sẽ coi các mục sau là CommonJS khi được chuyển đến nodelàm đầu vào ban đầu hoặc khi được tham chiếu bởi các importcâu lệnh trong mã mô-đun ES:

  • Tập tin kết thúc bằng .cjs.

  • Các tệp kết thúc bằng .jshoặc các tệp không có phần mở rộng, khi package.jsontệp cha gần nhất chứa trường cấp cao nhất "type"có giá trị là "commonjs".

  • Các chuỗi được truyền vào dưới dạng đối số --evalhoặc --printhoặc được dẫn nodequa STDIN, với cờ --input-type=commonjs.


3

Khi tôi bắt đầu với express luôn muốn có một giải pháp để sử dụng nhập thay vì yêu cầu

const express = require("express");
// to 
import express from "express"

Nhiều lần đi qua dòng này: - Unfortunately, Node.js doesn't support ES6's import yet.

Bây giờ để giúp đỡ khác, tôi tạo hai giải pháp mới ở đây

1) esm : -

Trình tải mô-đun ECMAScript đơn giản, không có babel, không có gói. hãy làm cho nó hoạt động

  yarn add esm / npm install esm

tạo start.js hoặc sử dụng không gian tên của bạn

 require = require("esm")(module/*, options*/)
 // Import the rest of our application.
 module.exports = require('./src/server.js')
 // where server.js is express server start file

Thay đổi package.josnđường dẫn của bạnstart.js

  "scripts": {
    "start": "node start.js",
    "start:dev": "nodemon start.js",
  },
  "dependencies": {
+    "esm": "^3.2.25",
  },
  "devDependencies": {
+   "nodemon": "^1.19.2"
  }

2) Babel js : -

Điều này có thể được chia thành 2 phần

a) Giải pháp 1 nhờ timonweb.com

b) Giải pháp 2

sử dụng Babel 6 (phiên bản cũ hơn của babel-preset-giai đoạn-3 ^ 6.0 ) tạo .babelrctệp tại thư mục gốc của bạn

{
    "presets": ["env", "stage-3"]
}

Cài đặt babel-preset-giai đoạn 3

yarn add babel-cli babel-polyfill babel-preset-env bable-preset-stage-3 nodemon --dev

Thay đổi trong gói.json

"scripts": {
+   "start:dev": "nodemon --exec babel-node -- ./src/index.js",
+   "start": "npm run build && node ./build/index.js",
+   "build": "npm run clean && babel src -d build -s --source-maps --copy-files",
+   "clean": "rm -rf build && mkdir build"
},
"devDependencies": {
+    "babel-cli": "^6.26.0",
+    "babel-polyfill": "^6.26.0",
+    "babel-preset-env": "^1.7.0",
+    "babel-preset-stage-3": "^6.24.1",
+    "nodemon": "^1.19.4"
},

Bắt đầu máy chủ của bạn

yarn start / npm start

Ôi không, chúng tôi tạo ra vấn đề mới

regeneratorRuntime.mark(function _callee(email, password) {
^
ReferenceError: regeneratorRuntime is not defined

Lỗi này chỉ xuất hiện khi bạn sử dụng async / await trong mã của mình. Sau đó sử dụng polyfill bao gồm thời gian chạy bộ tái tạo tùy chỉnh và core-js. thêm vào đầuindex.js

import "babel-polyfill"

Điều này cho phép bạn sử dụng async / await

sử dụng Babel 7

Cần cập nhật mọi thứ trong dự án của bạn, hãy bắt đầu với babel 7 .babelrc

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

Một số thay đổi trong gói.json

"scripts": {
+  "start:dev": "nodemon --exec babel-node -- ./src/index.js",
+  "start": "npm run build && node ./build/index.js",
+  "build": "npm run clean && babel src -d build -s --source-maps --copy-files",
+  "clean": "rm -rf build && mkdir build",
    ....
}
"devDependencies": {
+   "@babel/cli": "^7.0.0",
+   "@babel/core": "^7.6.4",
+   "@babel/node": "^7.0.0",
+   "@babel/polyfill": "^7.0.0",
+   "@babel/preset-env": "^7.0.0",
+   "nodemon": "^1.19.4"
....
}

và sử dụng import "@babel/polyfill"trên điểm bắt đầu

import "@babel/polyfill"
import express from 'express'
const app = express()

//GET request
app.get('/', async (req, res) {
  // await operation
  res.send('hello world')
})
app.listen(4000, () => console.log('🚀 Server listening on port 400!'))

Bạn đang nghĩ tại sao start:dev

Nghiêm túc. Đó là câu hỏi tốt nếu bạn là người mới. Mỗi thay đổi bạn đều sử dụng yarn start:devmáy chủ khởi động mỗi lần, sau đó sử dụng làm máy chủ phát triển, mọi thay đổi sẽ tự động khởi động lại máy chủ để biết thêm về gật đầu


2

Trong trường hợp của tôi, nó đang chăm sóc .babelrctập tin và nó sẽ chứa một cái gì đó như thế này:

{
  "presets": ["es2015-node5", "stage-3"],
  "plugins": []
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.