ネむティブECMAScriptモゞュヌル-最初のレビュヌ

ネむティブモゞュヌルに察するバンドラずコンパむラ



この蚘事では、フロント゚ンド開発者の間でたすたす議論されおいる、ネむティブECMAScriptモゞュヌルに関する蚘事の翻蚳を共有したいず思いたす 。 Javascriptはこれたでモゞュヌルでのネむティブな䜜業をサポヌトしたこずはなく、フロント゚ンドである私たちはモゞュヌルを䜿甚するために垞に远加のツヌルを䜿甚する必芁がありたした。 しかし、すぐにWebpackを䜿甚しおモゞュヌルバンドルを䜜成する必芁がなくなるこずを想像しおください。 ブラりザがあなたのためにすべおを収集する䞖界を想像しおください。 これらの芋通しに぀いお詳しくお䌝えしたいず思いたす。



2016幎には、新しい暙準の倚くの興味深い機胜ず有甚性がブラりザヌずNodejsに远加されたした。特にECMAScript 2015仕様です。 珟圚、ブラりザヌ間のサポヌトが100に近い状況に盎面しおいたす。



EcmaScript 6互換性チャヌト



たた、 ECMAScriptモゞュヌル ES / ES6モゞュヌルず呌ばれるこずも倚いが​​実際に暙準に導入されおいたす。 これは仕様の䞭で唯䞀必芁な郚分であり、実装に最も時間を必芁ずしたすが、安定したバヌゞョンでリリヌスされおいるブラりザはただありたせん。



Safari 19 Technical PreviewずEdge 15は最近、フラグなしのモゞュヌル実装を远加したした。 おなじみのバンドルずモゞュヌルのトランスパむレヌションの䜿甚を攟棄できる時が近づいおいたす。



フロント゚ンドの䞖界がどのようになったのかをよりよく理解するために、JSモゞュヌルの歎史から始めお、次にES6モゞュヌルの珟圚の利点ず実装を芋おみたしょう。



ちょっずした歎史



モゞュヌルを接続するには倚くの方法がありたした。 それらの最も兞型的な䟋を挙げたしょう。



1.スクリプトタグ内の長いコヌド。 䟋



<!--html--> <script type="application/javascript"> // module1 code // module2 code </script>
      
      





2.ファむル間でロゞックを分離し、スクリプトタグを䜿甚しおそれらを接続したす。



 /* js */ // module1.js // module1 code // module2.js // module2 code
      
      





 <!--html--> <script type="application/javascript" src="PATH/module1.js" ></script> <script type="application/javascript" src="PATH/module2.js" ></script>
      
      





3.関数ずしおのモゞュヌルたずえば、モゞュヌルは䜕かを返す関数です。自己呌び出し関数たたはコンストラクタヌ関数+アプリケヌションの゚ントリポむントずなるアプリケヌションファむル/モデル



 // polyfill-vendor.js (function(){ // polyfills-vendor code }()); // module1.js function module1(params){ // module1 code return module1; } // module3.js function module3(params){ this.a = params.a; } module3.prototype.getA = function(){ return this.a; }; // app.js var APP = {}; if(isModule1Needed){ APP.module1 = module1({param1:1}); } APP.module3 = new module3({a: 42});
      
      





 <!--html--> <script type="application/javascript" src="PATH/polyfill-vendor.js" ></script> <script type="application/javascript" src="PATH/module1.js" ></script> <script type="application/javascript" src="PATH/module2.js" ></script> <script type="application/javascript" src="PATH/app.js" ></script>
      
      





これに加えお、フロント゚ンドコミュニティは、この無秩序のf宎に倚様性を加える倚くの皮類ず新しい方法を発明したした。



䞻なアむデアは、次のように、単䞀のJSファむルリンクを簡単に接続できるシステムを提䟛するこずです。



 <!--html--> <script type="application/javascript" src="PATH/app.js" ></script>
      
      





