NodeJS planuje wspierać moduły importu / eksportu es6 (es2015)

275

Szukałem w Internecie bez jednoznacznej odpowiedzi na to pytanie.

Obecnie NodeJS używa tylko składni CommonJS do ładowania modułów, a jeśli naprawdę chcesz użyć standardowej składni modułów ES2015, musisz ją wcześniej przetransponować lub użyć zewnętrznego modułu ładującego w czasie wykonywania.

Obecnie nie jestem zbyt pozytywny, aby zastosować którąkolwiek z tych dwóch metod, czy opiekunowie NodeJS planują nawet wspierać moduły ES2015, czy nie? W ogóle nie znalazłem żadnej wskazówki na ten temat.

W tej chwili NodeJS 6.x twierdzi, że obsługuje 96% funkcji ES2015, ale nie ma odniesienia do modułów ( łącze do obsługi NodeJS ES2105 ).

Czy wiesz, czy NodeJS będzie obsługiwał te moduły w najbliższej przyszłości?

Zorgatone
źródło
2
Googling dla node es2015 modulespokazuje następujące jako jeden z najlepszych wyników: github.com/nodejs/node/wiki/ES6-Module-Detection-in-Node .
Felix Kling
6
Osobiście głosowałbym za zamknięciem tego pytania jako „zbyt zlokalizowane”, ale ten bliski powód już nie istnieje. Powiedzmy, że Node zdoła jutro wdrożyć moduły ES6. Czy zamierzasz usunąć swoje pytanie, ponieważ nie jest ono już istotne? Czy przynajmniej go zaktualizujesz? Nie sądzę, aby pytanie było odpowiednie dla SO, jeśli już wiesz, że będzie ono nieaktualne lub będzie wymagało aktualizacji „wkrótce”. Ale to tylko moja opinia i wydaje się, że są inni, którzy myślą inaczej, co jest dla mnie w porządku :) (fwiw, samo w sobie pytanie jest oczywiście ważne i interesujące)
Felix Kling
2
Żałuję jednak, że nie było miejsca w stosie wszechświata na takie pytania. Technicznie może się tu nie zmieścić, ale nie wiem, czy zgadzam się z tym, że to naprawdę „oparte na opiniach”. OP szuka konkretnej odpowiedzi na konkretne pytanie, ale takie, które będzie (w pewnym momencie) nieaktualne.
Wonko przy zdrowych zmysłach
5
Alternatywne sformułowanie tego pytania: „Jaki jest stan obsługi node.js dla modułów ES6?” Odpowiedź na wiele pytań SO zmienia się z czasem wraz z rozwojem technologii. Ja też miałem problem ze znalezieniem odpowiedzi, dopóki nie wylądowałem tutaj.
Joe Lapp,
4
@ FelixKling Myślę, że chciałbyś zamknąć to pytanie, to byłaby bardzo zła decyzja, ponieważ jest to problem, jak dotąd 211 osób było wystarczająco problematycznych, aby zagłosować.
Muhammad Umer

Odpowiedzi:

302

Węzeł 13.2.0 i powyżej

NodeJS 13.2.0 obsługuje teraz moduły ES bez flagi 🎉 Jednak implementacja jest nadal oznaczona jako eksperymentalna, dlatego należy zachować ostrożność podczas produkcji.

Aby włączyć obsługę ESM w 13.2.0, dodaj następujące elementy do package.json:

{
  "type": "module"
}

Wszystko .js, .mjs(lub pliki bez rozszerzenia) będą traktowane jako ESM.

Istnieje wiele różnych opcji innych niż całe package.jsonopt-in, z których wszystkie są szczegółowo opisane w dokumentacji dla 13.2.0 .

Węzeł 13.1.0 i poniżej

Ci, którzy nadal używają starszych wersji Node, mogą wypróbować moduł ładujący esm , który jest gotową do produkcji implementacją specyfikacji modułów ES dla NodeJS:

node -r esm main.js

Szczegółowe aktualizacje ...

23 kwietnia 2019 r

