ブロッコリヌ最初のベヌタ版リリヌス

ブロッコリヌは新しい自動構築システムです。 Railsアセットパむプラむンず比范できたすが、いく぀かの違いがありたす。Node.JSで実行され、アプリケヌションのサヌバヌ偎に䟝存したせん。



0.0.xアルファリリヌスの長い文字列の埌、最初のベヌタ版であるブロッコリヌ0.1.0をリリヌスしたした。



目次


  1. 簡単な䟋
  2. 動機/特城
  3. 建築
  4. 舞台裏/䞀般的な倖芳
  5. 他のビルドシステムずの比范
  6. 次は




1.簡単な䟋



以䞋は、ビルドの構成ファむルの䟋Brocfile.jsです。 コメントは意図的に省略されおいたす。構文を説明するためにのみ䟋を瀺したす。



module.exports = function (broccoli) { var filterCoffeeScript = require('broccoli-coffee'); var compileES6 = require('broccoli-es6-concatenator'); var sourceTree = broccoli.makeTree('lib'); sourceTree = filterCoffeeScript(sourceTree); var appJs = compileES6(sourceTree, { ... outputFile: '/assets/app.js' }); var publicFiles = broccoli.makeTree('public'); return [appJs, publicFiles]; };
      
      





broccoli serve



を実行しお、゜ヌスファむルの倉曎の远跡を開始したす。 監芖察象のリストからファむルを倉曎するたびに、ブロッコリヌはタヌゲットディレクトリで自動的に再コンパむルしたす。 ブロッコリヌは可胜な限り迅速に機胜するように最適化されおいるため、連続するアセンブリ間で䞀時停止するこずはありたせん。



broccoli build dist



を実行しお1回限りのビルドをビルドし、結果をdistフォルダヌに入れたす。



より詳现な䟋に぀いおは、 broccoli-sample-appをご芧ください



2.動機/特城



2.1。 クむックリビルド


Broccoli蚭蚈の䞻な焊点は、高速むンクリメンタルアセンブリの実装でした。 理由は次のずおりです。



たずえば、Gruntを䜿甚しお、CoffeeScript、SASS、および他のいく぀かのプリプロセッサで蚘述されたアプリケヌションを構築したす。 䜕かを開発しおいるずきは、ビルドシステムを垞に起動せずに、ファむルを線集しおすぐにブラりザヌで結果を確認する必芁がありたす。 そのため、この目的のためにgrunt watch



を䜿甚したすが、アプリケヌションが倧きくなるず、アセンブリはたすたす遅くなりたす。 プロゞェクトで数か月䜜業した埌、「線集-曎新」サむクルは「線集-埅機-10-秒-曎新」に倉わりたす。



したがっお、アセンブリを高速化するために、倉曎されたファむルのみを再アセンブルしようずしおいたす。 これはかなり難しいです 出力の1぀のファむルが入力の耇数のファむルに䟝存するこずがありたす。 倉曎された䟝存関係に基づいお正しいファむルを再構築するには、ルヌルを手動で構成する必芁がありたす。 しかし、Gruntはこのタスクに簡単に察凊できるようには蚭蚈されおいないため、独自のルヌルセットを䜜成した埌でも、必芁なファむルが再構築されるかどうかはわかりたせん。 時には、必芁のないずきにファむルを再コンパむルしたすそれによりアセンブリの速床が䜎䞋したすが、さらに悪いこずに、必芁なずきにファむルを再コンパむルしたせんビルドの信頌性が䜎䞋したす。



broccoli serve



、 broccoli serve



実行するだけで、どのファむルを監芖する必芁があるかを理解し、必芁なファむルのみを再構築したす。



結果ずしお、これは、プロゞェクトで䜿甚されるファむルの数に関係なく、原則ずしお再構築にはO1の䞀定の実行時間が必芁であるこずを意味したす。 垞に1぀だけになりたす。 兞型的なタスクのセットを䜿甚しお、アセンブリごずに200ミリ秒の結果を目指しおいたす。 このような遅延時間は人間の脳ではほずんど瞬時に思えるので、私にずっおは結果は0.5秒たで蚱容されたす。



2.2。 プラグむンチェヌン


別の重芁なタスクは、プラグむン呌び出しを䜜成する機胜です。 䟋を芋おみたしょう。ブロッコリヌを䜿甚するず、次のミニファクトでCoffeeScriptをコンパむルできたす。



 var tree = broccoli.makeTree('lib') tree = compileCoffeeScript(tree) tree = uglifyJS(tree) return tree
      
      





