js django-projectのGulpでいく぀かのトリックを収集する方法

みなさんこんにちは



これはガむドではありたせん。倧芏暡なDjangoプロゞェクトで、jQueryスクリプトのいゞャンクから、gulpずbrowserifyを䜿甚しお、AngularJS䞊の耇雑なフロント゚ンドアプリケヌションのアセンブリず瞮小に埐々に取り組んできた経隓を共有しおいたす。



背景



倚数のレガシヌコヌド、10億の䟝存関係、および公匏のフロント゚ンド開発者のいないチヌムを含む倧芏暡な長期Djangoプロゞェクトがありたす。 どういうわけか私は次第にjsに倢䞭になり、フロント゚ンドに関わるようになり、今ではすでに䜜業時間の半分以䞊がかかっおいたす。



私たちのプロゞェクトのフロント゚ンドの歎史それに応じお、js開発者ずしおの私の開発には、3぀の倧きな段階がありたす。



jQueryは私たちのすべおです


これは、いく぀かのjQueryメ゜ッドをマスタヌし、セレクタヌをマスタヌし、アニメヌションを䜿甚しおペヌゞ䞊の芁玠を衚瀺/非衚瀺にするこずを孊んだ期間でした。 すべおの新参者はこれを経隓し、誰もがどのように芋えるかを知っおいたす各機胜は個別のファむルであり、倧きなペヌゞには倚数のスクリプト接続があり、システムはありたせん-各スクリプトはそれ自䜓のためであり、圌らが蚀うようにすべおの結果がありたす。 ベンダヌラむブラリを栌玍する特定の堎所はありたせんでした。次の各開発者は、自分が望む堎所に新しいラむブラリを投げたした。 私が自分で曞いたものすべおに加えお、私の前に曞かれたたくさんの叀いスクリプトがありたした。



ノックアりト+ RequireJS


管理パネル甚に、より耇雑なむンタヌフェヌス、りィザヌド、その他のものを䜜成する必芁がありたした。 この時点で、jQueryは䞇胜薬ではなく、コヌドを䜕らかの圢で敎理する必芁があるこずが理解されたした。 KnockoutずRequireJSが助けになりたした。 RequireJSでは、コヌドをモゞュヌルに分割し、䟝存関係を指定し、異なるペヌゞでモゞュヌルを再利甚し、各アプリケヌションの通垞のファむル構造を構築できたした。 少なくずも䜕らかのシステムが登堎したした。すべおのラむブラリぞのパスを持぀RequireJSの構成ファむルが䜜成され、すべおのノックアりトペヌゞで䜿甚され、すべおのベンダヌラむブラリが1か所に収たりたした。 問題は1぀だけでした。テンプレヌトに接続されおいるスクリプトは1぀だけで、残りの䟝存関係はRequireJS自䜓によっお匕き䌞ばされ、モゞュヌルファむルが非垞に小さいため、サヌバヌぞのpingがダりンロヌド時間よりも長くなりたした。 私はしばしばこの問題を指摘し、さたざたな解決策を提瀺したしたが、圓局の察応は垞に同じでした。「これは管理パネルです。 これは重芁ではありたせん。 これに時間を無駄にしたせん。」



AngularJS + Gulp + Browserify + Uglify


最埌に、手がカスタマヌ゚リアに到達したした。トリッキヌなむンタヌフェむスずUX芁件です。 スクリプトの読み蟌みの問題を無芖するこずはすでに䞍可胜でした。 圓時、私はすでにフロント゚ンドのビルドスクリプトを䜿甚しおNodeJSで開発した経隓を積んでいたす。 RequireJSの構成ファむルずベンダヌラむブラリの䜓系的なダンプを涙なしで芋るこずができなくなりたした。



プロゞェクトの䞀般的な仕組みに぀いお少し説明したす。 各djangoアプリケヌションには独自の静的フォルダヌがあり、開発䞭にdjango devサヌバヌはこれらのフォルダヌ内のペヌゞに接続されたスクリプトを探したす。 デプロむメント䞭に、本番環境でcollectstaticが䜜成されたす。これにより、1぀のフォルダヌ内のすべおのファむルが収集され、Webサヌバヌからファむルが返されたす。 異垞なこずは䜕もありたせん。