Niedawno wylądował PR, aby zmienić sposób wykrywania modułów ES: https://github.com/nodejs/node/pull/26745

Nadal jest za --experimental-modulesflagą, ale istnieją znaczne zmiany w sposobie ładowania modułów:

  • package.typektóry może być modulelubcommonjs
    • type: "commonjs":
      • .js jest analizowany jako commonjs
      • domyślnym punktem wejścia bez rozszerzenia jest commonjs
    • type: "module":
      • .js jest analizowany jako esm
      • Domyślnie nie obsługuje ładowania JSON ani modułu macierzystego
      • domyślnym punktem wejścia bez rozszerzenia jest esm
  • --type=[mode]aby ustawić typ w punkcie wejścia. Zastąpi package.typepunkt wejścia.
  • Nowe rozszerzenie pliku .cjs.
    • ma to na celu w szczególności wsparcie importowania plików commonjs w moduletrybie.
    • jest to tylko moduł ładujący esm, moduł ładujący commonjs pozostaje nietknięty, ale rozszerzenie będzie działać w starym module ładującym, jeśli użyjesz pełnej ścieżki pliku.
  • --es-module-specifier-resolution=[type]
    • Opcje to explicit(domyślne) inode
    • domyślnie nasz moduł ładujący nie zezwala na opcjonalne rozszerzenia podczas importu, ścieżka do modułu musi zawierać rozszerzenie, jeśli takie istnieje
    • domyślnie nasz moduł ładujący nie zezwala na importowanie katalogów zawierających plik indeksu
    • programiści mogą użyć, --es-module-specifier-resolution=nodeaby włączyć algorytm rozwiązywania specyfikacji specyfikatora commonjs
    • To nie jest „funkcja”, ale raczej implementacja do eksperymentowania. Oczekuje się, że zmieni się przed usunięciem flagi
  • --experimental-json-loader
    • jedynym sposobem na zaimportowanie JSON kiedy "type": "module"
    • po włączeniu wszystko import 'thing.json'przejdzie przez eksperymentalny moduł ładujący niezależnie od trybu
    • na podstawie whatwg / html # 4315
  • Możesz użyć, package.mainaby ustawić punkt wejścia dla modułu
    • rozszerzenia plików używane w main zostaną rozwiązane na podstawie typu modułu

17 stycznia 2019 r

Węzeł 11.6.0 nadal wymienia moduły ES jako eksperymentalne, za flagą.

13 września 2017 r

NodeJS 8.5.0 został wydany z obsługą plików mjs za flagą:

node --experimental-modules index.mjs

Plan polega na usunięciu flagi dla wersji 10.0 LTS.

- Nieaktualne informacje. Trzymane tutaj do celów historycznych--

8 września 2017 r

Główny oddział NodeJS został zaktualizowany z początkową obsługą modułów ESM:
https://github.com/nodejs/node/commit/c8a389e19f172edbada83f59944cad7cc802d9d5

Powinno to być dostępne najpóźniej w nocy (można to zainstalować za pomocą nvm, aby działać równolegle z istniejącą instalacją):
https://nodejs.org/download/nightly/

I włączony za --experimental-modulesflagą:

pakiet.json

{
  "name": "testing-mjs",
  "version": "1.0.0",
  "description": "",
  "main": "index.mjs" <-- Set this to be an mjs file
}

Następnie uruchomić:

node --experimental-modules .

Luty 2017 r .:

https://medium.com/@jasnell/an-update-on-es6-modules-in-node-js-42c958b890c#.6ye7mtn37

Chłopaki z NodeJS zdecydowali, że najmniej złym rozwiązaniem jest użycie .mjsrozszerzenia pliku. Na wynos jest to:

Innymi słowy, biorąc pod uwagę dwa pliki foo.jsi bar.mjsużycie import * from 'foo'będzie traktowane foo.jsjako CommonJS, podczas gdy import * from 'bar' będzie traktowane bar.mjsjak moduł ES6

A co do osi czasu ...

