web-dev-qa-db-ja.com

Node.jsを使用すると、ES6のインポート/エクスポートが必要

私が共同作業しているプロジェクトでは、どのモジュールシステムを使用できるかについて2つの選択肢があります。

  1. requireを使用してモジュールをインポートし、module.exportsおよびexports.fooを使用してエクスポートします。
  2. ES6のimportを使用してモジュールをインポートし、ES6のexportを使用してエクスポートする

一方をもう一方よりも使用することによるパフォーマンス上の利点はありますか?私たちがノードのものの上にES6モジュールを使用することになっていたならば私たちが知るべきである何か他にありますか?

730
kpimov

一方をもう一方よりも使用することによるパフォーマンス上の利点はありますか?

ES6モジュールをネイティブにサポートするJavaScriptエンジンはまだありません。あなたは自分がBabelを使っていると言った。 Babelはデフォルトでimportexportの宣言をCommonJS(require/module.exports)に変換します。そのため、ES6モジュール構文を使用していても、Nodeでコードを実行すると、内部でCommonJSを使用することになります。

CommonJSモジュールとES6モジュールには技術的な違いがあります。 CommonJSではモジュールを動的にロードすることができます。 ES6はこれを許可していません、 しかしそのために開発中のAPIがあります

ES6モジュールは標準の一部なので、私はそれらを使用します。

604
Felix Kling

あなたが考慮したいかもしれないいくつかの用法/機能があります。

必須:

  • ロードされたモジュール名が事前定義されていない/静的でない場所、または「本当に必要」な場合にのみ条件付きでモジュールをロードする場所(特定のコードフローによって異なります)を動的ロードできます。
  • ロードは同期的です。つまり、requireが複数ある場合は、それらが1つずつ読み込まれて処理されます。

ES6の輸入:

  • 名前付きインポートを使用して、必要な部分だけを選択的にロードできます。それはメモリを節約することができます。
  • インポートは非​​同期にすることができ(そして現在のES6 Module Loaderでは、実際はそうです)、もう少しパフォーマンスを良くすることができます。

また、Requireモジュールシステムは標準ベースではありません。 ES6モジュールが存在する今では、標準になることはほとんどありません。将来的には、さまざまな実装でES6モジュールがネイティブにサポートされるようになり、パフォーマンス面で有利になります。

144
Amit

主な利点は構文です。

  • より宣言的でコンパクトな構文
  • ES6モジュールは基本的にUMD(Universal Module Definition)を時代遅れにするでしょう - 本質的にCommonJSとAMD(サーバー対ブラウザ)間の分裂を取り除きます。

ES6モジュールでパフォーマンス上の利点が得られることはほとんどありません。ブラウザでES6機能が完全にサポートされている場合でも、モジュールをバンドルするための追加のライブラリが必要になります。

36
snozza

一方をもう一方よりも使用することによるパフォーマンス上の利点はありますか?

現在のブラウザエンジンはES6規格のimport/exportを実装していないため、現在の答えはnoです。

いくつかの比較表 http://kangax.github.io/compat-table/es6/ これを考慮に入れていないので、Chromeのためのほとんどすべての緑を見るときは、ただ注意してください。 ES6のimportキーワードは考慮されていません。

言い換えれば、V8を含む現在のブラウザエンジンは、 メインのJavaScriptファイル から 新しいJavaScriptファイル をどのJavaScriptディレクティブを介してもインポートすることはできません。

(V8がES6仕様に従ってそれを実装するまで、まだ 数バグ または数年先のことになるかもしれません。)

この document が必要なもので、この document が従うべきものです。

そしてES6規格は、(ヘッダ).hファイルがあるプログラミング言語Cのようにモジュールを読む前にモジュールの依存関係があるべきだと言っていました。

これはよくテストされた優れた構造であり、ES6規格を作成した専門家がそれを念頭に置いていたことは間違いありません。

これにより、Webpackまたは他のパッケージバンドル担当者は、 special の場合にバンドルを最適化し、不要なバンドルからの依存関係を減らすことができます。しかし、完全な依存関係がある場合、これは決して起こりません。

import/exportのネイティブサポートが有効になるまでにはしばらく時間がかかります。そしてrequireキーワードは長い間どこにも行きません。

requireとは何ですか?