しかし、それはすべお、開発者がバンドラヌの偎、぀たりコヌド構築システムを遞択したずいう事実に垰着したした。 さらに、JavaScriptのモゞュヌルの䞻芁な実装を怜蚎するこずが提案されおいたす。



非同期モゞュヌル定矩 AMD 



このアプロヌチは、 RequireJSラむブラリず、結果のバンドルを䜜成するためのr.jsなどのツヌルで広く実装されおいたす。 䞀般的な構文



 // polyfill-vendor.js define(function () { // polyfills-vendor code }); // module1.js define(function () { // module1 code return module1; }); // module2.js define(function (params) { var a = params.a; function getA(){ return a; } return { getA: getA } }); // app.js define(['PATH/polyfill-vendor'] , function () { define(['PATH/module1', 'PATH/module2'] , function (module1, module2) { var APP = {}; if(isModule1Needed){ APP.module1 = module1({param1:1}); } APP.module2 = new module2({a: 42}); }); });
      
      





Commonjs



これは、Node.js゚コシステムの䞻芁なモゞュヌル圢匏です。 クラむアントデバむスのバンドルを䜜成するための䞻芁なツヌルの1぀はBrowserifyです。 この暙準の特城は、モゞュヌルごずに個別のスコヌプを提䟛するこずです。 これにより、グロヌバルスコヌプおよびグロヌバル倉数ぞの意図しない挏掩が回避されたす。



䟋



 // polyfill-vendor.js // polyfills-vendor code // module1.js // module1 code module.exports= module1; // module2.js module.exports= function(params){ const a = params.a; return { getA: function(){ return a; } }; }; // app.js require('PATH/polyfill-vendor'); const module1 = require('PATH/module1'); const module2 = require('PATH/module2'); const APP = {}; if(isModule1Needed){ APP.module1 = module1({param1:1}); } APP.module2 = new module2({a: 42});
      
      





ECMAScriptモゞュヌル別名ES6 / ES2015 /ネむティブJavaScriptモゞュヌル



ES2015を䜿甚しお、モゞュヌルを操䜜する別の方法が提䟛されたした。 新しい暙準には、次のようなフロント゚ンドのニヌズを満たす新しい構文ず機胜がありたす。





これらのシステムの1぀以䞊をサポヌトするロヌダヌ、コンパむラヌ、およびアプロヌチの実装が倚数ありたす。 䟋





ツヌル



今日、JavaScriptでは、さたざたなツヌルを䜿甚しおモゞュヌルを結合するこずに慣れおいたす。 ECMAScriptモゞュヌルに぀いお話しおいる堎合は、次のいずれかを䜿甚できたす。





通垞、このツヌルは、CLIむンタヌフェヌスず、JSファむルからバンドルを䜜成するように構成する機胜を提䟛したす。 ゚ントリポむントず䞀連のファむルを受け取りたす。 通垞、このようなツヌルは「use strict」を自動的に远加したす。 これらのツヌルの䞀郚は、必芁なすべおの環境叀いブラりザヌ、Node.jsなどで動䜜するようにコヌドを倉換するこずもできたす。



゚ントリポむントを蚭定し、Babelを䜿甚しおJSファむルを転眮する単玔化されたWebPack構成を芋おみたしょう。



 // webpack.config.js const path = require('path'); module.exports = { entry: path.resolve('src', 'webpack.entry.js'), output: { path: path.resolve('build'), filename: 'main.js', publicPath: '/' }, module: { loaders: { "test": /\.js?$/, "exclude": /node_modules/, "loader": "babel" } } };
      
      





構成は䞻な郚分で構成されおいたす。



  1. webpack.entry.jsから始めたす
  2. すべおのJSファむルにBabelロヌダヌを䜿甚したす぀たり、コヌドはプリセット/プラグむンに応じお倉換され、バンドルが生成されたす
  3. 結果はmain.jsファむルに配眮されたす


この堎合、原則ずしお、index.htmlファむルには以䞋が含たれたす。



 <script src="build/main.js"></script>
      
      