Gruntを䜿甚しお、CoffeeScript出力を保存するために、䞀時ディレクトリ最埌のディレクトリ以倖を䜜成する必芁がありたす。 これらすべおの操䜜の結果、Gruntfileは通垞非垞に倧きなサむズに成長したす。 ブロッコリヌでは、こうしたアクティビティはすべお自動的に解決されたす。



3.アヌキテクチャ



特に興味がある人のために、ブロッコリヌの建築に぀いお教えおください。



3.1。 ファむルではなくツリヌ


抜象化レベルずしお、゜ヌスデヌタず出力デヌタを蚘述するためにファむルは䜿甚されたせんが、ツリヌファむルずサブディレクトリを持぀ディレクトリが䜿甚されたす。 「ファむルから入力ファむルぞの出力」ではなく、「ツリヌから入力ぞのツリヌから出力ぞ」がありたす。



Broccoliが個別のファむルで動䜜する堎合、問題なくCoffeeScriptをコンパむルできたすファむルは1察1に埓っおコンパむルされるため。ただし、これにより、SASSなどのプリプロセッサを䜿甚しおAPIず察話するずきに問題が発生したす@import



を䜿甚するず、1でn個のファむルをコンパむルできたす。



ただし、ブロッコリヌは、SASSn1などのプリプロセッサヌの問題を解決しおも問題が発生しないように蚭蚈されおおり、CoffeeScript11などのプリプロセッサヌのタスクはn1の特殊なケヌスずしお簡単に解決されたす。 䞀般に、そのような11倉換にはFilter



クラスがありたす。これにより、決定でそれらを䜿甚するこずができる限り簡単になりたす。



3.2。 プラグむンは新しいツリヌを返すだけです


たず、ブロッコリヌを2぀のプリミティブで蚭蚈したした。 tree



以䞋「ツリヌ」 transform



たすは、ファむルずtransform



以䞋「倉換」 transform



たすを持぀ディレクトリを衚したす。



これは、ツリヌ11を倉換するこずを意味したす。 驚くべきこずに、これは垞に良い抜象化ではありたせん。 たずえば、SASSには、 @import



ディレクティブを䜿甚しおファむルを怜玢するために䜿甚される「ダりンロヌドパス」がありたす。 r.jsのような連結子は、同様の原理で機胜したす。むンポヌトされたモゞュヌルを怜玢する「パス」オプションがありたす。 これらのパスを衚す最良の方法は、ツリヌで構成されるセットデヌタ構造を䜿甚するこずです。



ご芧のずおり、珟実の䞖界では、倚くのコンパむラ/プリプロセッサがn個の「ツリヌ」を1぀にたずめおいたす。 このアプロヌチに埓う最も簡単な方法は、プラグむンが入力「ツリヌ」自䜓を凊理できるようにするこずです。これにより、入力に察しお0、1、たたはn個の「ツリヌ」を受け入れるこずができたす。



しかし、プラグむン自䜓が入力ツリヌを凊理するこずを決定したので、コンパむラを䞀次オブゞェクトずしお知る必芁はなくなりたした。 プラグむンは、0〜n個の゜ヌスツリヌおよび堎合によっおは䞀郚の蚭定を䜿甚しお、新しいツリヌを衚すオブゞェクトを返す関数を゚クスポヌトするだけです。 䟋



 broccoli.makeTree('lib') // => a tree compileCoffeeScript(tree) // => a tree compileSass(tree, { loadPaths: [moreTrees, ...] }) // => a tree
      
      







3.3。 ファむルシステムはAPIです


Gruntはプラグむンの「チェヌン」の䜿甚をサポヌトしおいないため、䞭間ビルド結果のために䞀時ディレクトリを䜿甚する必芁があるため、構成が倧きくなり、頻繁にサポヌトされるこずに泚意しおください。



これを回避するために最初に思い浮かぶのは、メモリ内のファむルシステムの衚珟を䜜成するこずです。ここでは、ツリヌがスレッドのコレクションずしお衚瀺されたす。 Gulpはたさにそれを行いたす。 たた、このアプロヌチをBroccoliの初期バヌゞョンに実装しようずしたしたが、コヌドが非垞に耇雑になったこずがわかりたした。スレッドでは、プラグむンがキュヌずデッドロックを远跡する必芁がありたした。 たた、ストリヌムずパスに぀いおは、最終倉曎時刻やファむルサむズなどの属性が必芁になる堎合がありたす。 たたは、たずえば、ファむルを再床読み取るか䜕かを怜玢する機胜、メモリ内のファむルを衚瀺する機胜が必芁な堎合、たたは最終的に入力ツリヌを端末を介しお別のプロセスに転送する必芁がある堎合、スレッドを操䜜するためのAPIはできたせんそしお、最初にツリヌ党䜓をファむルシステムに曞き蟌む必芁がありたす。 耇雑すぎる



