ES 6ゼロ基礎教育_宝くじ項目の解析-学習ノート(二)

15374 ワード

宝くじ項目実戦学習記録(二)
環境構築の自動化
ここでのコンパイル環境はgulp+webpack+node+express+express-generator
  • Gulpはnodejs streamベースのフローフロントエンド構築ツールであり、Grunt機能と同様にフロントエンドリソースのコンパイル、検査、圧縮などの自動化作業に専念している.
  • webpack各種ファイル(js,css,ピクチャなど)をパッケージ化するためのツール
  • express nodejsのwebサーバ
  • express-generator nodejsのwebサーバの初期化ツール
  • 注釈:自動リフレッシュ環境構築を実現するためにこの方法を使用する必要はありません.これはその一例にすぎません.

  • Nodeのインストールは詳しくは言いませんが、nodeとnpmをインストールするには、バンドルしてインストールされていることに注意してください.
    //           
    
    //          ,         npm   
    npm --init //      package.json  
    
    //       gulp
    npm install --global gulp
    //      express-generator   express
    npm install -g express-generator //    express    
    npm install -g express
    //        
    express -V  
    //     expres   ,   view        ejs     
    express -e --view=ejs

    express-generatorがexpressより先にインストールされているのは、逆にインストールすると使用できないからですexpress -eコマンド
    以上が成功すると、このようなディレクトリ構造が得られます.
    gulpfile.babel.js //gulp    babel        
    package.json 
    .babelrc // babel        ,      
    .gitignore //              git           
    app //           ,      
    ├── css 
    ├── js
    └── views
    server // express      ,                 
    ├── app.js
    ├── bin
    ├── package.json
    ├── public 
    ├── routes
    └── views
    tasks
    ├── browser.js
    ├── build.js
    ├── clean.js
    ├── css.js
    ├── default.js
    ├── pages.js
    ├── scripts.js
    ├── server.js
    └── util
        └── args.js

    コメント:
  • gulpfile.babel.js,gulpのデフォルトプロファイルについては、デフォルトgulpのファイルはes 5で記述されていますが、es 6を統一的に使用するため、元のファイル名gulpfile.jsgulpfile.babel.jsに変更されます.
  • express -e --view=ejsを使用しているため、nodejs webサーバとして必要なファイルを含むexpressのディレクトリを独自に生成します.

  • .babelrcファイル
    babelのプロファイルです.ここではpressetsを構成する必要があります.es 6構文をコンパイルするためです.
    {
      "presets":["es2015"]
    }

    gulpfile.babel.jsファイル
    これはgulpのデフォルトプロファイルですが、本プロジェクトのアーキテクチャはtasksディレクトリを中心に変更されているため、デフォルトプロファイルにtasksディレクトリを参照する処理を構成する必要があります.gulpが実行されると、デフォルトプロファイルでtasksディレクトリが見つかり、その中の本当のスクリプトが実行されます.
    import requireDir from 'require-dir'; // node        
    requireDir('./tasks'); //   ./tasks  

    npmに必要なソフトウェア補完
    プロジェクトには多くのモジュールソフトウェアが使用されます.これらはnpmのライブラリにあり、ダウンロードして開発用に保存する必要があります.
    npm install XXXX --save-dev

    以下は完全なnpmソフトウェア構成情報です.package.jsonファイルから取得します.
    {
      "name": "es6-caippiao-demo",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "babel-core": "^6.26.0",
        "babel-loader": "^7.1.2",
        "babel-polyfill": "^6.26.0",
        "babel-preset-env": "^1.6.1",
        "babel-preset-es2015": "^6.24.1",
        "cookie-parser": "^1.4.3",
        "del": "^3.0.0",
        "express": "^4.16.2",
        "express-generator": "^4.15.5",
        "gulp": "^3.9.1",
        "gulp-concat": "^2.6.1",
        "gulp-if": "^2.0.2",
        "gulp-live-server": "0.0.31",
        "gulp-livereload": "^3.8.1",
        "gulp-plumber": "^1.1.0",
        "gulp-rename": "^1.2.2",
        "gulp-sequence": "^0.4.6",
        "gulp-uglify": "^3.0.0",
        "gulp-util": "^3.0.8",
        "jquery": "^3.2.1",
        "mockjs": "^1.0.1-beta3",
        "morgan": "^1.9.0",
        "require-dir": "^0.3.2",
        "serve-favicon": "^2.4.5",
        "vinyl-named": "^1.1.0",
        "webpack": "^3.8.1",
        "webpack-stream": "^4.0.0",
        "yargs": "^10.0.3"
      }
    }

    gulp使用
    公式入門ガイドには次のように書かれています.
    //1.      gulp:
    
    $ npm install --global gulp
    //2.          (devDependencies)  :
    
    $ npm install --save-dev gulp
    //3.               gulpfile.js    :
    
    var gulp = require('gulp');
    
    gulp.task('default', function() {
      //              
    });
    //4.    gulp:
    
    $ gulp
    //      default    (task)     ,   ,           。
    
    //           (task),    gulp  

    gulpの実行はいくつかのコマンドにすぎず、apiもいくつかの-gulp-apiしかなく、gulpがどのように実行されているのかは大体理解できます.そこで、ここでは公式のgulpインスタンスと照らし合わせて、このプロジェクトのgulpインスタンスを分析します.
    参照:
  • gulp公式
  • http://www.tangshuang.net/3126.html

  • 本プロジェクトのgulp
    本プロジェクトのgulpはwebpackとbabelを組み合わせてes 6文法処理をパッケージ化し、翻訳します.
    まずディレクトリといえば、本プロジェクトのgulpはtasksディレクトリを使用し、gulpに関するすべてのスクリプトを格納し、主に標準プロジェクトのgulpスクリプトディレクトリに従って配置されています.
    tasks 
    ├── browser.js  //      
    ├── build.js //       
    ├── clean.js //      
    ├── css.js // css   
    ├── default.js //  gulp        ,       
    ├── pages.js //        
    ├── scripts.js //      
    ├── server.js // nodejs server         
    └── util //        
        └── args.js //       gulp        

    そして実行の順番についてお話ししますが、
    gulpコマンド-->gulpfile.babel.js-->tasksディレクトリ-->args.jsコマンドラインに入力されたコマンドパラメータを読み込み-->default.jsデフォルトタスクを実行-->build.js関連する他のタスクを指定-->他のタスクスクリプトの拡散.....
    このように処理が必要なファイルストリームをストリーム方式で一歩一歩転送し、フィルタ処理を行い、出力する.
    ファイルjs
    yargsというモジュールを用いてコマンドラインのパラメータを処理することにより,主にコマンドラインパラメータのキャプチャとフィルタリングを容易に処理する.公式住所
    import yargs from 'yargs';
    const args = yargs
    
        .option('production', {
            boolean: true,
            default: false,
            describe: 'min all scripts'
        })
    
        .option('watch', { // watch   
            boolean: true,
            default: false,
            describe: 'watch all files'
        })
    
        .option('verbose', {
            boolean: true,
            default: false,
            describe: 'log'
        })
    
        .option('sourcemaps', {
            describe: 'force the creation of sroucemaps'
        })
    
        .option('port', {
            string: true,
            default: 8080,
            describe: 'server port'
        })
    
        .argv //      ,          
    
    export default args;

    備考:パラメータは使わなくてもいいです.
    ファイルjs
    これはgulpのデフォルトで、まず実行されるタスクスクリプトファイルで、ここから他のタスクスクリプトに拡散します.
    import gulp from 'gulp';
    gulp.task('default',['build']); //          build   

    ファイルjs
    ここでは、スクリプトの実行順序をスケジュールする特別なパッケージgulp-sequenceを使用して、本物のbuildスクリプトタスクファイルです.
    import gulp from 'gulp';
    import gulpSequence from 'gulp-sequence';
    //               ,     
    gulp.task('build',gulpSequence('clean','css','pages','scripts',['browser','serve']));

    これは公式サイトの例です.
    // usage 1, recommend 
    // 1. run 'a', 'b' in parallel; 
    // 2. run 'c' after 'a' and 'b'; 
    // 3. run 'd', 'e' in parallel after 'c'; 
    // 3. run 'f' after 'd' and 'e'. 
    gulp.task('sequence-1', gulpSequence(['a', 'b'], 'c', ['d', 'e'], 'f'))

    ファイルjs
    コンパイルするたびに元のファイルを空にする必要があります.
    import gulp from 'gulp';
    import del from 'del';
    //                   ,      
    import args from './util/args'; 
    gulp.task('clean',()=>{ //    es6       
      return del(['server/public','server/views']) //   2      
    })

    ファイルcss.js
    cssファイルのコンパイルを処理する責任はありませんが、ここではより多くのcssコンパイル処理をしていません.cssコンパイルには通常less、sassなどがあり、異なるプラグインで処理する必要がありますが、ここでは直接出力するだけなので紹介しません.
    import gulp from 'gulp';
    //                   ,      
    import args from './util/args';
    
    gulp.task('css',()=>{
      return gulp.src('app/**/*.css') //            
        .pipe(gulp.dest('server/public'))
    
    })

    ファイルjs
    ejsページの処理を担当する(他のページを同じようにプッシュしてもよい、.vueなど)コンパイル.
    import gulp from 'gulp';
    import gulpif from 'gulp-if';
    import livereload from 'gulp-livereload'; //         
    import args from './util/args';
    
    gulp.task('pages',()=>{
      return gulp.src('app/**/*.ejs')
        .pipe(gulp.dest('server'))
        //        watch   ,       
        .pipe(gulpif(args.watch,livereload()))
    })

    なお、ここでのwatchは、リスニングコマンドパラメータのwatchにすぎず、リスニングファイルの変化ではない.
    ファイルscripts.js
    これが最も主要なスクリプトタスクファイルです.ここにはwebpackの処理、ファイル圧縮の処理が含まれています.
    import gulp from 'gulp';
    import gulpif from 'gulp-if';
    import concat from 'gulp-concat';
    import webpack from 'webpack'; // webpack  
    import gulpWebpack from 'webpack-stream'; // webpack        
    import named from 'vinyl-named';  //                   
    import livereload from 'gulp-livereload';
    import plumber from 'gulp-plumber'; //      gulp              
    import rename from 'gulp-rename'; //      
    import uglify from 'gulp-uglify'; // js         
    import {log,colors} from 'gulp-util'; 
    import args from './util/args';
    
    gulp.task('scripts',()=>{
      return gulp.src(['app/js/index.js'])
        .pipe(plumber({ //      errorHandle  
          errorHandle:function(){
            //   
          }
        }))
        .pipe(named()) //vinyl-named               ,          hash.
        .pipe(gulpWebpack({ //    webpack   js      babel     
          module:{ //    webpack        
            loaders:[{
              test:/\.js$/,
              loader:'babel-loader' //    babel loader
            }]
          }
        }),null,(err,stats)=>{
          log(`Finished '${colors.cyan('scripts')}'`,stats.toString({
            chunks:false
          }))
        })
        .pipe(gulp.dest('server/public/js')) //        js   
        .pipe(rename({ //    ,     js           
          basename:'cp',
          extname:'.min.js'
        }))
        .pipe(uglify({compress:{properties:false},output:{'quote_keys':true}})) //     
        .pipe(gulp.dest('server/public/js')) //          js   
        .pipe(gulpif(args.watch,livereload())) // watch          
    })

    なお、ここでのwatchは、リスニングコマンドパラメータのwatchにすぎず、リスニングファイルの変化ではない.
    ファイルサーバjs
    このserverはexpressを指し、webのserverであり、ここでの役割はローカル仮想webサーバを架設してWebファイルをレンダリングすることで、ローカル仮想開発環境を構成することができる.
    ファイル名はserver.jsですがgulpのタスクはserveと呼ばれています.ここで注意してください.1つはファイル名で、1つはタスク名で、両者は衝突しません.実は同じ名前で、混乱を避けたほうがいいです.
    import gulp from 'gulp';
    import liveserver from 'gulp-live-server';
    import args from './util/args';
    
    gulp.task('serve', (cb) => {
        if (!args.watch) return cb(); //    watch          web    
    
        let server = liveserver.new(['--harmony', 'server/bin/www']);
        server.start(); //    web    
    
        //         gulp   watch     
        //     web            
        gulp.watch(['server/public/**/*.js', 'server/views/**/*.ejs'], function (file) {
            //       web       
            server.notify.apply(server, [file]);
        });
        //      web   ,           ,       
        gulp.watch(['server/routes/**/*.js', 'server/app.js'], function () {
            server.start.bind(server)()
        });
    });

    注意しなければならないのは、ここで監視しているのはserver/publicディレクトリの下、言い換えれば、コンパイル後のファイルの変化です!
    参照:gulp-live-server
    ファイルjs
    この名前はあまりよくありません.ここの役割はbrowserではありません.このファイルは主にソースコードの変化を傍受し、変化した内容をそれぞれ異なるタスクに通知して処理します.これは本当にファイル傍受を実現するタスクです.
    import gulp from 'gulp';
    import args from './util/args';
    
    gulp.task('browser',(cb)=>{
      if(!args.watch) return cb();
      //    js     
      gulp.watch('app/**/*.js',['scripts']);
      //    ejs      
      gulp.watch('app/**/*.ejs',['pages']);
      //    css     
      gulp.watch('app/**/*.css',['css']);
    });

    バックグラウンドサーバデータmock
    mockの意味はシミュレーションで、バックグラウンドapiデータをシミュレートして、本当に前後端の分離開発を実現して、バックエンドの配置を待ってから仕事を始める必要はありません.双方が協議したデータ構造を知っていればいいです.
    mockデータはexpressとmockjsモジュールをインストールする必要があります.
    .
    ├── app.js // express      
    ├── bin
    │   └── www // express        
    ├── package.json
    ├── public
    │   ├── css //        css   
    │   │   ├── index.css
    │   │   ├── layout.css
    │   │   ├── lottery.css
    │   │   └── reset.css
    │   └── js //        js   
    │       ├── cp.min.js
    │       └── index.js
    ├── routes //   web       
    │   ├── index.js //        
    │   └── users.js
    └── views //        ejs   
        ├── error.ejs
        └── index.ejs

    ここでは、主なルーティングファイルに注目します.
    var express = require('express'); 
    var mockjs = require('mockjs'); //    mockjs
    var router = express.Router(); //    express    
    //             ,        
    var makeIssue = function() {
        var date = new Date();
        // first_issue_date       
        // end_issue_date          
        var first_issue_date = new Date();
        first_issue_date.setHours(9);
        first_issue_date.setMinutes(10);
        first_issue_date.setSeconds(0);
        var end_issue_date = new Date(first_issue_date.getTime() + 77 * 10 * 60 * 1000);
    
        var cur_issue, end_time, state;
    
        //     
        if (date.getTime() - first_issue_date.getTime() > 0 && date.getTime() - end_issue_date.getTime() < 0) {
            // cur_issue_date     
            var cur_issue_date = new Date();
            cur_issue_date.setHours(9);
            cur_issue_date.setMinutes(0);
            cur_issue_date.setSeconds(0);
    
            var minus_time = date.getTime() - cur_issue_date.getTime();
            var h = Math.ceil(minus_time / 1000 / 60 / 10);
            var end_date = new Date(cur_issue_date.getTime() + 1000 * 60 * 10 * h);
            end_time = end_date.getTime();
            cur_issue = [end_date.getFullYear(), ('0' + (end_date.getMonth() + 1)).slice(-2), ('0' + end_date.getDate()).slice(-2), ('0' + h).slice(-2)].join('');
        } else {
            //        
            first_issue_date.setDate(first_issue_date.getDate() + 1);
            end_time = first_issue_date.getTime();
            cur_issue = [first_issue_date.getFullYear(), ('0' + (first_issue_date.getMonth() + 1)).slice(-2), ('0' + first_issue_date.getDate()).slice(-2), '01'].join('');
        }
    
        var cur_date = new Date();
        if (end_time - cur_date.getTime() > 1000 * 60 * 2) {
            state = '    ';
        } else {
            state = '   ';
        }
        return {
            issue: cur_issue,
            state: state,
            end_time: end_time
        };
    };
    //        
    /* GET home page. */
    router.get('/', function(req, res, next) {
        res.render('index', {
            title: 'Express'
        });
    });
    //     mock          
    // get opencode
    router.get('/get/opencode', function(req, res, next) {
        var issue = makeIssue().issue; //             
        var data = mockjs.mock({
            'data': [/[1-3]/, /[4-5]/, /[6-7]/, /[8-9]/, /1[0-1]/]
        }).data;
        res.json({
            issue: issue,
            data: data
        });
    });
    //       
    module.exports = router;

    総じて一般的なnodejsのwebサーバとは差が少ないので、nodejsのwebサーバ作成の知識の一部を少し補足すれば理解できるので、詳細な説明はしません.