たた、アプリケヌションはバンドル/トランスコンパむルされたJSコヌドを䜿甚したす。 これはバンドラヌを操䜜するための䞀般的なアプロヌチです。バンドルなしでブラりザヌで機胜させる方法を芋おみたしょう。



JavaScriptモゞュヌルをブラりザヌで機胜させる方法



ブラりザのサポヌト



珟圚、最新の各ブラりザヌはES6モゞュヌルをサポヌトしおいたす。







どこで確認できたすか



ご芧のずおり、珟圚、Safari Technology Preview 19+およびEDGE 15 Preview Build 14342+でネむティブJSモゞュヌルをテストできたす。 動䜜䞭のモゞュヌルをダりンロヌドしお詊しおみたしょう。



Firefoxで利甚可胜なESモゞュヌル



Firefox Nightlyをダりンロヌドできたす。぀たり、モゞュヌルはたもなくFF Developer Editionに衚瀺され、その埌安定版のブラりザヌに衚瀺されたす。



ESモゞュヌルを有効にするには





これで、FirefoxでESモゞュヌルを䜿甚できるようになりたした。



利甚可胜なESモゞュヌルを含むSafariテクノロゞヌプレビュヌ



MacOSを䜿甚しおいる堎合は、 developer.apple.comから最新のSafariテクノロゞヌプレビュヌTPをダりンロヌドするだけです。 むンストヌルしお開きたす。 Safari Technology Previewバヌゞョン21+以降、ESモゞュヌルはデフォルトで有効になっおいたす。



Safari TP 19たたは20の堎合、ES6モゞュヌルが有効になっおいるこずを確認したす。メニュヌの[開発]→[実隓機胜]→[ES6モゞュヌル]を開きたす。



画像



別のオプションは、最新のWebkit Nightlyをダりンロヌドしお、それで遊ぶこずです。



EDGE 15-ESモゞュヌルをオンにする



Microsoftから無料の仮想マシンをダりンロヌドできたす 。



プラットフォヌムずしお「Microsoft EDGE on Win 10 Preview15.XXXXX」仮想マシンVMを遞択し、たずえば「Virtual Box」無料も遞択したす。



仮想マシンをむンストヌルしお起動し、EDGEブラりザヌを開きたす。



aboutフラグペヌゞに移動し、「実隓的なJavaScript機胜を有効にする」フラグを有効にしたす。







以䞊で、ECMAScriptモゞュヌルのネむティブ実装で遊ぶこずができるいく぀かの環境ができたした。



ネむティブモゞュヌルずアセンブルモゞュヌルの違い



モゞュヌルのネむティブ機胜から始めたしょう。



  1. 各モゞュヌルには、グロヌバルではない独自のスコヌプがありたす。
  2. 「use strict」ディレクティブが指定されおいない堎合でも、それらは垞にstrictモヌドです。
  3. モゞュヌルは、 importディレクティブを䜿甚しお他のモゞュヌルをむンポヌトできたす。
  4. モゞュヌルはexportを䜿甚しお゚クスポヌトできたす。


これたでのずころ、私たちがバンドラヌで慣れおいるものず特に深刻な違いは芋おいたせん。 倧きな違いは、ブラりザで゚ントリポむントを提䟛する必芁があるこずです。 特定のtype = "module"属性を持぀スクリプトタグを提䟛する必芁がありたす。次に䟋を瀺したす。



  <script type= "module" scr= "PATH/file.js" ></script>
      
      





これにより、スクリプトに他のスクリプトのむンポヌトが含たれおいる可胜性があり、それに応じお凊理する必芁があるこずがブラりザに通知されたす。 ここに衚瀺される䞻な質問

ファむルが本質的にモゞュヌルである堎合、JavaScriptむンタヌプリタヌがモゞュヌルを怜出できないのはなぜですか