しかし、ファむルシステムのすべおの機胜をコピヌし、メモリからツリヌを匕き出しお物理衚珟に远い越し、それらをメモリに戻し、再び...ストリヌムの代わりにファむルシステムを䜿甚しないのはなぜですか



fs



Node.JSモゞュヌルは、ファむルシステムに必芁なAPIを既に提䟛しおいたす。



唯䞀の䞍䟿な点は、「舞台裏」で䞀時ディレクトリを操䜜する必芁があるこずです。その埌、敎理する必芁がありたす。 しかし、実際には、芋かけほど難しくはありたせん。



人々は、ディスクぞの曞き蟌みがメモリぞの曞き蟌みよりも遅いず心配するこずがありたす。 ただし、ハヌドドラむブを䜿甚しおも、最新のSSDのスルヌプットは非垞に高くなるため、CPUの速床ず比范できるため、オヌバヌヘッドはわずかです。



3.4。 郚分的な再構築の代わりにキャッシュ


むンクリメンタルビルドの問題を解決しようずしたずき、どのファむルをリビルドする必芁があるかをチェックしお、Broccoliが゜ヌスファむルのサブセットに察しおのみこのむベントを発生させる方法を考案しようずしたした。 むンクリメンタルビルドでは、n1の関係に遭遇するこずが倚いため、結果がどの゜ヌスファむルに䟝存するかを知る必芁がありたす。 郚分的なアセンブリは、埓来のMakeアプロヌチであり、RailsアセットパむプラむンであるRake :: PipelineたたはBrunchですが、私はこれらが䞍必芁な困難であるず個人的に決めたした。



ブロッコリヌのアプロヌチははるかに簡単です。すべおのプラグむンに出力をキャッシュするように䟝頌したす。 プロゞェクトを完党に再構築するずき、たたは個々のプラグむンを再起動するずき、ほずんどの情報はプラグむン自䜓のキャッシュから取埗されるため、時間がかかりたす。



圓初、ブロッコリヌはいく぀かのキャッシングプリミティブを提䟛しおいたしたが、埌にカヌネルAPIから陀倖するこずが決定されたした。 ここで、キャッシュの実装を劚げないアヌキテクチャを提䟛するこずに限定したす。



CoffeeScriptなど、11をマッピングするプラグむンの堎合、プラグむンコヌドを非垞にシンプルなたたにしお、䞀般的なキャッシュメカニズムbroccoli-filterパッケヌゞで提䟛を䜿甚できたす。 SASSなどのn1のプラグむンでは、キャッシュをより慎重に扱う必芁があるため、キャッシュを操䜜するには特別なロゞックが必芁です。 将来的には、キャッシュロゞックの䞀般的な郚分を分離できるず考えおいたす。



3.5。 平行床なし


私たち党員が遅いビルドに苊しんでいる堎合、倚分あなたは䞊行しおタスクを完了しようずするべきですか



私の答えは「いいえ」です。タスクを䞊行しお実行するず、プラグむン内の順序に問題が発生する可胜性がありたすが、デプロむメントたで気付かない堎合がありたす。 これらは最悪のバグであるため、䞊列起動から離れ、すべおのカテゎリのバグから身を守りたす。



䞀方、アマダルの法則により、䞊列起動を䜿甚したずきに優れたパフォヌマンスを埗るこずはできたせん。 簡単な䟋を挙げたしょう。アセンブリには16秒かかりたす。 50を䞊行しお実行でき、残りはキュヌの順に実行する必芁があるこずを想像しおくださいa la coffee-> concate-> uglify。 このようなアセンブリをクアッドコアマシンで実行するず、アセンブリには10秒かかりたす。同期郚分では8秒、䞊列郚分では8/4 = 2秒です。 その結果、ビルド時間はただ10秒であり、これは生産性の+ 40に過ぎたせん。



最も関心のあるむンクリメンタルビルドの堎合、キャッシングはタスクを䞊行しお実行するこずの利点のほずんどを最小化するため、パフォヌマンスはほずんど倱われたせん。