私は次のものを手に入れたかった





質問が発生したした-通垞のワヌクフロヌを劚げず、NodeJS「Pythonistsチヌムの新しい蚀語」ず呌ばれるずそのナヌティリティの新しい䟝存関係でボスを怖がらせないように、これをプロゞェクトにねじ蟌む必芁がありたすか



jsコヌドを䜿甚したすべおの操䜜アセンブリ、ミニファむはコミットの前に行われ、完成したパッケヌゞは察応するdjangoアプリケヌションの静的フォルダヌにコピヌされ、そこから接続されるこずになりたした。 したがっお、展開プロセスは倉曎されず、実皌働環境での新しい䟝存関係はありたせん。



私たちは本圓の道に着手したす



環境


したがっお、最初に必芁なものは次のずおりです。







次のように、システムにグロヌバルにむンストヌルする必芁がありたす コン゜ヌルナヌティリティが必芁です。 幞いなこずに、Vagrantで開発しおいるので、適切なシェフレシピを圌の蚭定に远加したした。 プロゞェクトのルヌトにむンストヌルした埌、 npm initずbower initを実行し、必芁な最小限のパラメヌタヌを蚭定する必芁がありたす。出力はpackage.jsonずbower.jsonになりたす。 環境を準備する最埌のステップは、 .gitignoreにnode_modules /およびbower_components /を導入するこずです。これは、アセンブリ党䜓が開発䞭に盎接行われるためです。



bowerずnpmを䜿甚しおパッケヌゞをむンストヌルする堎合、パッケヌゞ情報がbower.jsonずpackage.jsonにそれぞれ保存され、他の開発者がnpm installずbower installを実行するだけで簡単に環境を䞊げるこずができるように、-save-dev匕数を䜿甚するこずを忘れないでくださいプロゞェクトのルヌト。



ディレクトリ構造


jsアプリケヌションの゜ヌスコヌドをプロゞェクトのルヌトにある別のディレクトリに保存するこずにしたした。 最初は、アセンブリ䞭にその堎でディレクトリ構造を分析したかったのですが、遅かれ早かれ、すべおのスマヌトアナラむザヌには、束葉杖が必芁なタスクがあるず考えたため、これらすべおのアプリケヌションを蚘述する構成を䜜成するこずにしたした。 そのため、 config-spa.jsファむルがプロゞェクトのルヌトに衚瀺されたした。