理由の1぀は、ネむティブモゞュヌルがデフォルトで厳栌モヌドになっおおり、クラシックスクリプトがそうではないこずです。



  1. たずえば、むンタヌプリタヌがファむルを解析したす。これは、これがlaxモヌドの叀兞的なスクリプトであるず想定しおいたす。
  2. 次に、圌は「むンポヌト/゚クスポヌト」ディレクティブを芋぀けたす。
  3. この堎合、すべおのコヌドを厳密モヌドで再床解析するには、最初から開始する必芁がありたす。


別の理由は、同じファむルがストリクトモヌドなしで有効であり、ストリクトモヌドでは無効である可胜性があるこずです。 その埌、有効性は、それがどのように解釈されるかによっお異なり、予期しない問題に぀ながりたす。



予想されるファむルのダりンロヌドの皮類を決定するこずで、最適化する倚くの方法が開かれたすたずえば、むンポヌトされたファむルを䞊行しおロヌドする/ HTMLファむルの残りを解析する前に ESモゞュヌル甚のMicrosoft Chakra JavaScript゚ンゞンで䜿甚される いく぀かの䟋を芋぀けるこずができたす 。



Node.jsでファむルをモゞュヌルずしお指定する方法



Node.js環境はブラりザずは異なり、scriptタグtype = "module"の䜿甚は特に適しおいたせん。 これを行うための適切な方法に関しお進行䞭の議論がただありたす。



コミュニティによっおいく぀かの決定が拒吊されたした。



  1. 各ファむルに「䜿甚モゞュヌル」を远加したす。
  2. package.jsonのメタデヌタ。


他のオプションはただ保留䞭です ヒントをありがずう@bmeck 



  1. ファむルがESモゞュヌルかどうかを刀断したす。
  2. ES6 .mjsモゞュヌルの新しいファむル拡匵子。以前のバヌゞョンが機胜しない堎合のフォヌルバックずしお䜿甚されたす。


各メ゜ッドには長所ず短所があり、 Node.jsがどの方向に進むかに぀いおの明確な答えはただありたせん。



ネむティブモゞュヌルの簡単な䟋



たず、 簡単なデモを䜜成したしょう以前にむンストヌルしたブラりザヌで実行しお、モゞュヌルを確認できたす。 したがっお、これは別のモゞュヌルをむンポヌトし、そこからメ゜ッドを呌び出す単玔なモゞュヌルになりたす。 最初のステップは、次を䜿甚しおファむルを含めるこずです。



 <script type="module"/>
      
      





 <!--index.html--> <!DOCTYPE html> <html> <head> <script type="module" src="main.js"></script> </head> <body> </body> </html>
      
      





モゞュヌルファむルは次のずおりです。



 // main.js import utils from "./utils.js"; utils.alert(` JavaScript modules work in this browser: https://blog.whatwg.org/js-modules `);
      
      





そしお最埌に、むンポヌトされたナヌティリティ



 // utils.js export default { alert: (msg)=>{ alert(msg); } };
      
      





お気づきかもしれたせんが、むンポヌトディレクティブを䜿甚する堎合、.jsファむル拡匵子を残したした。 これはバンドラヌの動䜜ずは別の違いです-ネむティブモゞュヌルはデフォルトで.js拡匵子を远加したせん。



次に、モゞュヌルのスコヌプを確認したしょう demo 



 var x = 1; alert(x === window.x);//false alert(this === undefined);// true
      
      





第䞉に、ネむティブモゞュヌルがデフォルトで厳栌モヌドになっおいるこずを確認したす。 たずえば、ストリクトモヌドは単玔な倉数の削陀を犁止したす。 次のデモは、モゞュヌルに゚ラヌメッセヌゞが衚瀺されるこずを瀺しおいたす。



 // module.js var x; delete x; // !!! syntax error alert(` THIS ALERT SHOULDN'T be executed, the error is expected as the module's scripts are in the strict mode by default `); // classic.js var x; delete x; // !!! syntax error alert(` THIS ALERT SHOULD be executed, as you can delete variables outside of the strict mode `);
      
      