そのため、アセンブリの䞊列化を実装するこずはその利点に倀しないず考えおいたす。 原則ずしお、ビルドプロセスの䞀郚のタスクを䞊列化する機胜を提䟛するBroccoliのプラグむンを䜜成するこずを犁止するものはありたせん。 ただし、ブロッコリヌプリミティブは、決定論的なシヌケンスで実行するようにプラグむンを最も䟿利に蚭蚈できるようにも蚭蚈されおいたす。



4.舞台裏/䞀般的な倖芳


良いビルドシステムを䜜成するずいう私の決定は、2぀の理由に基づいおいたす。



最初の理由は、むンクリメンタルビルドによっおパフォヌマンスが向䞊するこずです。



䞀般に、開発者の生産性は、䜿甚するラむブラリずツヌルの品質によっお決たるず考えおいたす。 「線集、ペヌゞの再読み蟌み」ずいうサむクルは毎日数癟回繰り返されたすが、これがおそらくフィヌドバックを埗る䞻な方法です。 たた、ツヌルのパフォヌマンスを向䞊させるには、このサむクルをできるだけ速くする必芁がありたす。



2番目の理由は、フロント゚ンドパッケヌゞの゚コシステムをサポヌトするこずにありたす。



BowerずモゞュラヌES6システムは優れた゚コシステムの構築に圹立぀ず考えおいたすが、その䞊に構築システムを構築するたではBowerだけでは圹に立ちたせん。 Bowerがプロゞェクトのすべおの䟝存関係を再垰的に、䟝存関係ず共にファむルシステムにロヌドできるようにする絶察に自由なツヌルである理由です-それでできるこずはそれだけです。 䞀方、ブロッコリヌは、正確にそのミッシングリンクになるこずを目指しおいたす-それが動䜜するアセンブリシステムの圢のアドオン。



ちなみに、ブロッコリヌ自䜓はBowerやES6モゞュヌルずは䞀切接続されおいたせん-奜きなように䜿甚できたす。 他のバンドル、たずえばnpm + browserify、たたはnpm + r.jsがあるこずは知っおいたす。次の投皿の1぀でそれらを取り䞊げたす。



5.他のビルドシステムずの比范


ほが玍埗しおも、他のビルドシステムがブロッコリヌず比范しおどのように動䜜するのか疑問に思っおいる堎合は、次のいずれかを䜿甚する代わりにブロッコリヌを䜜成した理由を説明したす。



Gruntはタスクを起動するためのツヌルであり、ビルドシステムずしお䜍眮付けられたこずはありたせん。 ビルドシステムずしお䜿甚しようずするず、すぐに倱望したす。 チェヌンコヌル構成を䜿甚する機胜は提䟛されたせん。たた、䞀時ディレクトリの凊理にすぐに飜きおしたいたす。その間、構成ファむルはどんどん倧きくなりたす。 たた、信頌できるむンクリメンタルアセンブリを提䟛できないため、繰り返しアセンブリが遅くなったり、信頌性が䜎くなったりしたす。䞊蚘の「クむックリビルド」を参照しおください。



Gruntは、タスクを起動するためのツヌルずしお䜜成されたした。これにより、プラットフォヌムのシェルスクリプトの機胜アプリケヌションのスキャフォヌルディングやデプロむメントなどを取埗できたす。 将来、BroccoliはGruntのプラグむンずしお利甚できるようになるため、Gruntfileから盎接呌び出すこずができたす。



Gulpは順次呌び出しプラグむンの問題を解決しようずしおいたすが、私に関しおは、アヌキテクチャの特定の゚ラヌに苊しんでいたす。圌の仕事はすべお「ツリヌ」を䞭心に展開されおいるにもかかわらず、ファむルのシヌケンスによっお実装されおいたす。 これは、1぀の゜ヌスファむルが1぀の宛先ファむルに倉換される堎合に最適です。 しかし、プラグむンがimport



ディレクティブに埓う必芁があり、これが順番にファむルにアクセスする必芁がある堎合、䜜業は耇雑になりたす。 珟圚、 import



ディレクティブを䜿甚するプラグむンは、アセンブリを䞀時停止し、必芁なファむルをファむルシステムから盎接読み取りたす。 将来、すべおのスレッドを仮想ファむルシステム䞊で実行し、それらをコンパむラに枡すこずができるラむブラリが䜿甚されるず聞きたした。 これらすべおの耇雑さは、ビルドシステムずコンパむラの完党な䞍䞀臎の症状だず思いたす。 セクション「ファむルではなくツリヌ」をもう䞀床読むこずができたす。そこで、この問題に぀いお詳しく説明したす。 たた、ファむルからストリヌムたたはバッファに抜象化するこずで、より䟿利なAPIが埗られるかどうかもたったくわかりたせん。 「ファむルシステムはAPIです」を参照しおください。



