Skip to content
uupaa edited this page Nov 8, 2014 · 35 revisions

このエントリでは、WebModule を使ったモジュール開発のワークフローについて簡単に流れを説明します。

WebModule を使ったモジュール開発のワークフローについて

ここでは例として ~/workflow 以下に GitHub 上で作成した MyExample.js リポジトリをクローンし、MyExample.js という名前のモジュールを作成する流れを説明します。

  1. WebModule が必要とするソフトウェアについて:

    • Mac OS X 10.8 以上
    • Homebrew
    • Node.js の最新版
    • Java runtime (Closure compilerが要求します)
    • Google Chrome Browser
    • Xcode にバンドルされている iOS Simulator
  2. インストール手順:

    $ ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"
    $ brew -v
    > Homebrew 0.9.5
    
    $ brew install node
    $ npm -v
    > 2.0.2
    • npm の検索パス(NODE_PATH)を シェルのリソースファイル(.zshrcなど)に追加します
    $ echo 'export NODE_PATH="/usr/local/lib/node_modules"' >> ${HOME}/.zshrc
    $ source ${HOME}/.zshrc
    $ env | grep NODE_PATH
    > NODE_PATH=/usr/local/lib/node_modules
    • 必要な npm パッケージをインストールします。
      npm run build でエラーが出る場合は Compile.js のエントリを参照してください。
    $ npm install -g plato
    $ npm install -g jshint
    $ npm install -g http-server
    $ npm install -g uupaa.task.js
    $ npm install -g uupaa.compile.js
  3. WebModule を ~/workspace にクローンします:

    $ mkdir ~/workspace
    $ cd workspace
    $ git clone git@github.com:uupaa/WebModule.git
  4. MyExample.js リポジトリを GitHub に作成します:

    • Creating a new repository を参考にしてください

      • (1) ユーザアカウントを選択します
      • (2) WebModule 名を入力します
      • (3) Description を入力します(省略可能です)
      • (4) Initialize this repository with a README をチェックし、ライセンスを選択します。お勧めは MIT ライセンスです
      • (5) ボタンをクリックしてリポジトリを作成します
      Owner                    Repository name
      +-------------------+   +-------------------+
      | your account  (1) | / | MyExample.js  (2) |
      +-------------------+   +-------------------+
      
      Description (optional)
      +------------------------------------------------+
      | my first webmodule  (3)                        |
      +------------------------------------------------+
      
      [x] Public
      
      [x] Initialize this repository with a README  (4)
      +----------------------+  |  +---------------------------------+
      |                      |  |  | Add a license: MIT License  (4) |
      +----------------------+  |  +---------------------------------+
      
      +------------------------+
      | Create repository  (5) |
      +------------------------+
      
  5. 作成した WebModule (MyExample.js) リポジトリを ~/workspace にクローンします:

    • クローン後に、MyExample.js ディレクトリに移動してください
    > ~/workspace
    
    $ git clone git@github.com:YOUR-ACCOUNT/MyExample.js.git
    $ cd MyExample.js
  6. WebModule の構造をクローンします:

    $ pwd
    > ~/workspace/MyExample.js
    
    $ node ../WebModule/clone
    > clone:     ~/workspace/MyExample.js/lint/plato/README.md
    > clone:     ~/workspace/MyExample.js/release/README.md
    > clone:     ~/workspace/MyExample.js/.gitignore
    > clone:     ~/workspace/MyExample.js/.jshintrc
    > clone:     ~/workspace/MyExample.js/.npmignore
    > clone:     ~/workspace/MyExample.js/.travis.yml
    > clone:     ~/workspace/MyExample.js/index.js
    > clone:     ~/workspace/MyExample.js/lib/MyExample.js
    > clone:     ~/workspace/MyExample.js/test/test.js
    > clone:     ~/workspace/MyExample.js/package.json
    > exists:    ~/workspace/MyExample.js/README.md - overwrite it? (y/n): y
    > overwrite: ~/workspace/MyExample.js/README.md
  7. MyExample.js の初期化を行います:

    $ pwd
    > ~/workspace/MyExample.js
    
    $ npm run init
    > npm update
    > npm run build
    > npm run test-page
  8. 必要な外部モジュールがある場合は、package.json の dependencies や devDependencies に追加します:

    • package.json を変更後に $ npm update$ npm run test-page コマンドを実行し、変更内容を適用してください
    {
      "dependencies": {
      },
      "devDependencies": {
        "uupaa.nodemodule.js": "",
        "uupaa.reflection.js": "",
        "uupaa.iphonesimulator.js": "",
        "uupaa.console.js": "",
        "uupaa.valid.js":   "",
        "uupaa.help.js":    "",
        "uupaa.task.js":    "",
        "uupaa.test.js":    "",
        "uupaa.watch.js":   "",
        "uupaa.plato.js":   "",
        "uupaa.minify.js":  "",
        "uupaa.webmoduleutility.js": ""
      }
    }
  9. Edit tags

    • package.json の keywords に検索用のタグを追加できます
    • ユーザ名 と WebModule は消さないでください
    {
      "keywords": ["GITHUB_USER_NAME", "WebModule", "Unstable"],
    }

