フロントエンドプロジェクトの構築に関する別の投稿

JSアプリスターター



フロントアセンブリの構築と自動化にはかなりの時間を費やしました。 このタスクは興味深いもので、話す価値があります。



コレクターができること:





入門



考えを簡単にするために、プロジェクトテンプレートを使用してリポジトリへのリンクをすぐにスローします: github.com/alexfedoseev/js-app-starter



入手方法
npmがインストールされていることを確認してください。

npm -v
      
      







必要なグローバルモジュールをインストールします(まだインストールされていない場合):

 npm install -g gulp browserify babel jade stylus http-server
      
      







リポジトリの分岐を作成します。

 git clone https://github.com/alexfedoseev/js-app-starter.git
      
      







プロジェクトの依存関係をインストールします(リポジトリのルートで実行):

 npm install
      
      







開発環境でプロジェクトをビルドし、ローカルサーバーを起動します。

 npm start
      
      







ブラウザーを開き、 lvh.mehaps500に移動します



コレクターとしてGulpを使用します。

アセンブリプロセスには何が含まれ、どの技術が使用されますか。



一般的に、SlimとSassが好きですが、Ruby to Ruby、JS to JS:フロントエンドプロジェクトでは、npmのピースのみを使用します。 必要に応じて、任意のツールを交換できます。



プロジェクト構造



 | dist/ | lib/ |-- gulp/ |-- helpers/ |-- tasks/ |-- config.js | node_modules/ | public/ |-- css/ |-- files/ |-- fonts/ |-- img/ |-- js/ |-- json/ |-- favicon.ico |-- index.html | src/ |-- css/ |-- files/ |-- fonts/ |-- html/ |-- img/ |-- js/ |-- json/ |-- sprite/ |-- favicon.ico | .gitignore | .npmignore | gulpfile.js | npm-shrinkwrap.json | package.json
      
      



Github



.gitignore.npmignore

これらのファイルの中には、コミットと公開時にgitとnpmが無視するもののリストがあります。



node_modules /

npmを介してインストールするすべてのモジュールは、このディレクトリに分類されます。



npm-shrinkwrap.json

node_modules /の内容をリポジトリに保持しません。 代わりに、このファイルを介してすべての依存関係を送信しています。 コマンド`npm shrinkwrap`によって自動的に生成されます。



package.json

これは、グローバルプロジェクト設定を含むファイルです。 彼に戻ります。



gulpfile.js

通常、プロジェクトをビルドするためにすべてのタスクがここに保存されますが、今回の場合は、環境変数の値を決定するだけで、gulpタスクが含まれるフォルダーにさらにスローされます。



lib / gulp /

ここに、コレクターのすべての設定とタスクを保存します。



|-config.js

タスク自体の編集を最小限に抑えるために、すべてのタスクの設定を別のファイルに取り出します。



|-ヘルパー/

コレクターのヘルパーメソッド。



|-タスク/

そして、gulpタスク自体。



src /

プロジェクトのソース。



公開/

アセンブリの結果。 このフォルダーのすべてのコンテンツはコレクターによって生成され、新しいアセンブリが完全にクリアされる前に、ここには何も保存されません。



dist /

時々私はオープンソースのモジュールを書きます。 このフォルダーには、アセンブリ後に、書かれたjsライブラリーの通常バージョンと縮小バージョンがあります。 public /ディレクトリは、デモのリポジトリとして使用されます。 通常のサイトまたはランディングページを作成している場合、それらは必要ありません。



プロジェクトのセットアップ



package.json


これは、グローバルプロジェクト設定が保存されるファイルです。

彼の内部の詳細な説明はここにあります: browsenpm.org/package.json