W chwili obecnej nadal istnieje szereg problemów ze specyfikacją i implementacją, które muszą wystąpić po stronie ES6 i maszyny wirtualnej, zanim Node.js będzie mógł rozpocząć pracę nad obsługiwaną implementacją modułów ES6. Prace są w toku, ale zajmie to trochę czasu - obecnie obserwujemy co najmniej około roku .

Październik 2016 r .:

Jeden z programistów Node.JS ostatnio uczestniczył w spotkaniu TC-39 i napisał świetny artykuł na temat blokowania implementacji dla Node.JS:

https://hackernoon.com/node-js-tc-39-and-modules-a1118aecf95e

Podstawowym podejściem do tego jest:

  • Moduły ES są analizowane statycznie, oceniane są CommonJS
  • Moduły CommonJS pozwalają na eksport łatania małp, obecnie moduły ES nie
  • Trudno jest wykryć, co to jest moduł ES, a co CommonJS bez jakiejkolwiek formy wprowadzania danych przez użytkownika, ale próbują.
  • *.mjs wydaje się najbardziej prawdopodobnym rozwiązaniem, chyba że potrafią dokładnie wykryć moduł ES bez udziału użytkownika

- Oryginalna odpowiedź -

To był gorący ziemniak od dłuższego czasu. Najważniejsze jest to, że tak, Node ostatecznie będzie obsługiwał składnię ES2015 do importowania / eksportowania modułów - najprawdopodobniej, gdy specyfikacja modułów ładujących zostanie sfinalizowana i uzgodniona.

Oto dobry przegląd tego, co powstrzymuje NodeJS. Zasadniczo muszą upewnić się, że nowa specyfikacja działa dla Węzła, który jest przede wszystkim warunkowy, ładowanie synchroniczne, a także HTML, który jest przede wszystkim asynchroniczny.

Obecnie nikt nie wie na pewno, ale wyobrażam sobie, że Node będzie obsługiwał import/exportładowanie statyczne, oprócz nowego System.importdo ładowania dynamicznego - przy jednoczesnym zachowaniu requirestarszego kodu.

Oto kilka propozycji, jak Node może to osiągnąć:

CodingIntrigue
źródło
38
O .mjsrozszerzenie: We have affectionately called these “Michael Jackson Script” files in the past. Na wypadek, gdybyś usłyszał, jak ktoś mówi o artystach popowych podczas rozmowy JS.
Jeewes,
1
Nie rozumiem, dlaczego zmiana składni importu nie wystarczy. Jedna składnia do importowania es („poprawna”) i jedna do importowania cjs? Innymi słowy, biorąc pod uwagę dwa pliki foo.js i bar.js, import * from 'foo'potraktuje foo.js tak jak CommonJS import * as bar from 'bar'potraktuje bar.js jako moduł ES6 Czy ktoś może to wyjaśnić?
Corey Alix
1
Składnia @CoreyAlix zasadniczo nie zostanie zmieniona w celu obsługi środowiska. To naprawdę wpływa tylko na Węzeł. Ponadto składnia jest nieco nieintuicyjna. Jak uzyskać dostęp do eksportu w proponowanej składni?
CodingIntrigue
Żeby było jasne, to nie jest „moja” propozycja, kopiuję to, co już robi maszynopis. Aby odpowiedzieć na twoje pytanie, uzyskujesz dostęp do eksportu za pomocą „bar”: bar.foobar () import {foo as Foo} z „./foo” jest mechanizmem identyfikacji modułu ES6. var Foo = wymagany („./ foo”) to mechanizm identyfikujący moduł CJS. W Typescript dane wyjściowe commonjs wyglądają tak: var mod1_1 = wymagany („./ mod1”); exports.mod1 = mod1; Wyjście ES6 wygląda następująco: import {mod1} z „./mod1”; export {mod1}
Corey Alix
1
Byłbym naprawdę interesujący w aktualizacji Node 10 do tej odpowiedzi. Czy ta funkcja spowodowała cięcie, czy nadal jest za flagą?
dcorking