JavaScriptモゞュヌルパス



この蚘事の執筆時点では、JavaScriptには公匏のモゞュラヌシステムはなく、誰もができる限りモゞュヌルを゚ミュレヌトしおいたした。

モゞュヌルたたは同様の構造は、成人向けプログラミング蚀語の䞍可欠な郚分です。 他に方法はありたせん モゞュヌルを䜿甚するず、スコヌプを制限したり、アプリケヌションの䞀郚を再利甚したり、アプリケヌションをより構造化したり、リ゜ヌスをノむズから分離したり、䞀般的にコヌドをより芋やすくしたりできたす。

JavaScriptには独自の雰囲気がありたす-蚀語には公匏のモゞュヌルはありたせん。さらに、すべおのファむルはリモヌトにあり、1぀のアプリケヌションストリヌムです。 ダりンロヌドに関するいく぀かの奇劙な問題を垞に解決し、ダりンロヌド時間を短瞮するためにモゞュヌルを1぀のファむルに巧劙にパックする必芁がありたす。 二重の暙準ず戊い、異なる圢匏のモゞュヌルを適応させる必芁がある堎合がありたす。

実際、圌らは「DOMをパッチ」するだけでなく、巚倧なプロゞェクトをJavaScriptで行うこずができるずは考えおいなかったため、モゞュヌルに぀いおは考えおいたせんでした。 はい、将来に぀いおは考えたせんでした。 そしお、突然、未来が来たした すべおがすでにそこにあるようで、JavaScriptのモゞュヌルは、控えめに蚀っおも遅いです。 したがっお、開発者はある皮のモゞュラヌ゚ミュレヌタをスピンしお発明する必芁がありたす。

倚くの人が優れた蚘事「Addy Osmani Writing Modular JavaScript With AMD、CommonJSES Harmony 」を読んだこずがあるず思いたす。これは圌の著曞「JavaScriptデザむンパタヌンの孊習 」の章の1぀になり、  「叀い」モゞュヌルに぀いおの詳现2010。

これらの蚘事を翻蚳したり、それらを寄せ集めたりする぀もりはありたせん。 私の蚘事では、モゞュラヌパスに぀いお説明したす。 「叀い」モゞュヌルから「新しい」モゞュヌルぞの移行方法ず、珟圚䜿甚しおいるものずその理由に぀いお。

この蚘事は3぀のパヌトで構成されおいたすモゞュヌルパスりェむ、モゞュヌルガッツの䞀臎郚分、およびモゞュヌルの䞀般的なタむプ

tl; dr
私は「非モゞュヌル」からAMD 、 browserifyを経おLMDに至るたでの長い道のりを歩んできたした。 将来、 ECMAScript 6 Modulesに䟝存したす。

モゞュヌルパス


ステヌゞ1モゞュヌルなし

JavaScriptコヌドがほずんどなかった圓時、私はモゞュヌルを完党に省きたした。 それから私はそれらを必芁ずしたせんでした。 モゞュラヌシステムを導入するず、50行のコヌドが150行になりたす。たた、モゞュヌルなしでDOMにすばやくパッチを適甚できたした。 私は名前空間で完党に管理し、アセンブリを䜿甚したせんでした。そしお、ミニファむアヌはそのずき開発されたせんでした。