以下では、いくつかの重要な部分のみに焦点を当てます。



 { //   "name": "js-app-starter", //   //     /  js+css        "version": "0.0.1", //    js-,      , //     `require('your-lib')` "main": "./dist/app.js", //  browserify //    ,      ES6  ES5 "browserify": { "transform": [ "babelify" ] }, //   ( ) "scripts": { "start": "NODE_ENV=development http-server -a lvh.me -p 3500 & gulp", "build": "NODE_ENV=production gulp build" }, //  jshint (  ) "lintOptions": { "esnext": true ... }, // Frontend  "dependencies": { "jquery": "^2.1.3" ... }, // Development  "devDependencies": { "gulp": "^3.8.11" ... } }
      
      



Github



コンソールコマンド


package.jsonでは、コンソールコマンドのエイリアスを指定できます。エイリアスは、開発プロセス中に頻繁に実行されます。



 "scripts": { "start": "NODE_ENV=development http-server -a lvh.me -p 3500 & gulp", "build": "NODE_ENV=production gulp build" }
      
      







開発アセンブリ

プロジェクトで作業を開始する前に、次のものが必要です。



 # ,   npm start #      NODE_ENV=development http-server -a lvh.me -p 3500 & gulp
      
      





部品に分解する
 #    NODE_ENV=development #      lvh.me   3500 http-server -a lvh.me -p 3500 #  gulp  gulp
      
      









生産組立

プロジェクトをリリースする準備ができたら、生産アセンブリを行います。



 #  Ctrl+C,      ,    # ,   npm run build #      NODE_ENV=production gulp build
      
      





部品に分解する
 #    NODE_ENV=production #  gulp- `build` gulp build
      
      









ガルプ



Gulpに渡します。 タスクの構造は、 Dan Telloのコレクターから取得されます。



ダイビングの前に、通常のgulpタスクの実行順序に関する短いコメント:



 var gulp = require('gulp'); gulp.task('task_1', ['pre_task_1', 'pre_task_2'], function() { console.log('task_1 is done'); }); //    `task_1`,      `task_1 is done` //    `gulp task_1` //     `task_1`    `['pre_task_1', 'pre_task_2']` //  ,  'pre_task_1' & 'pre_task_2' -  , //           , //  `task_1`    ,   2 pre- -   
      
      







次に、何をどの順序で収集するかを考えてみましょう。



開発アセンブリ

`npm start`gulp コマンドを実行します。 次に何が起こるか:





生産組立

すべてが彼女の方が簡単です。 「npm run build」は、「 gulp build」コマンドを起動します。このコマンドは、ターゲットフォルダーlint js-codeをクリアし、スプライトを収集してから、プロジェクトをビルドします(ソースマップなし)。 上記のコメント付きのコード。



Gulpタスク設定ファイル


すべての主要なタスク構成は、個別のlib / gulp / config.jsファイルに移動されます



 /* file: lib/gulp/config.js */ var pkg = require('../../package.json'), //  package.json bundler = require('./helpers/bundler'); //      /*   */ var _src = './src/', //    _dist = './dist/', //       _public = './public/'; //         var _js = 'js/', //   javascript  _css = 'css/', //   css _img = 'img/', //    _html = 'html/'; //   html /* *  js / css  * * : app.js, app.css -  * admin.js, admin.css -  * * : your-lib.js -    * your-lib.jquery.js -    jquery- * */ var bundles = [ { name : 'app', //   global : 'app', //   ,   ,      compress : true, // ? saveToDist : true //    `/dist`? (true -   , false -   ) } ]; module.exports = { /*    */ };
      
      



Github



HTMLアセンブリ


テンプレートにはJadeを使用します。 パーシャルの挿入、インラインjavascript、変数、ミックスイン、その他多くのクールなものを使用できます。



ガルプ
構成



 /* file: lib/gulp/config.js */ html: { src: _src + _html, //   jade- dest: _public, //    params: { //   jade pretty: devBuild, //    html? locals: { // ,      pkgVersion: pkg.version //      `pkgVersion` } } }
      
      



Github



タスク



 /* file: lib/gulp/tasks/html.js */ var gulp = require('gulp'), jade = require('gulp-jade'), jadeInherit = require('gulp-jade-inheritance'), gulpif = require('gulp-if'), changed = require('gulp-changed'), filter = require('gulp-filter'), notifier = require('../helpers/notifier'), config = require('../config').html; gulp.task('html', function(cb) { //   jade-   src/html gulp.src(config.src + '*.jade') //  dev-,  watcher     .pipe(gulpif(devBuild, changed(config.dest))) //    .pipe(jadeInherit({basedir: config.src})) //  - ( `_` ) .pipe(filter(function(file) { return !/\/_/.test(file.path) || !/^_/.test(file.relative); })) //  jade  html .pipe(jade(config.params)) //  html- .pipe(gulp.dest(config.dest)) //     .on('end', function() { notifier('html'); //  (  + ) cb(); // gulp-callback,     }); });
      
      



Github

ソースコード
Src / htmlフォルダー構造



 | src |-- html |-- index.jade #   |-- components/ #   |-- _header.jade |-- helpers/ # ,  |-- _params.jade |-- _mixins.jade |-- meta/ #  head,    . |-- _head.jade
      
      



Github



すべてのパーシャルは `_`(アンダースコア)で始まるため、アセンブリ中にそれらをフィルターして無視できます。



ヘルパー/ _variables.jade

必要なパラメーターを変数に保存します。 たとえば、電話がページの複数の場所にある場合、変数に保存してテンプレートで使用することをお勧めします。



 /* file: src/html/helpers/_variables.jade */ - var release = pkgVersion //   gulp- - var phone = '8 800 CALL-ME-NOW' // 
      
      



Github



ヘルパー/ _mixins.jade

頻繁に使用されるブロックは、ミックスインでラップできます。



 /* file: src/html/helpers/_mixins.jade */ mixin phoneLink(phoneString) - var cleanPhone = phoneString.replace(/\(|\)|\s|\-/g, '') a(href="tel:#{cleanPhone}")= phoneString //    // +phoneLink(phone)
      
      



Github



index.jade

メインページのスケルトン。



 /* file: src/html/index.jade */ include helpers/_variables //   include helpers/_mixins //   doctype html html head include meta/_head body include components/_header include components/_some_component include components/_footer
      
      



Github



meta / _head.jade

ヘッドコンテンツ。



 /* file: src/html/meta/_head.jade */ meta(charset="utf-8") ... //   ,    js/css    link(rel="stylesheet" href="css/app.min.css?v=#{release}") script(src="js/app.min.js?v=#{release}") ...
      
      



Github





JavaScriptアセンブリ


Browserifyはモジュラーシステムとして使用します。 これにより、ブラウザでCommonJSモジュールを直接接続するスタイルを使用できます。 さらに、ES6構文を使用できるようになりました。Browselifyがjsをビルドする前に、 BabelはそれをES5に変換します。 ビルドする前に、jsHint実行してコードの品質を確認します。



Browserifyには1つの欠点があります。外部依存関係(jQueryプラグインなど)を使用してライブラリを作成すると、正しいUMDラッパーを作成できなくなります。 この場合、Browserifyを連結に置き換え、手でラッパーを記述します。



バンドルについて
プロジェクトでは、いくつかのjs / cssのセットを作成する必要がある場合があります。



たとえば、front + adminと記述します。 または、2つのバージョンのライブラリ:依存関係のない、jQueryプラグインの形式。 これらのアセンブリは分離する必要があります。 これを行うには、コレクターの設定で、配列を作成します。



 /* file: lib/gulp/config.js */ /*   */ var bundles = [ { name : 'myLib', //   global : 'myLib', //   ,      compress : true, // ? (   ) saveToDist : true //    `/dist`? } ]; /*   /   */ var bundles = [ { name : 'app', //   global : false, //     compress : true, // ? saveToDist : false //    `/dist`? }, name : 'admin', global : false, compress : true, saveToDist : false } ];
      
      



Github



js / cssコレクターは、対応するエンドポイントファイル( `app.js`または` app.styl`)のjs / cssソースを含むフォルダーを検索します。 このエンドポイントファイルを通じて、すべてのバンドルの依存関係を管理します。 以下にその構造を示します。



バンドルをコレクターに渡す前に、設定でオブジェクトを形成する`bundler`ヘルパーに配列を渡します。
ガルプ
構成



 /* file: lib/gulp/config.js */ scripts: { bundles: bundler(bundles, _js, _src, _dist, _public), //   banner: '/** ' + pkg.name + ' v' + pkg.version + ' **/\n', //     min.js extensions: ['.jsx'], //    lint: { //   jshint options: pkg.lintOptions, dir: _src + _js } }
      
      



Github



タスク



 /* file: lib/gulp/tasks/scripts.js */ var gulp = require('gulp'), browserify = require('browserify'), watchify = require('watchify'), uglify = require('gulp-uglify'), sourcemaps = require('gulp-sourcemaps'), derequire = require('gulp-derequire'), source = require('vinyl-source-stream'), buffer = require('vinyl-buffer'), rename = require('gulp-rename'), header = require('gulp-header'), gulpif = require('gulp-if'), notifier = require('../helpers/notifier'), config = require('../config').scripts; gulp.task('scripts', function(cb) { //  -  var queue = config.bundles.length; //     ,    , //      bundle-   //      var buildThis = function(bundle) { //  bundle browserify var pack = browserify({ //   sourcemaps cache: {}, packageCache: {}, fullPaths: devBuild, //   end-point (app.js) entries: bundle.src, //   ,     // browserify    UMD- //        bundle.global standalone: bundle.global, //   extensions: config.extensions, //  sourcemaps? debug: devBuild }); //  var build = function() { return ( // browserify- pack.bundle() //  browserify-  vinyl .pipe(source(bundle.destFile)) //   ,    `require`   .pipe(derequire()) //  dev-,      `public/` ( -  )) .pipe(gulpif(devBuild, gulp.dest(bundle.destPublicDir))) //     `dist` -  .pipe(gulpif(bundle.saveToDist, gulp.dest(bundle.destDistDir))) //     sourcemaps   .pipe(gulpif(bundle.compress, buffer())) //  dev-    —  sourcemaps .pipe(gulpif(bundle.compress && devBuild, sourcemaps.init({loadMaps: true}))) //  .pipe(gulpif(bundle.compress, uglify())) //      `.min` .pipe(gulpif(bundle.compress, rename({suffix: '.min'}))) //    production -        .pipe(gulpif(!devBuild, header(config.banner))) //  sourcemaps .pipe(gulpif(bundle.compress && devBuild, sourcemaps.write('./'))) //     `/dist` .pipe(gulpif(bundle.saveToDist, gulp.dest(bundle.destDistDir))) //   `public` .pipe(gulp.dest(bundle.destPublicDir)) //    callback handleQueue ( ) .on('end', handleQueue) ); }; //   watchers if (global.isWatching) { //  browserify-  watchify pack = watchify(pack); //      -   pack.on('update', build); } //     var handleQueue = function() { // ,    notifier(bundle.destFile); //    if (queue) { //   1 queue--; //    ,  ,    if (queue === 0) cb(); } }; return build(); }; //      config.bundles.forEach(buildThis); });
      
      



Github

ソースコード
Src / jsフォルダー構造



 | src/ |-- js/ |-- components/ #   |-- helpers/ # js- |-- app.js # end-point 
      
      



Github



app.js

このファイルを通じて、jsコンポーネントのすべての依存関係と実行順序を駆動します。 ファイル名はバンドルの名前と一致する必要があります。



 /* file: src/js/app.js */ /* Vendor */ import $ from 'jquery'; /* Components */ import myComponent from './components/my-component'; /* App */ $(document).ready(() => { myComponent(); });
      
      



Github

npmに依存関係がない場合の対処方法
このような場合、 browserify-shimを使用します。これは、通常のライブラリをCommonJS互換モジュールに変換できるプラグインです。 それで、 nQueryにはないjQueryプラグイン`maskedinput`があります。



変換を「package.json」に追加し、依存関係設定を設定します。



 /* file: package.json */ "browserify": { "transform": [ "babelify", "browserify-shim" //   ] }, //  `browserify-shim`     //    github: https://github.com/thlorenz/browserify-shim "browser": { "maskedinput": "./path/to/jquery.maskedinput.js" }, "browserify-shim": { "maskedinput": { "exports": "maskedinput", "depends": [ "jquery:jQuery" ] } }
      
      







その後、モジュールを接続できます。

 require('maskedinput');
      
      







CSSアセンブリ


プリプロセッサとしてStylusを使用します。 さらに、ベンダープレフィックスを手で登録しないように、css 自動プレフィックスを使用します。



ガルプ
構成



 /* file: lib/gulp/config.js */ css: { bundles: bundler(bundles, _css, _src, _dist, _public), //   src: _src + _css, //      watcher params: {}, //     stylus -   autoprefixer: { //  autoprefixer browsers: ['> 1%', 'last 2 versions'], //     cascade: false //   ,    }, compress: {} //     -   }
      
      



Github



タスク



 /* file: lib/gulp/tasks/css.js */ var gulp = require('gulp'), process = require('gulp-stylus'), prefix = require('gulp-autoprefixer'), compress = require('gulp-minify-css'), gulpif = require('gulp-if'), rename = require('gulp-rename'), notifier = require('../helpers/notifier'), config = require('../config').css; /*  css-   js- */ gulp.task('css', function(cb) { var queue = config.bundles.length; var buildThis = function(bundle) { var build = function() { return ( gulp.src(bundle.src) .pipe(process(config.params)) .pipe(prefix(config.autoprefixer)) .pipe(gulpif(bundle.compress, compress(config.compress))) .pipe(gulpif(bundle.compress, rename({suffix: '.min'}))) .pipe(gulp.dest(bundle.destPublicDir)) .on('end', handleQueue) ); }; var handleQueue = function() { notifier(bundle.destFile); if (queue) { queue--; if (queue === 0) cb(); } }; return build(); }; config.bundles.forEach(buildThis); });
      
      



Github

ソースコード
SRC / CSSフォルダー構造



 | src/ |-- css/ |-- components/ #   |-- header.styl |-- footer.styl |-- globals/ |-- fonts.styl #   |-- global.styl #    |-- normalize.styl #  /  |-- variables.styl #  |-- z-index.styl # z-  |-- helpers/ |-- classes.styl #   |-- mixins.styl #   |-- sprite/ |-- sprite.json # json,  gulp.spritesmith |-- sprite.styl #   json css- |-- vendor/ #  css   |-- app.styl # end-point 
      
      



Github



app.styl

このファイルを介して、cssコンポーネントが接続される順序を制御します。 ファイル名はバンドルの名前と一致する必要があります。



 /* file: src/css/app.styl */ @import "helpers/mixins" @import "helpers/classes" @import "globals/variables" @import "globals/normalize" @import "globals/z-index" @import "globals/fonts" @import "globals/global" @import "sprite/sprite" @import "vendor/*" @import "components/*"
      
      



Github





他のすべてのタスク-写真、スプライト、クリーニングなど-は、追加のコメントを必要としません(実際、私は既に落書きにうんざりしています)。 ソースはリポジトリにあります: github.com/alexfedoseev/js-app-starter



妨害や追加がある場合-ここでのコメントまたはGithubでの問題 /プルリクエストを通じてフィードバックをお待ちしております。 頑張って!



All Articles