Directory entry

~/workspace/MyExample.js 以下のディレクトリ構成です

$ pwd
> ~/workspace/MyExample.js

$ tree
.
└── MyExample.js
    ├── bin/
    ├── lib/
    │  └── MyExample.js          <- モジュールのソースコードです
    ├── lint/
    │  └── plato/                <- npm run coverage コマンドが生成するファイルを格納するディレクトリです
    ├── release/                 <- npm run build コマンドが生成するファイルを格納するディレクトリです
    │  └── MyExample.min.js      <- npm run build コマンドが生成するMinifyされたソースコードです
    ├── test/                    <- npm run test  で実行するファイルを格納するディレクトリです
    │  ├── index.html            <- npm run test-page コマンドが生成するテストページです。Browser と WebWorkers のテストで使用します
    │  ├── index.node.js         <- npm run test-page コマンドが生成するテスト用のJavaScriptです。Node.js のテストで使用します
    │  └── test.js               <- テストロジックを記述するファイルです
    ├── .gitignore               <- git add, git push コマンドが参照する設定ファイルです
    ├── .npmignore               <- npm publish コマンドが参照する設定ファイルです
    ├── .jshintrc                <- npm run hint コマンドが参照する設定ファイルです
    ├── .travis.yml              <- Travis-Cl の設定ファイルです
    ├── index.js                 <- Node.js 用のエントリポイントです。require("MyExample.js") で読み込まれるファイルになります
    ├── package.json             <- npm の設定ファイルです
    ├── LICENSE
    └── README.md

Implement module

モジュールは以下を目安に実装してください

  • テストが可能なように実装してください
  • 1 モジュールに 1 クラスが基本ですが、WMCache.js のように複数のクラスを内包することも可能です
  • 1 クラスは 200〜400行程度の適切なボリュームで実装してください
  • 1 クラスにメソッドを10個以上持たせないでください。複雑すぎます
  • repositories にある WMFoo.js, WMCache.js, Task.js などを参考にしてください

Add test code

テストコードは ~/workspace/MyExample.js/test/test.js に記述します。

  • テストは、Test.jsTask.js を使用しています

  • テストコードの書き方は、 WMFoo.js などを参考にしてください

  • テストの設定を変更するには、test.js の new Test("MyExample", param) を修正してください

    var test = new Test("MyExample", {
            disable:    false,  // テストを無効化します
            browser:    true,   // Browser でテストします
            worker:     true,   // WebWorkers でテストします
            node:       true,   // Node.js でテストします
            button:     true,   // Browser のページに再テスト用のボタンを追加します
            both:       true,   // MyExample と MyExample_ の両方をテストします
                                // see https://github.com/uupaa/WebModule/wiki/SecondaryModulePattern
        }).add([
            testMyExample_value,
            testMyExample_isNumber,
            testMyExample_isInteger,
        ]);
    
    test.run().clone();
    

Change build target

package.json の x-build 以下を修正することで、ビルド対象の変更や、一緒にビルドするモジュールを指定できます。


Improve cycle

コード修正後は、以下のコマンドによるビルドとテストを行ってください。

$ vi lib/MyExample.js   # edit

$ npm run hint          # run jshint

$ npm run build         # debug build
$ npm run build-release # release build

$ npm run test          # run tests
$ npm run test-sim      # run test on iOS Simulator

$ npm run coverage      # run coverage tools

Build

npm run build コマンドを実行すると ./release/MyExample.min.js が生成されます。

  • ビルドに失敗した場合は、中間ファイル(./release/.Minify.tmp.js) を確認してください
  • ビルドには Minify.jsCompile.js を利用しています
  • npm run build 以外にも、npm build-simplenpm build-release が利用可能です。
    package.json の scripts を参照してください
  "scripts": {
    "build":        "node node_modules/uupaa.minify.js --verbose --strict --keep --pretty",
    "build-simple": "node node_modules/uupaa.minify.js --verbose --strict --keep --pretty --nowrap --simple",
    "build-release":"node node_modules/uupaa.minify.js --verbose --strict --module",
  },