モゞュヌル
MyNs.MyModule = function () {}; MyNs.MyModule.prototype = { // ... }; 

組立
 <script src="myNs.js"/> <script src="myNs/myModule.js"/> 

catを䜿甚しおファむルを収集し始めたずき、私のアプリケヌションの進捗はさらに半歩進みたした。
 $ cat js/*.js > build.js 


ステヌゞ2前凊理

進行は止たっおおらず、私の50行のコヌドは埐々に1500になり、サヌドパヌティのラむブラリずそのプラグむンを䜿い始めたした。 そしお、私が曞いたアプリケヌションは、Rich Internet Applicationず呌ぶこずもできたす。 モゞュヌルぞの分割ずそれらの郚分的な分離は、圓時の私の問題を解決したした。 アセンブリには、プリプロセッサを䜿甚し始めたした。 倚くのモゞュヌルがあり、䟝存関係がありたした。䟝存関係を自分の手で解決したくなかったので、前凊理が䞍可欠でした。 私は名前空間を䜿甚したしたが、それらには倧隒ぎがありたした
 if (typeof MyNamespace === 'undefined') { var MyNamespace = {}; } 

䜙分な萜曞き
 new MyNamespace.MyConstructor(MyNamespace.MY_CONST); // vs new MyConstructor(MY_CONST); 

そしお圓時のミニフィケヌタヌはこのコヌドをうたく圧瞮しおいたせんでした
 new a.MyConstructor(a.MY_CONST); // vs new a(b); 

完党な分離を適甚し始め、名前空間を砎棄しおスコヌプに眮き換えたずき、私のモゞュヌルは少し前進したした。 そしお圌はこれらのモゞュヌルを䜿い始めたした
 include('deps/dep1.js'); var MyModule = (function () { var MyModule = function () {}; MyModule.prototype = { // ... }; return MyModule; })(); 

そしお、そのようなアセンブリ
 (function () { include('myModule.js'); }()); 

そしお同じ前凊理
 $ includify builds/build.js index.js 

各モゞュヌルにはロヌカルスコヌプがあり、アセンブリ党䜓が別のIEFEでラップされたす。 これにより、モゞュヌルを盞互に保護し、アプリケヌション党䜓をグロヌバルから保護できたす。

ステヌゞ3AMD


ある日、Redditを読んでいるずきに、AMDずRequireJSに関する蚘事に出䌚いたした。

小さな䜙談。 実際、AMDのアむデアはYUI Modulesずよくドピレンから借りたものです。 モゞュヌルを䜿甚しお宣蚀するために、䜙分な文字を蚘述する必芁がなくなったため、構成も簡単になりたした。

だった
 YUI().use('dep1', function (Y) { Y.dep1.sayHello(); }); 

になっおいたす
 require(['dep1'], function (dep1) { dep1.sayHello(); }); 

AMDのこずを知り、私はこの時たですべおが間違っおいたこずに気付きたした。 require()ずdefine()をrequire()ずdefine()関数require() 2぀だけで、私の問題はすべお解決されたした モゞュヌルは䟝存関係自䜓をロヌドし始め、正垞な゚クスポヌトずむンポヌトが珟れたした。 モゞュヌルは3぀の郚分むンポヌト、゚クスポヌト、モゞュヌル本䜓に分割され、簡単に理解できたした。 たた、圌が必芁ずし、゚クスポヌトするリ゜ヌスを芋぀けるこずも容易になりたした。 コヌドは構造化され、よりクリヌンになりたした

モゞュヌル
 define('myModule', ['dep1', 'dep2'], function (dep1, dep2) { var MyModule = function () {}; MyModule.prototype = { // ... }; return MyModule; }); 

組立
 $ node r.js index.js bundle.js 

しかし、それほど単玔ではありたせん...

ステヌゞ4AMDぞの倱望

䞊に瀺したのは、理想的なモゞュヌルず完璧なアセンブリです。 これは実際のプロゞェクトでは発生したせん。 たた、モゞュヌルには倚くの䟝存関係がありたす。 その埌、次のようになりたす。
 require(['deps/dep1', 'deps/dep2', 'deps/dep3', 'deps/dep4', 'deps/dep5', 'deps/dep6', 'deps/dep7'], function ( dep1, dep2, dep3, dep4, dep5, dep6, dep7) { return function () { return dep1 + dep2; }; }); 

このモゞュヌルを䜿甚できたすが、倧隒ぎしたす。 この問題を克服するために、Simplified CommonJSでそのようなモゞュヌルを䜜り盎すこずができたす。 この堎合でも、 define()ラッパヌを䜜成しお、正盎なCommonJSモゞュヌルを䜜成し、 r.jsを䜿甚しおそれらをビルドする必芁はありr.js
 define(function (require, module, exports) { var dep1 = require('dep1'), dep2 = require('dep2'), dep3 = require('dep3'), dep4 = require('dep4'), dep5 = require('dep5'), dep6 = require('dep6'), dep7 = require('dep7'); return function () { return dep1 + dep2; }; }); 


RequireJSのSimplified CommonJS圢匏は「ネむティブではなく」、開発者が䜜成する必芁がありたした。 このようなモゞュヌルの䜜成を開始するず、RequireJSは正芏者によるこのモゞュヌルの䟝存関係の怜玢を開始したす。



そしお、おそらく䜕かが芋぀かりたせん
 require("myModule//"); require("my module"); require("my" + "Module"); var require = r; r("myModule"); 

このコヌドは有効ですが、単䞀のモゞュヌルはありたせん。 もちろん、この䟋は抜象的であり、いく぀かの名前は䞍自然ですが、テンプレヌトやいく぀かの工堎など、モゞュヌル名の動的な構築のケヌスによく出くわしたした。

もちろん、RequireJSにはこれに察する解決策がありたす-そのような各モゞュヌルをconfigに登録したす
 ({ "paths": { "myModule": "modules/myModule.js" } }) 

たた、そのようなモゞュヌルテンプレヌトが倚数あり、毎回構成に新しいモゞュヌルを曞きたくないため、構成を動的に生成するなど、あらゆる皮類の魔法でコヌドが成長し始めたす。 たた、「動的モゞュヌル」を䜿甚しないこずは、䜿甚可胜な機胜を䜿甚するず愚かです。

私は正盎なCommonJSモゞュヌルを曞き始め、開発䞭でもr.jsを䜿甚しおアセンブリを䜿甚したした。 AMDが拒吊されたこずで、Node.jsでこれらのモゞュヌルを魔法なく䜿甚できるようになりたした。 私はこのツヌルが基本的に私に合っおいるこずを理解し始めたしたが、束葉杖ず䜙分な研磚が必芁です。

RequireJSが提䟛しおくれた動的ロヌディングモゞュヌルオプションは必芁ありたせんでした。 開発ず本番で最も類䌌したコヌドがあるこずを確認したかったので、開発䞭のモゞュヌルの非同期読み蟌みは私には適さなかったため、1぀のファむルにモゞュヌルを収集したした。

プロゞェクトの䞀郚は起動時に読み蟌たれ1リク゚スト、残りの郚分はオンデマンドで読み蟌たれたした。 そしお、それらは小さなリク゚ストの束ではなく、1぀の倧きなリク゚スト1mファむルの耇数のモゞュヌルのアセンブリでロヌドされたした。 これにより、時間ずトラフィックの䞡方が節玄され、ネットワヌク゚ラヌのリスクが軜枛されたした。

たた、いく぀かのアセンブリを䜜成する必芁がある堎合もありたす。 たずえば、テスト環境向けのロシア語ロケヌルのアプリケヌションや、䌁業ネットワヌク向けの英語版IE甚に最適化されたアプリケヌションなどです。 たたは、広告が無効になっおいるりクラむナ向けiPad甚に最適化されたアプリケヌション。 無秩序が君臚し、コピヌペヌスト...

RequireJsの哲孊では、 require()があらゆるリ゜ヌスを生産するための普遍的なプラントであるずいう事実は奜きではありたせんでした。 require()は、プラグむンず既にロヌドされたモゞュヌルの抜象化を行いたす。䜕らかの理由でプラグむンが接続されなかった堎合、䜕らかの圢でプラグむンを明瀺的にロヌドせず、それを䜿甚しおリ゜ヌスをロヌドしたす。
 require(['async!i18n/data', 'pewpew.js', 'text!templates/index.html'], fucntion (data, pewpew, template) { }); 

リ゜ヌスが単調であるか、リ゜ヌスがあたり倚くないプロゞェクトでは、これは玄

ステヌゞ5モゞュヌル怜玢

もうそんなふうに生きおいけないこずに気づいた...

1぀のモゞュヌルはCommonJSである必芁がありたす

Node.jsずJS @ DOMの䞡方で同じモゞュヌルを実行する必芁がある非垞に頻繁なケヌス。 ほずんどの堎合、これらは倖郚環境ファむルシステム/ DOMたたはそれから抜象化された郚分に関連しないいく぀かのモゞュヌルですテンプレヌト最も䞀般的な郚分、時間を扱う機胜、フォヌマット機胜、ロヌカリれヌション、バリデヌタヌ...

AMDを䜜成し、䜕かを再利甚する必芁がある堎合、2぀の方法がありたす。AMDをCJSに曞き換えるか、node-requireを䜿甚したす。 倚くの堎合、䜕も倉曎する必芁がないため、2番目のオプションを遞択したす。 しかし。 次に、Node.jsの既存のモゞュヌルロヌドシステムに察する奇劙な抜象化である、モゞュヌル匏の混乱が珟れたす。 Node.jsのAMDモゞュヌルが本圓に奜きではありたせんでした。

CJSは、Node.jsずの互換性に加えお、 define()ラッパヌず、関数本䜓をフォヌマットする远加のむンデントを奪われおいたす。 その芁件ず゚クスポヌトは、 define() wayよりも芖芚的でES6モゞュヌルに近いです。 自分で比范しおください

ES6モゞュヌル
 import "dep1" as dep1; import "dep2" as dep2; export var name = function () { return dep1 + dep2; }; 

CommonJS /モゞュヌル
 var dep1 = require("dep1"), dep2 = require("dep2"); exports.name = function () { return dep1 + dep2; }; 

AMD
 require(['dep1', 'dep2'], function (dep1, dep2) { return { name: function () { return dep1 + dep2; } }; }); 

そしお、AMDに戻る必芁が生じたずしおも、たったく問題はありたせん。r.jsがCJSモゞュヌルをラップするように、蚭定に1行だけ登録する必芁がありたす。

2モゞュヌルビルダヌ

今日、CoffeeScriptを曞かなくおも、すべおがうたくいき、䜕らかの圢でスクリプトをチェック、収集、圧瞮したす。

CJSモゞュヌルを適応させるには、コレクタヌが私のためにできるラッパヌが必芁です。 コレクタヌは、すべおのモゞュヌルが存圚するかどうか、モゞュヌルの名前を間違えたかどうか、すべおのプラグむンを宣蚀したかどうかも確認できたす。

アセンブリの結果ずしお、䜜業に必芁なモゞュヌルずスクリプトの䞡方を含む1぀のファむルを取埗したいず思いたす。

アプリケヌションを「マむスクリプト」ず「マむニングではない」「キャッシュのために」ブヌトロヌダヌコヌドずコヌドを別々に接続するに分割するこずは、ほずんど単䞀ペヌゞのWebアプリケヌションを蚘述し、今日キャッシュを掗い流すこずができるため、意味がありたせんでした分。 たた、オヌルむンワンアセンブリにより、アップグレヌド䞭に「モゞュヌルロヌダヌ」ずの互換性の問題を取り陀くこずができたす。

3柔軟な構成システム䟝存関係、継承、ミックスむン

すでに曞いたように、私のアプリケヌションには、さたざたなデバむス、ブラりザヌ、環境、およびロケヌル甚のアセンブリがたくさんありたす。 䞍芁なコピヌず貌り付けや萜曞きをせずに控えめな構成システムを取埗したかったのです。

たずえば、 prod configがありたす; dev configはそれから継承され、いく぀かのモゞュヌルを眮き換えたす。 prod+en 、 dev+ru混圚させるこずができる構成ruずenもありたす。 珟圚、「共通」コピヌペヌスト prod-ru 、 prod-en 、 dev-ru 、 dev-en の代わりに、4぀の「ドラむ」構成ファむル prod 、 dev 、 ru 、 en しかありたせん。

4 CLI

これは、䜜業の半分を行うロボットぞのむンタヌフェヌスです。 それが非垞に過負荷であるか、 -- ----を-- ----必芁がある堎合、これはMakefileの倖芳に負担をかけ始め、このロボットを起動するのに倚くの時間の無駄を䌎うため、時間を節玄できたす。

頻繁に繰り返されるアクションは、可胜な限り簡玠化する必芁がありたす。 サブコマンドず同じ匕数名であるデフォルト倀を䜿甚する必芁がありたす。 䞀般的に、開発者が最小限のこずを芚えお曞くようにしたす。

比范する
 $ tool make -f path/to/build_name.js -o path/to/build.js 

そしお
 $ tool make build_name 

そしお今、もう䞀床オヌトコンプリヌトなしでコン゜ヌルでこの長いコマンドを曞き出すず、このツヌルを嫌い始めたす。 1番目のオプションはおそらく2番目のオプションよりも明瀺的であるこずは明らかですが、実際にはグラフマニアックツヌルのように芋えたす。

ステヌゞ6browserify




browserifyは、ブラりザでNode.jsモゞュヌルを実行できるツヌルです。

browserify main.js > bundle.jsを参照するだけで機胜したす。

しばらくの間browserifyを䜿甚した埌、Node.js環境をブラりザヌで動䜜するように適応させるずいう真のナヌスケヌスに気付きたした。 browserifyはその目的には最適ですが、Webアプリケヌションが䜜成される珟実には適しおいたせん。 適応されおいないサヌドパヌティのモゞュヌルがある堎合、アプリケヌションの倧郚分の動的なロヌドがある堎合。 すべおが機胜するように、コン゜ヌルでよく考えなければなりたせんでした。

ステヌゞ7LMD




私は本圓にやりたくありたせんでしたが、 LMD-私の人生を楜にするツヌルに取り組み始めなければなりたせんでした。 既存のツヌルを自分の目暙に合わせおカスタマむズできなくなりたした。

その結果、プロゞェクトのスクリプト郚分を組み立おるツヌルが開発されたした。

LMDの基瀎ずなるいく぀かの機胜を次に瀺したす。

1蚭定からのアセンブリ

構成の存圚は避けられないので、それを基にしお構築しおみたせんか lmdの動䜜は、モゞュヌルずプラグむンの䞡方が含たれる構成ず、結果のファむルの゚クスポヌトパスによっお完党に決定されたす。 構成を継承し、他の構成ず混合できたす。

これは蚭定がどのように芋えるかです
 { "name": "My Config", "root": "../js", "output": "../build.lmd.js", "modules": { "main": "index.js" }, "optimize": true, "ie": false, "promise": true } 

100個のモゞュヌルがある堎合-各モゞュヌルをconfigに登録する必芁はありたせん 同じタむプのモゞュヌルに察しお「曞き換えルヌル」を登録するだけで十分です。
 { "modules": { "main": "index.js", "<%= file %>Template": "templates/*.html" } } 

極端な堎合、CJSモゞュヌルの圢匏で構成を蚘述し、すべおをその堎で生成できたす。

2抜象FSファむルシステムぞのバむンドの欠劂

䞀方ではFSぞのバむンドは自然であり、HTTPサヌバヌはファむルシステムを䞀意に反映できたす。 しかし、ブラりザヌにはファむルシステムがなく、HTTPサヌバヌはリ゜ヌスを提䟛し、コヌドはこのURLのこのテキストがモゞュヌルであるこずを既に理解しおいるこずを芚えおおく䟡倀がありたす。 リ゜ヌスは、CDNに任意の名前で移動しお配眮できたす。

抜象ファむルシステムの導入により、モゞュヌルの抜象化が可胜になりたす。 たずえば、locale.ru.jsonずlocale.en.jsonの䞡方が同じむンタヌフェむスを持っおいるずいう事実のために非衚瀺にできるロケヌルモゞュヌルがありたす。あるファむルを別のファむルに透過的に倉曎できたす。

モゞュヌルには奜きな名前を付けお、盞察パスを考えずに接続できたす。 倚くのモゞュヌルがあり、このモゞュヌルの䞋に隠されおいるファむルを忘れた堎合は、 lmd infoを䜿甚するだけです。
 $ lmd info build_name | grep module_name info: module_name ✘ plain ✘ ✘ ✘ info: module_name <- /Users/azproduction/project/lib/module_name.js 

3オヌバヌロヌドされおいないrequireおよびプラグむン

私はrequireがファクトリヌであるこずが奜きではなかったので、その動䜜はわずかに曞き盎されたした。 次に、単にrequire()が抜象ファむルシステムからモゞュヌルをロヌドし、それ以倖は䜕もロヌドしたせん。 require.*()プラグむンを䜿甚しお*独自の凊理を行いたす。 たずえば、 require.js() 、 $.loadScript䌌たJavaScriptファむルrequire.js()ロヌドしたす。

プラグむンは、構成に明瀺的に蚘述する必芁がありたすが、LMDは、「正しいコヌド」を蚘述する堎合にプラグむンを有効にするこずを忘れないでください。

たずえば、このコヌドでは、LMDは3぀のプラグむン、css、parallel、promiseを忘れないようにしたす。
 require.css(['/pewpew.css', '/ololo.css']).then(function () { }); 

しかし、このコヌドでは、jsプラグむンのみ
 var js = require.js; js('http://site.com/file.js').then(function () { }); 

継承ずミックス蚭定を䜿甚しお、プラグむンを有効たたは無効にできたす。

4適応モゞュヌル

プロゞェクトには、モゞュヌルを呌び出すのが難しいファむルがいく぀かありたすが、他のモゞュヌルず同様に䜿甚する必芁がありたす。 LMDは、ビルド時に任意のファむルを簡単に適合させ、そこからCJSモゞュヌルを䜜成できたす。 さらに、テキストファむルテンプレヌトずJSONファむルを䜿甚するために、プラグむンRequireJSのプラグむンテキストを参照たたはアダプタヌを登録する必芁はありたせん。 同じRequireJS LMDずは異なり、これらのファむルは正盎なモゞュヌルに倉換され、shimで適合したせん。

珟圚、LMDには倚数のプラグむンずそれらの䜿甚䟋、およびアセンブリ甚の組み蟌み分析システムがありたす。 そしおもちろん、LMDは私の生掻を楜にしたす。 LMDの詳现に぀いおは、私の蚘事の範囲を超えおいたす。 次回は、LMDのサンプルプロゞェクトに関する蚘事を曞きたす。

未来は




はい、もちろん、これらはES6モゞュヌルです。 それらの圢匏は、他の蚀語のモゞュヌルの倚くの圢匏ず類䌌しおおり、JavaScriptの初心者の期埅に応えたす。 これらには、むンポヌト、゚クスポヌト、モゞュヌルラッパヌ耇数のファむルを連結する必芁がある堎合に必芁なすべおのモゞュヌル属性がありたす。 CJSずAMDで完党に攟送されたす。 ただし、珟圚ドラフトに含たれおいる圢匏では、実際のプロゞェクトで䜿甚するこずは困難です。

むンポヌトは静的です。 モゞュヌルビルダヌを䜿甚しお、アプリケヌションの起動を高速化する必芁がありたす。 倖郚モゞュヌルのむンポヌトはブロックされたす
 <script> import {get, Deferred} from "http://yandex.st/jquery/3.0/jquery.min.js"; get('/').then(console.log.bind(console)); </script> 

ほが同じです
 <script src="http://yandex.st/jquery/3.0/jquery.min.js"> <script> var get = $.get, Deferred = $.Deferred; get('/').then(console.log.bind(console)); </script> 

次に、 <script async/>を䜿甚しおロックを解陀できたす

モゞュヌルは動的にロヌドされたすが、珟圚は完党ではありたせん。
 Loader.load('http://json.org/modules/json2.js', function(JSON) { alert(JSON.stringify([0, {a: true}])); }); 

モゞュヌルロヌダヌがいく぀かのモゞュヌルのアセンブリをロヌドできるこずを願っおいたす。 それで十分でしょう。

暙準は珟圚掻発に議論されおおり、今日お芋せしたこずは明日はそうではないかもしれたせんしかし、そうではないでしょう。 珟圚、むンポヌト/゚クスポヌトのモゞュヌルず構文は、他の蚀語で芋るのに慣れおいるものず䌌おいたす。 倚くの開発者がJavaScriptを䜿甚しおおり、AMDのようなワむルドハックを芋るのが痛いため、これは良いこずです。 今日、ECMAScript開発の方向の1぀は、蚀語を他の蚀語からの翻蚳のための䞀皮のアセンブラヌに倉えるこずを目的ずしおいたす。 そしお、モゞュヌルはこの方向の䞍可欠な郚分です。

結論

今日、JavaScriptには確立されたモゞュラヌシステムがないず蚀えたすが、モゞュラヌ゚ミュレヌタヌしかありたせんが、ES6モゞュヌル構文を䜿甚しおCJSずAMDでモゞュヌルをコンパむルする機䌚がありたす。 JavaScriptには独自の雰囲気があり、倚くの䜿い慣れたむンポヌトの䜿甚を蚱可しない倚くの制限ネットワヌクブレヌキ、トラフィック、遅延がありたす。 アセンブリず非同期ロヌドの問題は、䞀般的なモゞュラヌ゚ミュレヌタヌで䜕らかの圢で解決されたすが、ES6開発者がどのように解決するかは問題です。

マテリ゚ル


あなたが私のモゞュラヌパスを習埗しおいれば、私の小さなモゞュラヌ分類に興味があるず思いたす。

既存のJavaScript「モゞュヌル」ずそのむンフラストラクチャを機胜別に分類したした。 分類では、倚くの機胜が考慮されたす。 モゞュヌルの分類を芋おから、モゞュヌルシステムを分離したす。


䟝存関係の解決

アセンブリツヌルたたは開発者が、このモゞュヌルの通垞の操䜜のために接続/初期化する必芁がある䟝存関係を決定する方法。 䟝存関係は、順番に䟝存関係を持぀こずもできたす。

䟝存関係の解決。 手動制埡

開発者の肩の䟝存関係管理。 開発者は、接続する必芁がある䟝存関係を分析的に理解したす。
 <script src="deps/dep1.js"/> <script src="deps/dep2.js"/> <script src="moduleName.js"/> 

そしおそれに応じおmain.js
 var moduleName = function () { return dep1 + dep2; }; 

䜿甚するサヌドパヌティのラむブラリはありたせん
倚くのモゞュヌルがなく、それらがすべお独自のものである堎合、それは問題ありたせん
倚くのモゞュヌルがある堎合、そのようなコヌドはサポヌトできたせん。
耇数のファむル=耇数のサヌバヌ芁求

「クむックフィル」に適しおいたす。

䟝存関係の解決。 䟝存関係は構成に曞き蟌たれたす

䟝存関係は倖郚構成に登録され、継承できたす。 この蚭定を䜿甚しお、䞀郚のアセンブリツヌルはこのモゞュヌルの䟝存関係をダりンロヌド/接続したす。 構成は、特定のモゞュヌルずプロゞェクト党䜓の䞡方に察しお蚘述できたす。

この構成はLMDで䜿甚されたす
 { "modules": { "main": "moduleName.js" "<%= file %>": "deps/*.js" } } 

そしおそれに応じおmain.js
 var dep1 = require('dep1'), dep2 = require('dep2'); module.exports function () { return dep1 + dep2; }; 

モゞュヌルはファむルシステムに関連付けられおいたせん任意のファむルに任意の名前を付けるこずができたす
モゞュヌルの名前を倉曎せずに、その内容を倉曎できたす
このような蚭定を蚘述する必芁があり、
远加のツヌル/ラむブラリが必芁です。

䟝存関係の解決。䟝存関係はモゞュヌル自䜓に曞き蟌たれたす

䟝存関係、ファむルぞのパス、および実行時にそれらがどのように呌び出されるかは、ファむル自䜓で宣蚀されたす。モゞュヌルは実際に䜜業に必芁なリ゜ヌスを決定し、ロヌダヌはそれらを提䟛したす。䟝存関係ず䟝存関係の䟝存関係が読み蟌たれるたで、モゞュヌルは䜜業を開始したせん。

このメ゜ッドはAMDRequireJSを䜿甚したす
 require(['deps/dep1', 'deps/dep2'], function (dep1, dep2) { return function () { return dep1 + dep2; }; }); 

1぀のモゞュヌルに倚くの䟝存関係がある堎合、この構文は通垞、CommonJS定矩に䜎䞋するか、あらゆる皮類の歪みを䜿甚したす。

倒錯
 require(['deps/dep1', 'deps/dep2', 'deps/dep3', 'deps/dep4', 'deps/dep5', 'deps/dep6', 'deps/dep7'], function ( dep1, dep2, dep3, dep4, dep5, dep6, dep7) { return function () { return dep1 + dep2; }; }); 

CommonJS定矩の劣化
 define(function (require, module, exports) { var dep1 = require('dep1'), dep2 = require('dep2'), dep3 = require('dep3'), dep4 = require('dep4'), dep5 = require('dep5'), dep6 = require('dep6'), dep7 = require('dep7'); return function () { return dep1 + dep2; }; }); 

この䜎䞋を䜿甚する堎合、RequireJSは䟝存関係を定期的に怜玢したす。これは95の信頌できる方法です。正盎な方法ASTたたは巧劙な凊理は、リ゜ヌスコヌドサむズず凊理時間を過床に消費したすが、すべおのニヌズをカバヌするわけでもありたせん。

たずえば、定矩方法がわからない叀いモゞュヌルを適応させるため、たたはある皮の「正盎なモゞュヌル」が動的に初期化される堎合など、同じ方法で構成を蚘述する必芁がある堎合require('templates/' + type)がありたす。動的な初期化はたれであり、䞻にテンプレヌトの動的なロヌドに䜿甚されたすが、可胜です。

ほずんどすべおの䟝存関係のファむルに蚘述
非同期ロヌドしないのconfigs
曞き蟌み蚭定する必芁はありたせんが
ただし、ずにかく蚭定を曞かなければならない堎合がありたす。
远加のツヌル/ラむブラリが必芁です

䟝存関係の解決。䟝存関係はモゞュヌルず構成に登録されたす

䟝存関係は、ファむル自䜓ず特別な構成で登録されたす。

configは、䟝存関係を解決するためにパッケヌゞマネヌゞャヌによっお䜿甚されたす。たずえば、npmおよびpackage.json
 { "dependencies": { "express": "3.x", "colors": "*" } } 

それに応じお main.js
 //   var express = require('express'); //   var dep1 = require('./deps/dep1'), dep2 = require('./deps/dep2'); module.exports function () { return dep1 + dep2; }; 

. . , , . package.json . require('pewpew.js')

,




/ , browserify


, .

䟝存関係ぞのアクセス。任意

すべおのモゞュヌルは、グロヌバルスコヌプたたは名前空間にオヌプンにありたす。各モゞュヌルは、制限なしに、アプリケヌションのあらゆる郚分にどこからでもアクセスできたす。
 var dep1 = 1; var dep2 = 2; alert(dep1 + dep2); 

モゞュヌルは倚くはありたせん、圌らは倧きなされおいない堎合、それは倧䞈倫だ
、モゞュヌルの倚くは、このコヌドが維持できない堎合には
グロヌバル倉数たたは名前空間の名前を探すためにが、目はモゞュヌルの䟝存関係を決定するこずはできたせん

䟝存関係ぞのアクセス。ダむナミック

モゞュヌルぞのアクセスは、「ロヌダヌ」を介しおのみ取埗できたす。require()たたは、モゞュヌルの䟝存関係を宣蚀するこずにより取埗define()

できたす。この機胜はグロヌバルにアクセスするこずもできたす。
 var dep1 = require('./deps/dep1'), dep2 = require('./deps/dep2'); alert(dep1 + dep2); 

したがっお、 define()
 require(['./deps/dep1', './deps/dep2'], function (dep1, dep2) { alert(dep1 + dep2); }); 

簡単に応じお、芋぀ける/理解するための
䟝存関係ぞのアクセスが緩和され、あなたが怠惰など、ランタむムベヌスを蚈算するためのモゞュヌルを初期化するこずができたす
静的に党䜓の䟝存関係グラフのほずんどを定矩するこずが可胜である
コヌドに冗長ビットを、それが保守のために良いの手数料だ
远加のラむブラリ

䟝存関係ぞのアクセス。宣蚀的

モゞュヌルはコヌドを蚘述するずきに宣蚀され、動的にはロヌドされたせん。静的コヌドアナラむザヌは、アプリケヌションの動䜜に必芁なモゞュヌルのセットを明確に理解できたす。ほずんどすべおのむンポヌト構造がこのように機胜したす。
 import * from "dep1"; import * from "dep2"; 

たた、この方法では、䟝存関係ぞのアクセスの属性を割り圓おるこずができ、静的AMDが定矩されたす
 define('module', ['./deps/dep1', './deps/dep2'], function (dep1, dep2) { }); 

静的むンポヌトにより、コレクタヌは䟝存関係を構築でき、ES6モゞュヌルトランスレヌタヌはES3互換でコヌドをリメむクできたす。

静的解析が可胜完党たたは郚分的で
利甚可胜な攟送ES6モゞュヌル
めったに適甚ピュア

モゞュヌルから゚クスポヌト

ほずんどの堎合、モゞュヌルは他のモゞュヌルが䜿甚できるリ゜ヌスを提䟛したす。これには、デヌタ、ナヌティリティ日付、数倀、i18nなどの圢匏を䜿甚できたす。モゞュヌルから゚クスポヌトするず、そのようなリ゜ヌスを提䟛しおいるずいうモゞュヌルの衚瀺方法が決たりたす。

゚クスポヌト。混oticずした茞出

モゞュヌルは、䜕でも、どこでも、い぀でも゚クスポヌトしたす
 var a = 10, b = ''; for (var i = 0; i < a; i++) { b += i; } var dep1 = b; 


地獄ず悪倢のグロヌバルな範囲を詰たらせる、いずれにしおも、これは原則ずしおサポヌトされおいたせん

゚クスポヌト。匷力なマネヌゞド゚クスポヌト

IIFEを远加しお以前のメ゜ッドを少し倉曎するず、このメ゜ッドが埗られたす。モゞュヌルは、どこにあるのか、䜕を呌び出すのかを事前に知っおいたす。
 var dep1 = (function () { var a = 10, b = ''; for (var i = 0; i < a; i++) { b += i; } return b; })(); 

たたはわずかに異なるオプション
 (function () { var a = 10, b = ''; for (var i = 0; i < a; i++) { b += i; } exports.dep1 = b; })(exports); 

たたはAMDずいう名前
 define('dep1', [], function () { var a = 10, b = ''; for (var i = 0; i < a; i++) { b += i; } return b; }); 

その
ようなモゞュヌルをビルドしお䜿甚するのに特別なツヌルは必芁ありたせんAMDを陀く。
必芁なものだけが゚クスポヌトされたす。
モゞュヌルは、゚クスポヌト先ずその名前を知っおいたす。

゚クスポヌト。厳密な名前の「自己゚クスポヌト」

このメ゜ッドは、「モゞュヌルを登録する」ずいう特別な機胜に基づいおready()いたす。モゞュヌルは、準備ができたら呌び出す必芁がありたす。モゞュヌルの名前ずそれが提䟛するリ゜ヌスずいう2぀の匕数を取りたす。
 (function () { var a = 10, b = ''; for (var i = 0; i < a; i++) { b += i; } ready('dep1', b); })(); 

機胜のモゞュヌルの䟝存関係をロヌドするためには䜿甚されおいるload()、ず同様require()
 load('dep1', 'dep2', function (dep1, dep2) { ready('dep3', function () { return dep1 + dep2; }); }); 

 load('dep3', do.stuff); 

モゞュヌルは非同期に゚クスポヌトされ、゚クスポヌトを遅らせるこずができたす。
モゞュヌルはどこにあるかわかりたせん。
モゞュヌル自䜓ぱクスポヌトされたすモゞュヌルはそれを䜿甚するモゞュヌルに埓属したす。
モゞュヌルはその名前を知っおおり、動的に倉曎する
こずができ
たす。

゚クスポヌト。カスタム名前付き゚クスポヌト

モゞュヌルは、その名前もそれがどこにあるかを知りたせん。モゞュヌルのコンシュヌマヌ自身が、コンシュヌマヌのコンテキストで呌び出されるモゞュヌルを決定したす。

これはCommonJSモゞュヌルです
 var a = 10, b = ''; for (var i = 0; i < a; i++) { b += i; } module.exports = b; 

たたは匿名のAMD
 define([], function () { var a = 10, b = ''; for (var i = 0; i < a; i++) { b += i; } return b; }); 

モゞュヌルの゚クスポヌト䞭に任意の名前を䜿甚できたす。
 var dep1 = require('deps/dep1'); 

圌はそれを䜿甚するずきに呌び出されたすどのようにあるか、どこモゞュヌルが知らない
あなたはモゞュヌルの名前を倉曎する堎合にのみ、ファむルの名前を倉曎する必芁があり
、組み立おおよび䜿甚のためのラむブラリの必芁性

゚クスポヌト。正盎なむンポヌト/゚クスポヌト

モゞュヌルを宣蚀するこのメ゜ッドは、2぀おきのプログラミング蚀語を䜿甚したす。ECMAScript 6モゞュヌル仕様はかなり前に登堎したので、遅かれ早かれこのような構文はJavaScriptで提䟛されるでしょう。

モゞュヌルを宣蚀したす。
 module "deps" { var a = 10, b = ''; for (var i = 0; i < a; i++) { b += i; } export var dep1 = b; export var dep2 = b + 1; } 

バむンディングなしでモゞュヌルを宣蚀するこずもできたすmodule {}。

デフォルトの名前を䜿甚しお、より少なく曞くこずができたす
 import * from "deps"; console.log(dep1); 

名前の競合は、䞀皮の「名前空間」を䜿甚しお回避できたす
 import "crypto" as ns; console.log(ns.dep1); 

モゞュヌルの䞀郚を゚クスポヌトできたす
 import {dep1} from "deps"; console.log(dep1); 

䜿い慣れた芖芚的な倚くの蚀語からの銎染みのあるむンポヌト
これはECMAScript 6
です。たずえば、TypeScriptのモゞュヌルを䜿甚するなど、ES6モゞュヌルをES3互換コヌドに倉換する必芁がありたす。

サむドモゞュヌル

今日、モゞュヌルを含め、ほがすべおが進行䞭です。CoffeeScriptずAMDを䜿甚しない堎合でも、いずれにせよプロゞェクトを組み立おたすファむルを連結し、圧瞮したす。

組み立おなし

HTMLのすべお
 <script src="deps/dep1.js"/> <script src="deps/dep2.js"/> <script src="moduleName.js"/> 

それは単にある
ため、リク゚スト数の増加を遅くするために、アプリケヌションが停止し、開始によっおサポヌトされるモゞュヌルの数を増やすこずにより、
HTML゚ンティティず宣蚀モゞュヌルミキシング
新しいビルドを-新しい.htmlを

モゞュヌルの組み立お。ファむルの連結をマスクする

集める
 $ cat **/*.js > build.js 

䜿甚する
 <script src="build.js"/> 

簡単です。
アップロヌドするファむルは1぀だけです。
各タむプのアセンブリに぀いお、新しいスクリプトを䜜成する必芁がありたす。
ファむルは、異なるOSおよびFSで任意の順序でアセンブルできたす。

モゞュヌルの組み立お。前凊理

方法は、ファむル内の特別な「タグ」を怜玢するこずです- include('path/name.js')たたは// include path/name.js同様の
 include('deps/dep1.js'); include('deps/dep2.js'); var moduleName = function () { return dep1 + dep2; }; 

これらはすべお、この圢匏の特別なナヌティリティによっお展開されたす。
 /* start of deps/dep1.js */ var dep1 = 1; /* end of deps/dep1.js */ /* start of deps/dep2.js */ var dep2 = 2; /* end of deps/dep2.js */ var moduleName = function () { return dep1 + dep2; }; 

したがっお、ネストされたモゞュヌルには䟝然䟝存関係があり、再垰的にロヌドされたす。

あるのみ1ファむル
なし「の継承のconfigs」を䜜るこずはできたせん
アセンブリの各タむプのためには、すべおのリストに新しいファむルを䜜成する必芁があるinclude
ならば、プリプロセッサ愚かなこずの可胜なコヌドの重耇や他のアヌティファクト
かのモゞュヌルにコヌドの誀甚の可胜な泚入

の敎合性ぞのモゞュヌルのリヌド線ぞのコヌドの泚入モゞュヌルでは、"use strict"名前の競合やその他の問題が発生したす。

これが兞型的な䟋です
 (function () { "use strict"; var i = 3; include('dep1'); //     return dep1 + i; })(); 

そしお圌の䞭毒
 var i = 4, dep = 01234; 

結果を理解しおいるず思う;-)

モゞュヌルの組み立お。静的䟝存性分析

䟝存関係怜玢によるモゞュヌルコンテンツの静的分析。このメ゜ッドは、r.jsRequireJSモゞュヌルのコレクタヌおよびbrowserifyCommonJSモゞュヌルのアダプタヌおよびブラりザヌのNode.jsむンフラストラクチャを䜿甚したす。ASTパヌサヌを䜿甚しお、define / require呌び出しを探し、䟝存関係を芋぀け、includeずは異なり、これらの䟝存関係をモゞュヌルの倖偎に眮きたす。

たずえば、そのようなモゞュヌル
 require(['dep1', 'dep2'], function (dep1, dep2) { return function () { return dep1 + dep2; }; }); 

r.jsを介しおドラむブする堎合、このフォヌムでここでやり盎されたす。
 define('dep1', [], function () { return 1; }); define('dep2', [], function () { return 2; }); require(['dep1', 'dep2'], function (dep1, dep2) { return function () { return dep1 + dep2; }; }); 

同様にbrowserifyに動䜜したすが、収集し、より耇雑なフォヌマット

のみ1ファむルに行く
すべおの䟝存関係は、モゞュヌルに登録されおいる
アセンブリの皮類ごずに新しいファむルを䜜成したり、シンボリックリンクでマゞックを行うこずが必芁である
プリプロセッサ動的モゞュヌル名によっお構築いく぀かの䟝存関係を芋぀けるこずができない
前の段萜を修正するにはこれらのモゞュヌルを有効にするために蚭定を曞く必芁がありたす

サむドモゞュヌル。構成アセンブリ

ここではすべおが明らかです。構成では、必芁なモゞュヌル。コレクタヌはそれらをアセンブリに含め、䟝存関係を芋぀けたす。その埌、アナラむザヌによっおアセンブリの結果が静的にチェックされたす。アナラむザヌは、䜕かの远加たたは削陀を勧めたす。

このメ゜ッドはLMDを䜿甚したす。
 { "root": "../js", "modules": { "main": "main.js", "dep1": "deps/dep1.js", "dep2": "deps/dep2.js" } } 

もちろん、このオプションは興味深いものですが、なぜモゞュヌルず構成に同じこずを2回曞くのですか

これは簡単に説明できたす。 LMDはファむルシステムを認識せず、実際には構成は抜象ファむルシステムです。これにより、盞察パスを考慮せずに、モゞュヌルの転送/名前倉曎䞭に、プロゞェクト党䜓でパスを実行たたは倉曎しないでください。抜象FSを䜿甚するず、ロヌカリれヌション、環境蚭定の眮換、およびその他の最適化のための安䟡な䟝存性泚入を取埗できたす。たた、モゞュヌルが動的に接続され、静的アナラむザヌがそれらを物理的に芋぀けるこずができないため、構成でモゞュヌルに関する蚘録を䜜成する必芁がありたす。毎回configにモゞュヌルを登録するこずは䞀歩埌退するこずは明らかです。したがっお、LMDでは、glob-ingを䜿甚しおディレクトリ党䜓をサブディレクトリに接続するこずが可胜です。曞き換えルヌルの䞀皮。

この構成は、前の構成ず同じです。
 { "root": "../js", "modules": { "<%= file %>": "**/*.js" } } 

どのファむルが必芁かを刀断し、テンプレヌトを䜜成しお、このLMDモゞュヌルでの衚瀺方法を指定したす。名前を決定するために、LMDはlodashのテンプレヌト゚ンゞンを䜿甚するため、よりトリッキヌな構造を蚘述できたす。
 { "root": "../js", "modules": { "<%= file %><%= dir[0][0].toUpperCase() %><%= dir[0].slice(1, -1) %>": "{controllers,models,views}/*.js" } } 

この方法の結果は以䞋のずおりです。

芖芚-すべおのプロゞェクトツリヌを1぀のファむルに蚘述するこずができたす
安党に-陀倖パヌサ゚ラヌ
抜象ファむルシステムが
蚭定曞き蟌む必芁がある
必芁性コレクタを

モゞュヌルの初期化ず解釈

これは、倧量のコヌドが実行されたずきにアプリケヌションの起動時の遅延を枛らすこずができる重芁なポむントです。コヌドがペヌゞに到達するず、初期化䞭にコヌドが初期化され関数を䜜成し、䜕らかの名前で登録されたす、コヌドが解析され、怜蚌されお、さらなる解釈ず可胜なJITコンパむルのためにASTに枡されたす。関数が呌び出されるず、そのコヌドが解釈されたす。

関数は初期化たたは解釈されたせん。JavaScript文字列のみが初期化されたす。
 'function a() {return Math.PI;}'; 

関数が初期化されたす。
 function a() { return Math.PI; } 

関数は初期化され、解釈されたす。
 function a() { return Math.PI; } a(); 

各関数の宣蚀ずその呌び出しには、特にモバむルでは時間がかかるため、この時間を短瞮するずよいでしょう。

起動時に初期化および解釈されたす

モゞュヌルはそのたた提䟛され、プログラムの開始時に実行されたす。たずえ今圌がいなくおも ご芧のずおり、モゞュヌルには䜜業の速床を䜎䞋させる可胜性のあるサむクルがいく぀かありたす。
 var dep1 = (function () { var a = 10, b = ''; for (var i = 0; i < a; i++) { b += i; } return b; })(); 

远加のツヌルを䜿甚する必芁はありたせん。
コヌドが倧きくない堎合、初期化時間は重芁ではありたせん。
コヌドの量が増えるず、スタヌトアップレむテンシが衚瀺され始めたす。

起動時に初期化され、オンデマンドで解釈されたす

AMDずNode.jsのモゞュヌルの䞡方で䜿甚されおいる非垞に人気のある方法
 define('dep1', [], function () { var a = 10, b = ''; for (var i = 0; i < a; i++) { b += i; } return b; }); 

このモゞュヌルは起動時に初期化されたす。しかし、圌の䜓は芁求に応じお実行され、結果はreturn b;キャッシュされ、次回呌び出されたずきに解釈はパスしたせん。

モゞュヌルの非垞に匷力なビュヌに倉曎する必芁はありたせ
倧量のコヌドが時にスタヌトアップ埅ち時間が倧幅に短瞮されおいない
远加のラむブラリが必芁

リク゚ストに応じお初期化および解釈されたす

コヌドの初期化を遅らせるこずができる、以前のメ゜ッドの小さな倉曎。䞻にモバむルデバむスでのコヌドダりンロヌドの最適化に䜿甚されたす。このような最適化は、RequireJSおよびLMDで実行できたす。

LMDアセンブリピヌス構成ではない
 { 'dep1': '(function(){var a=10,b="";for(var i=0;i<a;i++){b+=i;}return b;})' } 

䞀郚のモゞュヌルにモゞュヌルリ゜ヌスが必芁な堎合dep1、LMDはこのコヌドを解釈しお初期化したす。

このようなもの
 var resources = new Function('return ' + modules['dep1'])()(require, module, exports); 

コヌドの初期化時間は、new Function正盎な初期化よりも少し遅くなる堎合がありたすが、この最適化を賢明に䜿甚すれば、最初から時間を皌ぐこずができたす。new Functionずは異なりeval()、生成されたコヌドはJITコンパむラヌによっお最適化できたす。

この操䜜は開発者に察しお透過的であり、
远加のラむブラリが
必芁です。

倖郚䟝存関係をダりンロヌドする

すでに述べたように、JavaScript @ DOMには独自の雰囲気があるため、モゞュヌルをロヌドする通垞の方法はここでは機胜したせん。モゞュヌルはリモヌトにあり、それらの同期ロヌドは珟実的ではありたせん。デスクトップアプリケヌションで「光の速床で」ラむブラリを同期的にリンクできる堎合、JavaScript @ DOMでは、EventLoopのブロックにより、これはほずんど珟実的ではありたせん。

䞀床にすべおをロヌドするこずはできないので、䜕かを発明しお苊しむ必芁がありたす:)

非管理モゞュヌルロヌダヌ

非実行モゞュヌルずは、远加の凊理を必芁ずしないコヌドを意味したす。たずえば、このようなロヌダヌjQuery.getScript(file)

は次のようなものです。
 var script = document.createElement('script'); script.src = file; script.onload = done; document.head.appendChild(script); 

耇数のモゞュヌルを同時にロヌドする堎合、それらはロヌド順に実行されたす。そのため、モゞュヌルをリストされおいる順序で実行する必芁がありたす。たずえば、LAB.jsラむブラリは、XHRを䜿甚しお同時にスクリプトコヌドを読み蟌み、そのコヌドを順番に実行したす。XHRは、その制限を導入したす。
 $LAB .script("framework.js").wait() .script("plugin.framework.js"); 

YepNopeやscript.jsなどのその他のロヌダヌは、ほが同じこずを実行しおいたす。

安䟡な゜リュヌション
XHRの䞀郚に制限があるか、远加の蚘述がありたす。

マネヌゞドモゞュヌルロヌダヌ

成人のモゞュラヌシステムには独自のロヌダヌが付属しおおり、モゞュヌルずその䟝存関係をロヌドできたす。䟋えば、それが機胜しrequire()ずdefine()RequireJSのを。RequireJS

の関数require()は、必芁な䟝存関係ず䟝存関係の䟝存関係を読み蟌み、指定された順序でこれらのモゞュヌルのコヌドを実行したす。
 require(['dep1', 'dep2'], function (dep1, dep2) { console.log(dep1 + dep2); }); 

たずえば、LMDには、バンドルのようなものがありたす-いく぀かのモゞュヌルが1぀のファむルにたずめられおいたす。このバンドルをロヌドするず、すべおのモゞュヌルがすべおのモゞュヌルで利甚可胜になりたす。
 _e4fg43a({ 'dep1': function () { return 1; }, 'dep2': 2, 'string': 'Hello, <%= name %>!' }); 

 require.bundle('name').then(function () { // do stuff }); 

モゞュヌルのロヌドず初期化の䞡方の管理;
開発者にずっおほずんど透過的なダりンロヌド;
远加のツヌルず蚭定が必芁

モゞュヌルの分離

モゞュヌルのセキュリティたたは分離は、䜜業を䞭断する開発者ではなく開発者に必芁です。モゞュヌルのプロパティぞの盎接か぀無秩序なアクセスは、䞍適切に䜿甚されるず「コヌドを台無しにする」可胜性がありたす。䞀方、グロヌバルスコヌプにJavaScriptの痕跡がない堎合、コヌドの研究者が䜕かを理解しお「ブレむク」するこずはより困難になりたすが、ここでは時間の問題です。

モゞュヌルは分離されおいたせん

モゞュヌルたたはその䞀郚はグロヌバルにアクセス可胜で、開発者はどこからでも利甚できたす。
 var dep1 = (function () { var a = 10, b = ''; for (var i = 0; i < a; i++) { b += i; } return b; })(); 

繰り返したすが、これは簡単です。
ツヌルは䞍芁です。
名前空間に぀いお考える必芁
がありたす。モゞュヌルの分業はありたせん。圌は仕事をし、䟝存関係の受け取りを管理したす。

分離されたモゞュヌル

モゞュヌルはグロヌバルにアクセスできたせんが、名前-を知るこずで取埗できたすrequire('pewpew')。私が蚀ったように、非衚瀺はモゞュヌル匏システムの目暙ではなく、結果です。AMDは、あなたが䜕らかの圢でモゞュヌルぞのアクセスを埗るこずが可胜な2぀の機胜がある-これをrequire()しおdefine()。リ゜ヌスを取埗するには、モゞュヌルのコヌド名を知るだけで十分です。
 define('dep3', ['dep1', 'dep2'], function (dep1, dep2) { return function () { return dep1 + dep2; }; }); 

モゞュヌルは他のモゞュヌルから分離されおいるため、誀っお䜕かを損なうこずはありたせん。
別のモゞュヌルぞのアクセスは明瀺的に宣蚀されおい
たす。

モゞュヌルは完党に分離されおいたす

このようなモゞュヌルの目的は、倖郚からモゞュヌルに到達できないようにするこずです。私は倚くの人がすでにそのような「モゞュヌル」を芋たこずがあるず思う、䟋えば
 $(function () { var dep1 = (function () { var a = 10, b = ''; for (var i = 0; i < a; i++) { b += i; } return b; })(); $('button').click(function () { console.log(dep1); }); }); 

実際、これは完党に隔離されたモゞュヌルであり、倖郚から内郚に到達するこずは䞍可胜です。しかし、これは1぀のモゞュヌルの䟋です。そのような各モゞュヌルが「クロヌゞャ」にラップされおいる堎合、それらは盞互䜜甚できたせん。耇数のモゞュヌルを分離するには、それらを共通のスコヌプに配眮するか、スコヌプ内のいく぀かの共通リ゜ヌスをスロヌしたす。これらのリ゜ヌスを䜿甚するず、このようなモゞュヌルは互いに通信できたす。

IEFEでそのようなモゞュヌルをラップするだけで十分です。
 (function () { /* start of deps/dep1.js */ var dep1 = 1; /* start of deps/dep2.js */ var dep2 = 2; var moduleName = function () { return dep1 + dep2; }; })(); 

このビルド方法では、たずえばjQueryを䜿甚したす。

LMDずbrowserifyもモゞュヌルを環境から完党に分離したすが、オヌルむンワンアセンブリずは異なり、それらのモゞュヌルは互いに、たたアセンブリの「制埡郚分」から分離されおいたす。

圌らはこのように回っおいたす
 (function (main, modules) { function lmd_require() {} // ... main(lmd_require); }) (function (require) { var dep1 = require('dep1'); // ... }, { dep1: function (r,m,e) {} }); 

単玔なケヌスでは、完党な絶瞁を簡単に達成できたす。
他のケヌスでは、远加のツヌルが必芁です

人気のあるJavaScriptモゞュヌル゚ミュレヌタヌの比范衚


AMD、YUIES6CJS / LMDIEFE
䟝存関係の解決モゞュヌル+ configモゞュヌル内構成でマニュアル
䟝存関係アクセスダむナミック宣蚀的ダむナミック任意
茞出する任意の名前で正盎なむンポヌト/゚クスポヌト任意の名前で混oticずした/制埡䞍胜
サむドモゞュヌル静的解析䞍芁/連結構成アセンブリ連結
モゞュヌルの解釈リク゚ストに応じおネむティブ゜リュヌションリク゚ストに応じお開始時
モゞュヌルの分離孀立した孀立した完党に分離孀立しおいない

䞀般的なモゞュヌル圢匏


そしお最埌に、今日存圚するJavaScriptモゞュレヌタヌに関する背景情報をいく぀か玹介したす。

モゞュヌルなし

 var moduleName = function () { return dep1 + dep2; }; 

名前空間

 var MyNs.moduleName = function () { return MyNs.dep1 + MyNs.dep2; }; 

IIFEリタヌン

 var moduleName = (function (dep1, dep2) { return function () { return dep1 + dep2; }; }(dep1, dep2)); 

IIFEの茞出

 (function (exports, dep1, dep2) { exports.moduleName = function () { return dep1 + dep2; }; }(window, dep1, dep2)); 

AMD

YUIモゞュヌルは、AMDず意味的に類䌌しおいたす。私はそれらを実蚌したせん。
 define(["dep1", "dep2"], function (dep1, dep2) { return function () { return dep1 + dep2; }; }); 

CommonJSのAMDラッパヌ

 define(function (require, module, exports) { var dep1 = require('dep1'), dep2 = require('dep2'); module.exports = function () { return dep1 + dep2; }; }); 

Commonjs

 var dep1 = require('dep1'), dep2 = require('dep2'); module.exports = function () { return dep1 + dep2; }; 

UMD

珟圚、サポヌトが必芁なモゞュヌルには少なくずも3぀の圢匏があるこずがわかりたす。プロゞェクトを曞いお、䜕でも曞くこずができるなら、それは䞀぀のこずです。すべおの圢匏をサポヌトするこずが望たしいオヌプン゜ヌスプロゞェクトは別の問題です。これらのモゞュヌルはすべお、本質的に同じこずを行う単なるラッパヌです-リ゜ヌスを取埗し、リ゜ヌスを提䟛したす。少し前たで、UMDUniversal Module Definitionプロゞェクトが登堎したした。これは、すべおの圢匏のナニバヌサルラッパヌを「暙準化」したした。
 (function (root, factory) { if (typeof exports === 'object') { //  1: CommonJS factory(exports, require('dep1'), require('dep2')); } else if (typeof define === 'function' && define.amd) { //  2: AMD ( ) define(['exports', 'dep1', 'dep2'], factory); } else { //  3:    factory(window, root.dep1, root.dep2); } })(this, function (exports, dep1, dep2) { //  exports.moduleName = function () { return dep1 + dep2; }; }); 

開発でこれを䜿甚するのは䞀皮の奇劙なこずですが、゚クスポヌトでは最も倚く䜿甚されたす。

読む


  1. JavaScriptモゞュヌルパタヌン詳现
  2. YUIモゞュヌルの䜜成
  3. AMD、CommonJS、ES Harmonyを䜿甚したモゞュラヌJavaScriptの蚘述
  4. Why AMD?
  5. AMD is Not the Answer
  6. Why not AMD?
  7. Proposal ES6 Modules
  8. Playing with ECMAScript.Harmony Modules using Traceur
  9. Author In ES6, Transpile To ES5 As A Build-step: A Workflow For Grunt

, , .

Source: https://habr.com/ru/post/J181536/


All Articles