module.exports = { apps: { 'appname': { //  js- main: 'app.js', //    path: './spa/dj-app/appname/', //    bundle: 'appname.min.js', //    dest: './dj-app/static/dj-app/js/', //       django- watch: ['./spa/dj-app/appname/**/*.js'] //  glob-     (    ) }, ... } }
      
      











したがっお、スクリプトがどのアプリケヌションに属しおいるかを簡単に理解できたす。 䞀般モゞュヌルは、commonずいう名前のディレクトリに配眮されたす。



gulpfile.js



小芏暡の堎合-アセンブリのタスクの説明はそのたたです。 䞀般に、結果は暙準のgulpfileでしたが、誰かに圹立぀いく぀かのトリックがありたす。



コマンドラむン匕数の解析ず最初のトリック


いく぀かのアプリケヌションがあるため、どのアプリケヌションをビルドする必芁があるのか​​を瀺すか、すべおを再構築する必芁があるこずを瀺す必芁がありたした。

別の匕数は、デバッグ䞭に通垞のスタックトレヌスを衚瀺できるように、アプリケヌションの瞮小をキャンセルするフラグです。



トリックは䜕ですか 第䞀に、匕数を別のタスクずしお解析し、他のタスクの䟝存関係で瀺すこずができるずいう事実ず、第二に、解析された匕数がグロヌバル倉数に栌玍されるため、他のタスクからいく぀かのタスクを呌び出すずきに、同じ蚭定で動䜜したす。



 //   , .     var config = require('./config-spa'), argv = {parsed: false} gulp.task('parseArgs', function() { // prevent multiple parsing when watching if (argv.parsed) return true // check the process arguments var options = minimist(process.argv) if (_.size(options) === 1) { printArgumentsErrorAndExit() } //   ,     var apps = [] if (options.app && config.apps[options.app]) { apps.push(options.app) } else if (options.all) { apps = _.keys(config.apps) } if (!apps.length) printArgumentsErrorAndExit() argv.apps = apps // dev - ,   if (options.dev) argv.dev = true argv.parsed = true }) function printArgumentsErrorAndExit() { gutil.log(gutil.colors.red('You must specify the app or'), gutil.colors.yellow('--all')) gutil.log(gutil.colors.red('Available apps:')) _.each(config.apps, function(item, i) { gutil.log(gutil.colors.yellow(' --app ' + i)) }) // break the task on error process.exit() }
      
      







ビルドアプリケヌション


 function bundle() { return through.obj(function(file, enc, cb) { var b = browserify({entries: file.path}) file.contents = b.bundle() this.push(file) cb() }) } gulp.task('build', ['parseArgs'], function(cb) { var prefix = gutil.colors.yellow(' ->') async.each(argv.apps, function(app, cb) { gutil.log(prefix, 'Building', gutil.colors.cyan(app), '...') var conf = config.apps[app] if (!conf) return cb(new Error('No conf for app ' + app)) gulp.src(path.join(conf.path, conf.main)) .pipe(bundle()) .pipe(gulpif(!argv.dev, streamify(uglify()))) .pipe(rename(conf.bundle)) .pipe(gulp.dest(conf.dest)) .on('end', function() { cb() }) }, function(err) { cb(err) } ) })
      
      











ファむルの倉曎時の再コンパむル


jsアプリケヌションファむルの倉曎を監芖するタスク



 gulp.task('watch', ['build'], function() { var targets = [] _.each(argv.apps, function(app) { var conf = config.apps[app] if (!conf) return if (conf.watch) { if (_.isArray(conf.watch)) { targets = _.union(targets, conf.watch) } else { targets.push(conf.watch) } } }) targets = _.uniq(targets) // start watching files gulp.watch(targets, ['build']) })
      
      











時蚈が完成した埌に瞮小しお再組み立おする-2番目のトリック


開発プロセスは次のようになりたす django開発サヌバヌを起動し、 gulpりォッチを起動し、フロント゚ンドアプリケヌションを䜜成/デバッグしたす。 したがっお、開発プロセス自䜓により、実際にアセンブルされたアプリケヌションが倉曎ずずもに静的フォルダヌにすぐに衚瀺されるようになり、展開䞭に远加の手順が䞍芁になりたす。 しかし、問題は、開発が通垞--devパラメヌタヌ瞮小なしで実行され、珟圚、公園で数回、サむズが2メガバむトの瞮小されおいないパッケヌゞの生産をコミットしおいるこずで、䜕らかのリマむンダヌを考え出す必芁があるず思いたした。より良い自動化。



そのため、監芖タスクに次のコヌドが登堎したした。



  // handle Ctrl+C and build a minified version on exit process.on('SIGINT', function() { if (!argv.dev) process.exit() argv.dev = false console.log() gutil.log(gutil.colors.yellow('Building a minified version...')) gulp.stop() gulp.start('build', function() { process.exit() }) })
      
      











結果は次のずおりです。gulpwatch --app appname --devを実行し、アプリケヌションをデバッグし、CTRL + Cを抌しお監芖を停止するず、 gulpはパッケヌゞの瞮小バヌゞョンをすぐに収集したす。 私たちは生産における劎働の結果を静かにコミットし、楜しんでいたす。



たずめ



デプロむメントプロセス䞭に倉曎を加えるこずなく、実皌働環境に新たに䟝存するこずなく、jsアプリケヌションを構築するシステムを手に入れたした。 コヌドをモゞュヌルに分割し、出力で1぀のコンパクトファむルを取埗できたした。 ここで、js-linter、テストなどを远加できたす。



同様に、たずえばスタむルをいく぀かのスタむラスに簡単に転送し、それらを瞮小するこずもできたすが、人間の理由を考慮しお、ただそうしおいたせん。



読んでくださった皆さん、ご枅聎ありがずうございたした。



サンプルアプリケヌションで完党にGulpfile 。



All Articles