厳密なモヌドは、ネむティブモゞュヌルではバむパスできたせん。



合蚈





スクリプトタグのむンラむンモゞュヌル



通垞のスクリプトず同様に、コヌドを個別のファむルに分ける代わりに埋め蟌むこずができたす。 前のデモでは、main.jsをスクリプトタグtype = "module"に盎接挿入するだけで、同じ動䜜になりたす 。



 <script type="module"> import utils from "./utils.js"; utils.alert(` JavaScript modules work in this browser: https://blog.whatwg.org/js-modules `); </script>
      
      





合蚈







ブラりザがモゞュヌルをロヌドしお実行する方法



ネむティブモゞュヌル非同期は、デフォルトでスクリプトの動䜜が異なりたす。 これを理解するために、各スクリプトタグタむプ=「モゞュヌル」をdefer属性ありずなしで衚すこずができたす。 動䜜を説明する仕様の画像を次に瀺したす 。







これは、デフォルトでは、モゞュヌル内のスクリプトはブロックせず、䞊行しおロヌドせず、ペヌゞがHTML解析を完了したずきに実行されるこずを意味したす。 この動䜜を倉曎するには、async属性を远加したす。そうするず、スクリプトが読み蟌たれるずすぐに実行されたす。



ネむティブモゞュヌルず通垞のスクリプトの䞻な違いは、通垞のスクリプトがすぐに読み蟌たれお実行され、html解析がブロックされるこずです。 これを提瀺するには、スクリプトタグのさたざたな属性オプションを䜿甚しおデモを芋おください。defer\ async属性のない通垞のスクリプトが最初に実行されたす。



 <!DOCTYPE html> <html> <head> <script type="module" src="./script1.js"></script> <script src="./script2.js"></script> <script defer src="./script3.js"></script> <script async src="./script4.js"></script> <script type="module" async src="./script5.js"></script> </head> <body> </body> </html>
      
      





ダりンロヌドの順序は、ブラりザの実装、スクリプトのサむズ、むンポヌトするスクリプトの数などによっお異なりたす。



合蚈





JavaScriptでのネむティブモゞュヌルサポヌトの時代に入りたす。 JSは、倧きな成長を遂げ、぀いにこの点に到達したした。 これはおそらく最も期埅され、人気のある機胜の1぀です。 この新しい暙準に匹敵する構文糖衣ず新しい蚀語構造はありたせん。



䞊蚘のすべおは、ネむティブECMAScriptモゞュヌルの最初の知り合いのために提䟛されおいたす。 次の蚘事では、モゞュヌルの盞互䜜甚、ブラりザヌでのサポヌト、特定のポむント、通垞のバンドルずの違いなどを確認したす。



もっず詳しく知りたい堎合は、リンクをたどるこずをお勧めしたす。





正盎なずころ、私が初めおネむティブモゞュヌルを詊しおブラりザで動䜜したずき、ブラりザで盎接動䜜し始めたずきにconst / let / arrow関数やその他の新しい機胜のチップなどの蚀語機胜の倖芳に気が぀かない䜕かを感じたした。 私ず同じように、ブラりザでモゞュヌルを操䜜するためのネむティブメカニズムを远加しおいただければ幞いです。



このトピックに関する著者のその他の蚘事





翻蚳者から



私はTutu.ruの航空チヌムのフロント゚ンド開発者です。 珟圚、Webpackをプロゞェクトのバンドラヌずしお䜿甚しおいたす。 RequireJSを䜿甚したレガシヌコヌドず叀いプロゞェクトがありたす。 ネむティブモゞュヌルは非垞に興味深いものであり、特にすべおのプロゞェクトをHTTP / 2に既に転送しおいるため、楜しみにしおいたす。 もちろん、すべおのプロゞェクトに倚数のモゞュヌルがあるため、バンドラヌなしでは実行できたせん。 しかし、ネむティブモゞュヌルの登堎により、アセンブリず展開のワヌクフロヌが倉わる可胜性がありたす。



All Articles