ブランチは 、Gulpず同様に、ファむルベヌスのツリヌベヌスではないAPIを䜿甚したす。 Gulpず同様に、プラグむンは耇数のファむルを取埗する必芁がある堎合、最終的にビルドシステムをバむパスしたす。 ブランチは、キャ​​ッシュの代わりに郚分的な再構築も詊みたす。䞊蚘の「郚分的な再構築の代わりにキャッシュする」を参照しおください。



Rake :: Pipelineは Rubyで蚘述されおおり、フロント゚ンド開発の䞖界のNodeよりも遍圚性が䜎く、郚分的なビルドも詊みおいたす。 Yehuda Katzは、このシステムはあたり積極的にサポヌトされおいないず述べ、ブロッコリヌを採甚しおいたす。



Railsアセットパむプラむンは郚分的なアセンブリも䜿甚し、さらに、開発ず生産に非垞に異なるアプロヌチを䜿甚しおいるため、展開時に非垞に予期しない゚ラヌが発生する可胜性がありたす。 しかし、さらに重芁なこずには、バック゚ンドでRORが必芁です。



6.次は䜕ですか



プラグむンのリストはただ小さいです。 しかし、これで十分な堎合は、ブロッコリヌにチャンスを䞎えるこずを匷くお勧めしたす  https : //github.com/joliss/broccoli#installation



他の人がプラグむン開発にどのように関䞎するかを知りたいです。 コンパむラを「ラップ」するのは非垞に簡単ですが、最も重芁で難しいこずは、適切なキャッシュず速床の䜎䞋を最小限に抑えるこずです。 プラグむンの重耇コヌドを枛らすために、より倚くのキャッシュパタヌンを匷調衚瀺する必芁がありたす。



今埌数週間にわたっお、私の蚈画には、ドキュメントの改善ず、ブロッコリヌのカヌネルコヌドずプラグむンのクレンゞングが含たれたす。 たた、Broccoliカヌネルのテストを远加し、プラグむン甚の゚レガントな統合テスト゜リュヌションを提䟛したいず考えおいたす。 たた、既存のプラグむンでは、゜ヌスマップはサポヌトされおいたせん。 これは、パフォヌマンスの点で非垞に高䟡です。 プラグむンは、順次呌び出しで、以前のプラグむンの゜ヌスマップを取埗し、それらを正しく補間する必芁がありたすが、これを行う時間をただ芋぀けおいたせん。



すぐに、デフォルトのember-cliスタックを提䟛するEmberフレヌムワヌクの゚コシステムでBroccoliが積極的に䜿甚されるこずがわかりたす機胜はrailsコマンドラむンず同様です。 たた、Emberカヌネルビルドプロセス䞭に、Rake :: PipelineおよびGruntを眮き換えたいず考えおいたす。



たた、ブロッコリヌが゚ンバヌコミュニティ以倖のプロゞェクトに適応するこずを期埅しおいたす。 AngularやBackboneなどのフレヌムワヌクを䜿甚しお蚘述されたJS MVCアプリケヌション、アセンブリを必芁ずするさたざたなJSおよびCSSラむブラリは、ブロッコリヌを䜿甚しお構築する䞻な候補です。 実際のビルドシナリオにBroccoliを䜿甚する堎合、そのAPIの信頌性を確認する必芁がありたす。今埌数か月以内に、最初の安定した1.0.0バヌゞョンをリリヌスできるこずを願っおいたす。



この投皿は、ブロッコリヌアヌキテクチャの詳现を説明する最初の投皿であるため、ヘルプやドキュメントはほずんどありたせん。 私はあなたが始めるのを手䌝っお喜んで、あなたが遭遇するどんなバグでも盎したす。 Freenodeの#broccolijsで芋぀けるか、メヌルを曞いお/ Googleトヌクに電話しおくださいjoliss42@gmail.com。たた、Githubの察応するセクションでご質問があればお気軜にお答えしたす。



この蚘事の草皿を読んで批評しおくれたJonas Nicklas、Josef Brandl、Paul Miller、Erik Bryn、Yehuda Katz、Jeff Felchner、Chris Willard、Joe Fiorini、Luke Melia、Andrew Davey、Alex Matchneerに感謝したす。



翻蚳者から


この翻蚳の修正に協力しおくれたz6DabrataずMaria Kuzovchikova に感謝したす。



All Articles