回答:
どちらを使用してもパフォーマンス上のメリットはありますか?
ES6モジュールをネイティブでサポートするJavaScriptエンジンはまだないことに注意してください。あなたは自分がバベルを使っていると言っていました。とにかくimport
、Babelはデフォルトでexport
CommonJS(require
/ module.exports
)に変換して宣言します。したがって、ES6モジュール構文を使用していても、Nodeでコードを実行すると、CommonJSが内部で使用されます。
CommonJSとES6モジュールの間には技術的な違いがあります。たとえば、CommonJSではモジュールを動的にロードできます。ES6はこれを許可していませんが、開発中のAPIがあります。
ES6モジュールは標準の一部なので、私はそれらを使用します。
ES6 import
、動作require
が異なりました。CommonJSは、クラスが1つしかないときにクラス自体をエクスポートします。ES6は複数のクラスがあるように.ClassName
エクスポートするので、エクスポートされたクラスを取得するために使用する必要があります。実際の実装をもたらす任意の他の違いがあります
module.exports = ...;
と同等export default ...
です。exports.foo = ...
と同等export var foo = ...
です。
import
Webpack 2 / Rollup(およびES6ツリーのシェイクを可能にする他の任意のバンドラー)と共に使用されるBabelは最終的にNodeのCommonJSにトランスパイリングしますが、同等のコードNodeのクランチよりも大幅に小さいファイルで終了する可能性があることは注目に値しますES6がインポート/エクスポートの静的分析を可能にするという事実のために、require
正確に使用する。これは(まだ)Nodeに影響を与えませんが、コードが最終的に単一のブラウザーバンドルとして完成する場合は、確かに可能です。
検討する必要のある使用法/機能がいくつかあります。
必要とする:
require
、複数のがある場合、それらは1つずつ読み込まれて処理されます。ES6インポート:
また、Requireモジュールシステムは標準ベースではありません。ES6モジュールが存在するようになった今、標準になる可能性はほとんどありません。将来的には、さまざまな実装でES6モジュールがネイティブにサポートされ、パフォーマンスの点で有利になります。
require
とにかくES6モジュールをコンパイルする可能性があるため、ノードのモジュールシステムとローダーをとにかく使用しています。
主な利点は構文です:
ES6モジュールでパフォーマンスの利点が見られる可能性はほとんどありません。ブラウザでES6機能が完全にサポートされている場合でも、モジュールをバンドルするために追加のライブラリが必要です。
node --experimemntal-modules index.mjs
使用できますimport
。npmパッケージをネイティブESModuleとして公開することもできます(そうする必要があります)require
。以前の方法との下位互換性があります。多くのブラウザーは、動的インポートもネイティブでサポートしています。
どちらを使用してもパフォーマンス上のメリットはありますか?
現在の答えはノーです。現在のブラウザエンジンはどれもimport/export
ES6標準から実装されていないためです。
いくつかの比較チャートhttp://kangax.github.io/compat-table/es6/はこれを考慮に入れていないため、Chromeのほぼすべてのグリーンが表示される場合は注意してください。import
ES6のキーワードは考慮されていません。
つまり、V8を含む現在のブラウザエンジンは、JavaScriptディレクティブを介してメインJavaScriptファイルから新しいJavaScriptファイルをインポートできません。
(V8がES6仕様に従ってそれを実装するまで、まだ数バグまたは数年先の可能性があります。)
このドキュメントは私たちが必要とするものであり、このドキュメントは私たちが従わなければならないものです。
また、ES6標準では、(ヘッダー).h
ファイルがあるプログラミング言語Cのように、モジュールを読み取る前にモジュールの依存関係が存在する必要があると述べています。
これは適切で十分にテストされた構造であり、ES6標準を作成した専門家はそれを念頭に置いていたと思います。
これにより、Webpackまたは他のパッケージバンドルが、いくつかの特別な場合にバンドルを最適化し、バンドルからの不要な依存関係を減らすことができます。しかし、完全な依存関係がある場合、これは決して起こりません。
import/export
ネイティブサポートが公開されるまでにはしばらく時間がかかり、require
キーワードはどこにも行きません。
なにrequire
?
これはnode.js
モジュールをロードする方法です。(https://github.com/nodejs/node)
ノードはシステムレベルのメソッドを使用してファイルを読み取ります。を使用するときは、基本的にそれに依存しrequire
ます。(エンドシステム、Linux、Mac、Windowsに依存する)JavaScriptファイル/モジュールをロードするrequire
ようなシステムコールで終了しuv_fs_open
ます。
これが正しいことを確認するには、Babel.jsを使用すると、import
キーワードがに変換されrequire
ます。
import
Webpack 2 / Rollupビルドプロセスで使用すると、未使用のモジュール/コードを「ツリーシェイク」することにより、最終的なバンドルに巻き込まれる可能性があるファイルサイズを潜在的に減らすことができます。小さいファイルサイズ=ダウンロードの高速化=クライアントでの初期化/実行の高速化。
import
キーワードをネイティブに許可していないことでした。または、これは、JavaScriptファイルから別のJavaScriptファイルをインポートできないことを意味します。これが、これら2つのパフォーマンスの利点を比較できない理由です。しかしもちろん、Webpack1 / 2やBrowserifyなどのツールは圧縮を処理できます。彼らは首から首までです:gist.github.com/substack/68f8d502be42d5cd4942
import
し、export
特定のコードパスをインポート静的宣言され、一方、require
動的とすることができるので、使用されていないコードにバンドル。パフォーマンス上の利点は、indirect-- WebPACKの2及び/又はロールアップができ、潜在的に高速ダウンロードにある小さいバンドルサイズをもたらし、したがって、(ブラウザの)エンドユーザにきびきび見えます。これは、すべてのコードがES6モジュールで記述されている場合にのみ機能するため、インポートを静的に分析できます。
import/export
がに変換されrequire
、付与されます。しかし、このステップの前に何が起こるかは、「パフォーマンス」強化と見なすことができます。例:lodash
がES6で記述されている場合import { omit } from lodash
、究極のバンドルには「除外」のみが含まれ、他のユーティリティは含まれませんが、シンプルバンドルはrequire('lodash')
すべてをインポートします。これにより、バンドルサイズが大きくなり、ダウンロードに時間がかかるため、パフォーマンスが低下します。もちろん、これはブラウザのコンテキストでのみ有効です。
ES6モジュールを使用すると、「ツリーの揺れ」に役立ちます。つまり、Webpack 2、Rollup(または他のバンドラー)を有効にして、使用/インポートされていないコードパスを識別し、結果のバンドルに含めないようにします。これにより、不要なコードを排除することでファイルサイズを大幅に削減できますが、CommonJSにはデフォルトでバンドルされています。これは、Webpackなどが必要かどうかを知る方法がないためです。
これは、コードパスの静的分析を使用して行われます。
たとえば、次のように使用します。
import { somePart } 'of/a/package';
... package.anotherPart
バンドラーに不要なヒントを提供します(インポートされない場合、使用できません-正しいですか?)。バンドルする必要はありません。
Webpack 2でこれを有効にするには、トランスパイラーがCommonJSモジュールを吐き出さないようにする必要があります。あなたが使用している場合はes2015
プラグインをバベルと、あなたはあなたにそれを無効にすることができます.babelrc
ので、のように:
{
"presets": [
["es2015", { modules: false }],
]
}
ロールアップなどは動作が異なる場合があります。興味がある場合はドキュメントを参照してください。
非同期読み込みまたは遅延読み込みの場合、import ()
はるかに強力です。非同期の方法でコンポーネントが必要な場合を確認してから、を使用import
するconst
変数のように、非同期の方法でそれを使用しますawait
。
const module = await import('./module.js');
または、使用したい場合require()
は、
const converter = require('./converter');
物事はimport()
実際には非同期です。でneehar venugopalで述べたようにReactConf、あなたはクライアント側のアーキテクチャのコンポーネントを動的に反応する負荷にそれを使用することができます。
また、ルーティングに関しては、はるかに優れています。これは、ユーザーが特定のコンポーネントに特定のWebサイトに接続したときに、ネットワークログに必要な部分をダウンロードさせる特別なものです。例えば、ダッシュボードがダッシュボードのすべてのコンポーネントをダウンロードする前にログインページ。現在必要なのはログインコンポーネントなので、ダウンロードされるのはそれだけです。
同じことがexport
当てはまりexport
ます。ES6 はCommonJSとまったく同じmodule.exports
です。
注 -node.jsプロジェクトを開発している場合は、厳密に使用する必要があります。これは、を使用する場合require()
と同様に、ノードが例外エラーをスローinvalid token 'import'
するためimport
です。したがって、ノードはインポート文をサポートしていません。
更新-Dan Dascalescuによって提案されたように:v8.5.0(2017年9月リリース)以降、Babelなしでnode --experimental-modules index.mjs
使用できますimport
。npmパッケージをネイティブESModuleとして公開することもできます(そうする必要があります)require
。 以前の方法との下位互換性があります。
非同期インポートを使用する場所の詳細については、こちらをご覧ください-https://www.youtube.com/watch?v = bb6RCrDaxhw
知っておくべき最も重要なことは、ES6モジュールは確かに公式の標準ですが、CommonJS(Node.js)モジュールはそうではないということです。
2019年、ES6モジュールは84%のブラウザーでサポートされます。Node.jsはそれらを--experimental-modulesフラグの後ろに配置しますが、esmと呼ばれる便利なノードパッケージもあり、これにより統合がスムーズになります。
これらのモジュールシステム間で遭遇する可能性が高いもう1つの問題は、コードの場所です。Node.jsは、ソースがnode_modules
ディレクトリに保持されていると想定していますが、ほとんどのES6モジュールはフラットなディレクトリ構造でデプロイされています。これらの調整は簡単ではありませんが、package.json
インストール前後のスクリプトを使用してファイルをハッキングすることで実行できます。ここに同形モジュールの例とそれがどのように機能するかを説明する記事があります。
私は個人的にインポートを使用しています。インポートを使用して、必要なメソッド、メンバーをインポートできるからです。
import {foo, bar} from "dep";
ファイル名: dep.js
export foo function(){};
export const bar = 22
クレジットはポールシャンに行く。詳細情報。
require
方法はありますか?
const {a,b} = require('module.js');
同様に動作します...エクスポートa
した場合b
module.exports = { a: ()={}, b: 22 }
-@BananaAcidレスポンスの後半
現在、ES6インポートの時点で、エクスポートは常にCommonJSにコンパイルされているため、どちらを使用してもメリットません。ES6の使用をお勧めしますが、ブラウザからのネイティブサポートがリリースされたときに有利になるはずです。その理由は、CommonJSではすべてのファイルを必要とする一方で、1つのファイルからパーシャルをインポートできるためです。
ES6→ import, export default, export
CommonJS→ require, module.exports, exports.foo
以下はそれらの一般的な使用法です。
ES6エクスポートのデフォルト
// hello.js
function hello() {
return 'hello'
}
export default hello
// app.js
import hello from './hello'
hello() // returns hello
ES6複数エクスポートおよび複数インポート
// hello.js
function hello1() {
return 'hello1'
}
function hello2() {
return 'hello2'
}
export { hello1, hello2 }
// app.js
import { hello1, hello2 } from './hello'
hello1() // returns hello1
hello2() // returns hello2
CommonJS module.exports
// hello.js
function hello() {
return 'hello'
}
module.exports = hello
// app.js
const hello = require('./hello')
hello() // returns hello
CommonJS module.exports multiple
// hello.js
function hello1() {
return 'hello1'
}
function hello2() {
return 'hello2'
}
module.exports = {
hello1,
hello2
}
// app.js
const hello = require('./hello')
hello.hello1() // returns hello1
hello.hello2() // returns hello2
なぜ(おそらく最適化-遅延読み込み?)それはそのように機能しているのimport
かわかりませんが、インポートしたモジュールを使用しないとコードを解析できない可能性があることに気付きました。
これは、場合によっては予期されない動作になる可能性があります。
サンプルの依存関係として、嫌われているFooクラスを取り上げます。
foo.ts
export default class Foo {}
console.log('Foo loaded');
例えば:
index.ts
import Foo from './foo'
// prints nothing
index.ts
const Foo = require('./foo').default;
// prints "Foo loaded"
index.ts
(async () => {
const FooPack = await import('./foo');
// prints "Foo loaded"
})();
一方:
index.ts
import Foo from './foo'
typeof Foo; // any use case
// prints "Foo loaded"
node --experimental-modules index.mjs
import
Babelなしで使用でき、Node 8.5.0以降で動作します。npmパッケージをネイティブESModuleとして公開することもできます(そうする必要があります)require
。以前の方法との下位互換性があります。