これはモジュールをロードするnode.js方法です。 ( https://github.com/nodejs/node

Nodeはファイルを読み込むためにシステムレベルの方法を使います。 requireを使うとき、あなたは基本的にそれに頼ります。 requireは、JavaScriptファイル/モジュールをロードするためのuv_fs_open(エンドシステム、Linux、Mac、Windowsに依存)のようなシステムコールで終了します。

これが正しいことを確認するには、Babel.jsを使用してみてください。そうすれば、importキーワードがrequireに変換されることがわかります。

enter image description here

28
prosti

ES6モジュールを使用すると、「ツリーの揺れ」に役立ちます。つまり、Webpack 2、Rollup(または他のバンドル業者)が使用されていない、またはインポートされていないコードパスを識別できるようにするため、結果として得られるバンドルに組み込まれません。これは必要のないコードを削除することでファイルサイズを大幅に減らすことができますが、Webpackなどには必要かどうかを知る方法がないため、CommonJSにはデフォルトでバンドルされています。

これはコードパスの静的解析を使用して行われます。

たとえば、

import { somePart } 'of/a/package';

... package.anotherPartは必須ではないというヒントをバンドラーに与えます(インポートされないのであれば使用できないのではないでしょうか)。

Webpack 2でこれを有効にするには、あなたのtranspilerがCommonJSモジュールを吐き出さないようにする必要があります。 babelでes2015プラグインを使用している場合は、次のように.babelrcで無効にできます。

{
  "presets": [
    ["es2015", { modules: false }],
  ]
}

ロールアップ および他のユーザーとは動作が異なる場合があります - 興味がある場合はドキュメントを参照してください。

27
Lee Benson

非同期ロードや遅延ロードに関しては、import ()のほうがはるかに強力です。非同期でコンポーネントが必要な場合を確認してから、importname__を使用するconstname__変数のように、非同期的にawaitname__を使用します。

const module = await import('./module.js');

それならrequire()を使いたいのなら、

const converter = require('./converter');

実はimport()は実際には非同期です。 ReactConf のneehar venugopalによって述べられているように、これを使ってクライアントサイドアーキテクチャ用の反応コンポーネントを動的にロードすることができます。

また、ルーティングに関しては、それははるかに優れています。それはユーザーがその特定のコンポーネントに特定のWebサイトに接続するときにネットワークログに必要な部分をダウンロードさせる特別なことです。例えばダッシュボードの前のログインページでは、ダッシュボードのすべてのコンポーネントがダウンロードされません。現在必要とされているもの、すなわちログインコンポーネントがあるので、それがダウンロードされるだけであろう。

exportname__についても同じです。ES6exportname__は、CommonJSのmodule.exportsとまったく同じです。

_ note _ - node.jsプロジェクトを開発している場合、importname__を使用する場合はnodeがinvalid token 'import'として例外エラーをスローするので、require()を厳密に使用する必要があります。そのため、nodeはimport文をサポートしません。

更新 - Dan Dascalescu で示唆されているように_:v8.5.0(2017年9月リリース)以降、node --experimental-modules index.mjsではBabelなしでimportname__を使用できます。古いrequirename__の方法では、 後方互換性のあるネイティブESModuleとしてnpmパッケージを公開する _もできます(そしてそうすべきです)。

非同期インポートを使用する場所の詳細については、こちらを参照してください - https://www.youtube.com/watch?v=bb6RCrDaxhw

14
Meet Zaveri

私は個人的にインポートを使用しているので、インポートを使用して必要なメソッド、メンバーをインポートできます。

import {foo, bar} from "dep";

ファイル名: dep.js

export foo function(){};
export const bar = 22

信用はポールシャンに行きます。 詳細情報

5
chandoo

知っておくべき最も重要なことは、ES6モジュールが実際には公式の標準であるのに対して、CommonJS(Node.js)モジュールはそうではないということです。

2019年、ES6モジュールは 84% のブラウザでサポートされています。 Node.jsはそれらを --experimental-modules フラグの後ろに置きますが、 esm と呼ばれる便利なノードパッケージもあり、これは統合を円滑にします。

これらのモジュールシステム間で遭遇する可能性があるもう1つの問題はコードの場所です。 Node.jsはソースがnode_modulesディレクトリに保存されていることを前提としていますが、ほとんどのES6モジュールはフラットなディレクトリ構造にデプロイされています。これらを調整するのは簡単ではありませんが、インストール前後のスクリプトでpackage.jsonファイルをハッキングすることでそれを行うことができます。これがどのように動くかを説明する 同型のモジュールarticle の例です。

2
isysd