Do test

npm run test コマンドでテストが始まります。

まずは、 ./test/index.node.js によるNode.js のテストが走り、成功した場合に ./test/index.html を使ったブラウザのテストが始まります。

  • テストは ./lib/MyExample.js に対して node →browser →worker の順番で行い、./release/MyExample.min.js に対しても同様にテストします
  • テスト成功でブラウザの画面が緑に、失敗で赤くなります
  • Closure Compiler による MyExample.min.js のコンパイルに失敗している場合も赤くなります
  • Closure Compiler の ADVANCED_OPTIMIZATIONS MODE で、重要な識別子やプロパティがリネームされている可能性があります
    • MyExample.min.js を DevTools 上で開き、Minify されているコードを展開({ }をクリック)します
  • リネームされたくない名前やプロパティは global.MyExample.hoge = 1; ではなく global["MyExample"]["hoge"] = 1; として保護してください。

Coverage

npm run coverage または npm run lint コマンドを実行すると、JSHint による静的解析と、Plato によるテストが行われ、結果をブラウザに表示します

  • lint erros をゼロにし、Average Maintainability は65点以上を目指して下さい。60点以下は赤点です
  • JSHint のチェックを緩和するには、 .jshintrc を修正してください
  • 問題が発覚した場合は、 npm run buildnpm run testnpm run coverage を繰り返し、動作をチェックしつつ修正します

Commit and publish

コードが公開可能なクオリティに達した事を確認できたら、GitHub への push と npm publish で世界にモジュールを公開しましょう。

  • Update patch version.

    • npm publish 後に ./lib/MyExample.js を修正した場合は、package.json の version も忘れずに修正します
    • npm run patch コマンドで package.json のパッチバージョンをインクリメントできます
      • version は、major.minor.patch バージョン(Semver)で構成されています。
      • API の動作変更など、下位互換性がなくなる修正の場合は、major を +1 します
      • bugfix など軽微な修正の場合は、patch を +1 します。
      • Semver については The semantic versioner for npm を参考にしてください
      • package.json の version を修正せずに、再度 npm publish するとエラーになります。
    $ npm run patch         # update patch version
    > update patch version. 0.0.0 -> 0.0.1
  • Commit と publish は以下のようにします

$ git add .
$ git status

> # On branch master
> # Changes to be committed:
> #   (use "git reset HEAD <file>..." to unstage)
> #
> #    new file:   .gitignore
> #    new file:   .jshintrc
> #    new file:   .npmignore
> #    new file:   LICENSE
> #    modified:   README.md
> #    new file:   index.js
> #    new file:   lib/MyExample.js
> #    new file:   package.json
> #    new file:   test/index.html
> #    new file:   test/index.node.js
> #    new file:   test/test.js

$ git commit -m "first commit"
$ git push
$ npm publish

Write Document

モジュールの作成が終わったら、GitHub/Wiki に Markdown でドキュメントを記述します。

open https://github.com/uupaa/MyExample.js/wiki/MyExample コマンドを実行するか、
open test/index.html でブラウザを開き DevTools のコンソールで MyExample.help ENTER とタイプします。

$ open https://github.com/uupaa/MyExample.js/wiki/MyExample

表示されたリンクから、 Reference: のリンクをクリックすると、GitHub の MyExample.js の wiki ページが生成されます。

新しく生成された wikiページに、API の説明を記述してください。

    # MyExample.js

    MyExample.js は、WebModule の機能を説明するためのダミーライブラリです。

    ## MyExample

    new MyExample(value:Number) は、MyExample クラスのインスタンスを生成します。  
    value には数値を指定します。

    ```js
    function MyExample(value) { // @arg Number: the valud.
        this._value = value;
    }
    ```


    ## MyExample.prototype.value

    MyExample#value():Number は、[MyExample](#MyExample) で渡された value を返します。

    ```js
    function MyExample_value() { // @ret Number:
        return this._value;
    }
    ```

    ## MyExample.prototype.isNumber

    MyExample#isNumber():Boolean は、[MyExample](#MyExample) で渡された value が Number 型なら true を返します。

    ```js
    function MyExample_isNumber() { // @ret Boolean:
        return typeof this._value === "number";
    }
    ```

    ## MyExample.prototype.isInteger

    MyExample#isInteger():Boolean は、[MyExample](#MyExample) で渡された value が Number 型で端数を持たない場合に true を返します。

    ```js
    function MyExample_isInteger() { // @ret Boolean:
        return typeof this._value === "number" &&
               Math.floor(this._value) === this._value;
    }
    ```

Clone this wiki locally