ぺーぺーSEのブログ

備忘録・メモ用サイト。

Express入門 〜express-generatorの使い方〜

Node.jsのWebフレームワーク Express ベースのアプリ雛形を作成するツール express-generator をさわってみた。
下記の記事を読んだテイで書く。

blog.pepese.com

express-generator のインストール

$ npm install -g express-generator
$ ndenv rehash # ndenvを使っている人は

RailsのScaffoldのように使用できる。

サンプルアプリの作成

以下の順で記載する。

  • express-generatorの使い方
  • express-generatorで雛形作成
  • ディレクトリ構造
  • 実行と確認
  • コードを見てみる

express-generatorの使い方

$ express --help

  Usage: express [options] [dir]

  Options:

    -h, --help           output usage information
        --version        output the version number
    -e, --ejs            add ejs engine support
        --pug            add pug engine support
        --hbs            add handlebars engine support
    -H, --hogan          add hogan.js engine support
    -v, --view <engine>  add view <engine> support (ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade)
    -c, --css <engine>   add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain css)
        --git            add .gitignore
    -f, --force          force on non-empty directory

express-generatorで雛形作成

ExpressのデフォルトのView Template Engine は Jade だが、 Jadeは Pug にリネームされた。
今後、ExpressのデフォルトのView Template EngineはPugに置き換えられるため、ここでは Pug を使用する。
また、ここではCSSメタ言語としてSASSを使用する。

$ express express-generator-sample --view=pug --css=sass --git

   create : express-generator-sample
   create : express-generator-sample/package.json
   create : express-generator-sample/app.js
   create : express-generator-sample/.gitignore
   create : express-generator-sample/public
   create : express-generator-sample/routes
   create : express-generator-sample/routes/index.js
   create : express-generator-sample/routes/users.js
   create : express-generator-sample/views
   create : express-generator-sample/views/index.pug
   create : express-generator-sample/views/layout.pug
   create : express-generator-sample/views/error.pug
   create : express-generator-sample/bin
   create : express-generator-sample/bin/www
   create : express-generator-sample/public/javascripts
   create : express-generator-sample/public/images
   create : express-generator-sample/public/stylesheets
   create : express-generator-sample/public/stylesheets/style.sass

   install dependencies:
     $ cd express-generator-sample && npm install

   run the app:
     $ DEBUG=express-generator-sample:* npm start

$ cd express-generator-sample/
$ npm install

express <プロジェクト名> コマンドでExpressの雛形プロジェクトが作成される。
npmのpackage.jsonが作成されているので「npm install」でモジュールをインストールする。
npm start コマンド(package.jsonにて定義)で node ./bin/www が実行され、サービスが起動する。
「./bin/www」には、Express.jsでHTTPサービス(3000番ポート)が起動するJavaScriptがコーディングされており、「app.js」に記述されたサービスが実行される。

ディレクトリ構造

$ tree
.
├── app.js           # メインJavaScript
├── bin/             # サービス起動JavaScript(www)置き場
├── node_modules/    # npmモジュール置き場
├── package.json
├── public/          # 公開ディレクトリ
│   ├── images/
│   ├── javascripts/
│   └── stylesheets/
│       └── style.sass
├── routes/          # ルーティング先のスクリプト置き場(MVCのCとロジックに相当)
│   ├── index.js
│   └── users.js
└── views/           # View用のコード置き場(MVCのVに相当)
    ├── error.pug
    ├── index.pug
    └── layout.pug

実行と確認

# 実行
$ npm start
# 確認
$ curl localhost:3000
<!DOCTYPE html><html><head><title>Express</title><link rel="stylesheet" href="/stylesheets/style.css"></head><body><h1>Express</h1><p>Welcome to Express</p></body></html>

$ curl localhost:3000/users
respond with a resource

コードを見てみる

app.js

  • 各種ライブラリのロード( var xxx = require('xxx');
  • ルーティング先コントローラ層ロジックのロード( var xxx = require('./routes/xxx');
  • Express本体オブジェクトの作成と設定( var app = express();
    • View Template Engine( Pug ) の設定
    • ロガー、パーサー、公開ディレクトリの設定
    • ルーティン部先ロジックの設定( app.use('/xxx', xxx);
    • エラーハンドリングの設定

index.js

users.js

style.sass

Node.js(npm)入門

本記事は移転しました。

約3秒後にリダイレクトします。

リダイレクトしない場合はここをクリックしてください。

Spring BootでJUnitテスト

Spring Bootのテストについて書く。
spring-boot-starter-testを使用するとコントローラのJUnitテストも可能になる。
テストやコードインスペクションレポートのMaven設定は以下を参照。

blog.pepese.com

テスト対象アプリ

以下の記事で紹介した入門アプリをテスト対象とする。

blog.pepese.com

テストの作成

以下を作成する。

  • com.pepese.sample.service.HelloServiceTest
    • コントローラへDIされるサービスクラスのテスト
  • com.pepese.sample.controller.HelloControllerTest
    • コントローラのテスト

サービスのテスト(com.pepese.sample.service.HelloServiceTest)

ポイントは以下。

  • @RunWith(SpringRunner.class) アノテーション
    • Spring BootでJUnitテストするときはコレをつける
  • @SpringBootTest アノテーション
    • SpringのJava/XML Based Configurationなどの設定を読み込んでくれる

Springの設定(Java/XML Based Configuration)を読み込んでいるのでDIでテスト対象のインスタンスを取得できる。

コントローラのテスト(com.pepese.sample.controller.HelloControllerTest)

ポイントは以下。

  • @AutoConfigureMockMvc アノテーションをつけるとコントローラ層のモック( MockMvc )を作成でき、これでコントローラのJUnitテストが可能になる
    • @WebMvcTest(HelloController.class) としてコントローラクラスを指定することもできる
  • @MockBean でコントローラ内でDIされるモジュールのモック(Mockito)を作成できる
  • when メソッド等(Mockito)を使用してコントローラ内にDIされたモジュールの挙動を指定できる
  • HamcrestのMatchersを使用してassertする

テストの実行

基本的には mvn test で実行可能だが、特定のクラスを指定してテストしたい場合は mvn clean test -Dtest=*.HelloControllerTest のように指定して実行できる(正規表現の指定可能)。
また、 mvn clean test -Dtest=*.HelloControllerTest,*HelloServiceTest のようにカンマ区切りで複数指定することもできる。

webpack + Babel 入門

webpack + Babel で ES6(ECMAScript 2015)をトランスパイルしてブラウザで動くまでをまとめる。
以降を記載する。

  • サンプルが動くまで
    • サンプルが動くまでの手順
  • 説明
    • 上記の手順の説明

サンプルが動くまで

ブラウザに「Hello World !」とポップアップが出るサンプルを作成する。

前提

$ npm -v
4.0.2

プロジェクトの作成

$ mkdir es6-sample
$ cd es6-sample
$ npm init -y
$ npm install --save-dev \
      webpack \
      babel-cli \
      babel-core \
      babel-preset-env \
      babel-preset-es2015 \
      babel-polyfill \
      babel-loader \
      webpack-dev-server
$ mkdir src; touch src/app.js
$ mkdir dist; touch dist/index.html
$ touch webpack.config.js
$ touch .babelrc

トランスパイル後のディレクトリ構造は以下のようになる。

$ tree -a -I 'node_modules'
.
├── .babelrc
├── dist
│   ├── app.bundle.js
│   ├── app.bundle.js.map
│   └── index.html
├── package.json
├── src
│   └── app.js
└── webpack.config.js

以降、各ファイルの内容を記載する。

package.json

npm run build でES6のトランスパイル、npm run start で簡易Webサーバが起動する。

.babelrc

ここでトランスパイル対象の種類を指定する。

webpack.config.js

webpackの設定ファイル。
npm run build でES6のトランスパイル、npm run start で簡易Webサーバが起動するように package.json にスクリプトを設定している。

index.html

トランスパイル後のJSコードをロードしている。

app.js

実行方法

  1. npm run build でトランスパイル
  2. npm run start で簡易Webサーバの起動
  3. http://localhost:8080/webpack-dev-server/ へブラウザでアクセス
  4. 「Hello World !」とポップアップが出れば成功

説明

Babelのインストール

npm install --save-dev babel babel-preset-es2015

babel はトランスパイラだが、これだけだとまだ何をトランスパイルするのか分からない。
babel-preset-es2015 を入れるとES6をトランスパイルできるようになる。
Babelは .babelrc というファイルがあると、その設定を読み込んでくれる。

Babel6での変更?

Babel5からBabel6で babelbabel-corebabel-cli に分割された模様。
CLIを使用しないのであれば、 babel-core だけでいい。

.babelrc

トラインスパイルする内容を指定する場合、以下のように プリセット(presets) を指定する。

{
  "presets": [es2015", "react"]
}

babel-preset-2015babel-preset-react を使用する場合は上記のように指定する。

Polyfill

$ npm install --save-dev babel-polyfill

Babelでトランスパイルすると古いブラウザでも動作する Javascript(ES5) を出力するが、古いブラウザのブラウザオブジェクトの中には標準オブジェクト(ES6で記述できるブラウザオブジェクトの扱い方)に対応していないものがある。
babel-polyfill を利用すると、古いブラウザでも動くように標準オブジェクトを拡張してくれる。
ちなみに、古いブラウザーに欠けている部分、新しいブラウザーでも足りない機能の穴を埋めることを、 ポリフィル (polyfill) という。

標準オブジェクトを拡張すると、既存の環境と互換性を失うことになるため、別ライブラリ babel-polyfill に分かれている。

babel-polyfill の他に babel-runtime というのがある。
babel-polyfill が標準オブジェクトを拡張するのに対して、 babel-runtime は標準オブジェクトの対応していない機能を、その場で別のコードにトランスパイルして解決する。
babel-polyfill を導入しているほうが多そうな肌感。

その他のBabelプラグイン

  • babel-preset-env
    • compat-tableを用いて、サポートされている環境に基づいて必要なBabelプラグインを自動で決定するライブラリ
  • babel-loader
    • webpackからbabelを使用できるようにするやつ
  • babel-preset-react
    • Reactをトランスパイルするプリセット
  • babel-preset-stage-0
    • ECMAScriptのステージを指定できる
    • ステージについては後述
  • bable-register
    • 通常のwebpackの設定ファイルは webpack.config.js というファイルだが、 webpack.config.babel.js というファイル名でES6で書けるようになる

ステージ(stage)

BabelはECMAScript2015 (ES6), ECMAScript7をECMAScript5に変換するが、ECMAScript2015 (ES6), ECMAScript7の仕様でもまだ議論中のものもある。
そこで、ECMAScriptの中でもまだ議論しきれていない仕様に関しては、stageという概念を使って安定度を示している。
初期値は2が指定されており、Draft版のものが使用できる。
基本的には初期値で問題無いが、それ以上のものを使いたい場合はリスクを加味して使用すること。
ステージは以下がある。

stage description
0 Strawman - アイデア
1 Proposal - 提案
2 Draft - ドラフト
3 Candidate- 仕様書と同じ形式
4 Finished - 策定完了

sourceMaps

トラインスパイル前後のコードをマッピングする。
デバッグなどする際、エラー箇所がトランスパイル前のコードのどこに対応するのかがわかるようになる。

webpack

webpackは、複数のファイルの依存関係を顧慮してビルドを行うツール。
設定ファイルは webpack.config.js

  • entry でトランスパイル対象を指定して、output で出力先を指定する。
  • Loaderという仕組みがあり、これでES6やReactをコンパイルできる。
  • Pluginという仕組みがあり、これでUglifyなど圧縮処理などができる。PluginはLoaderの前後で実行される。
  • WebpackDevServerという確認用簡易Webサーバがある。

Sublime Text 3のインストールとパッケージの導入

インストール

公式から「portable version」を入手して展開するだけ。
(Windowsではportable versionでないとプロキシ環境下で何故か動かなかった)
MacユーザはHomebrewを使用して以下のようにインストール。

$ brew cask install sublime-text

Homebrewについては以下を参照。

blog.pepese.com

起動方法

アイコンクリックでもいいがコマンドラインで起動できる。

$ subl file

プロジェクト(カレントディレクトリ)で起動したい場合は以下。

$ subl .

Package Controlのインストール

パッケージの検索・インストールを簡単にしてくれる。
「View」→「Show Console」からコンソールを起動。
下記を実行。

import urllib.request,os,hashlib; h = 'df21e130d211cfc94d9b0905775a7c0f' + '1e3d39e33b79698005270310898eea76'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); by = urllib.request.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); print('Error validating download (got %s instead of %s), please try manual install' % (dh, h)) if dh != h else open(os.path.join( ipp, pf), 'wb' ).write(by)

プロキシ環境の場合は下記を実行。

import urllib.request,os,hashlib; h = 'df21e130d211cfc94d9b0905775a7c0f' + '1e3d39e33b79698005270310898eea76'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler({"http": "http://[username]:[password]@[proxy_server]:[port]", "https": "https://[username]:[password]@[proxy_server]:[port]"})) ); by = urllib.request.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); print('Error validating download (got %s instead of %s), please try manual install' % (dh, h)) if dh != h else open(os.path.join( ipp, pf), 'wb' ).write(by)

「[username]:[password]@[proxy_server]:[port]」の箇所はプロキシ環境に合わせて書き換える。
また、最新のインストールコマンドは公式を参照。
 
その他、以降のオペレーションなどでプロキシ関係でうまくいかないときは、

  • 「Preferences」→「Package Settings」→「Package Controll」→「Settings-User」

を選択して、 Package Control.sublime-settings ファイルを開き、編集する。

{
  "http_proxy": "プロキシサーバのアドレス:ポート番号",
  "https_proxy": "プロキシサーバのアドレス:ポート番号",
  "proxy_username": "プロキシのユーザ名",
  "proxy_password": "プロキスのパスワード"
}

その他設定はここを参照。(※プロキシの設定とか)

日本語化

Japanize というパッケージを導入する。

  • 「Preferences」→「Package Control」を選択( Command + Shift + P
  • 「Package Control: Install Package」を選択
  • 「Japanize」を選択
  • 「Package Control Message」の内容に従う

Macユーザは以下の手順で。

  1. ~/Library/Application Support/Sublime Text 3/Packages/Japanize にインストールされている*.jpファイルを、以下にコピー。
  2. ~/Library/Application Support/Sublime Text 3/Packages/Default
  3. Defaultフォルダがない場合は自分で作成
  4. コピーしたファイルをオリジナルのファイル(.jpが付かないファイル)と置き換える。
  5. ~/Library/Application Support/Sublime Text 3/Packages/Japanize/Main.sublime-menu(.jpが付かない方)を、以下にコピー。
  6. ~/Library/Application Support/Sublime Text 3/Packages/User
  7. すると、他のプラグインで上書きされてしまっているトップメニューも日本語化される。

カスタマイズ

テーマの変更

  • 「Package Control: Install Package」で使用したいテーマを検索してインストール
  • 「Preferences」→「Settings」を選択して Preferences.sublime-settingsーUser ファイルを開く
  • 設定ファイルに各テーマ用のコードを記述・保存

ググって好きなテーマを探す。
筆者はMaterial Themeをインストールして以下の設定を行った。

{
  "theme": "Material-Theme-Darker.sublime-theme",
  "color_scheme": "Packages/Material Theme/schemes/Material-Theme-Darker.tmTheme"
}

インデントの変更

  • 「Preferences」→「Settings - User」を選択して設定ファイルを開く
  • 「"tab_size": 2」(タブサイズが2)を追記
  • 「"translate_tabs_to_spaces": true」(タブをスペースに変換)を追記して保存

その他

基本には

  • 「Package Control: Install Package」( Command + Shift + P してInstall Package)
  • 好きなパッケージを入力・インストール

でパッケージをインストールできる。
プログラマな人は下記のパッケージ辺りを入れておくといいかも。

  • AdvancedNewFile
    • Option + Command + N で新規ファイルを作成できる
  • All Autocomplete
    • コード補完を補強するパッケージ
  • SublimeLinter
    • 下記の「SublimeLinter-XX」を使うためのフレームワーク
  • SublimeLinter-XX
    • リアルタイムに構文チェック
    • XXの部分に任意の文字が入っていろんな種類がある
  • BracketHighlighter
    • []、()、{}、””、”、などの開始、終了をハイライトしてくれるパッケージ
  • GitGutter
    • Git管理してるファイルを編集すると「+ -」で行番号のとこに表示
  • SideBarEnhancements
    • サイドバーのファイル/フォルダ操作を拡張
  • ConvertToUTF8
    • UTF-8以外の文字コードのファイルをUTF-8にしてくれる
  • SublimeCodeIntel
    • 補完機能を強化、Tabによるコード補完補完
  • BoundKeys
    • 複雑になったショートカットキーを確認できるパッケージ

便利機能

  • ショートカット
  • スニペット
    • 少しのキーボード入力をトリガーとして、よく利用するコードなどを手軽に書き込むことができる機能
  • キーバインド
  • [画面分割]
    • Alt + Shift + N で好きな画面の個数に分割できる。(Nは好きな数)
    • 変則的に分割したい場合はここ

Spring MVC入門

Spring MVCで最小アプリケーションが動くまでの設定についてまとめる。
以下の2種類で同じアプリを実装する。

  • Java Based Configuration
  • XML Based Configuration

上記は両方HTTP GETするとHelloが返ってくる簡単たRESTアプリ。
Spring BOM 2.0.8.RELEASEで動確した。

Java Based Configuration

以下を作成する。

  • pom.xml
  • src/main/java/com/pepese/sample/config/AppConfig.java
    • Spring設定クラス
      • DIやAOPなどの設定に使用する
    • @Configuration アノテーションを付与すること
    • 必要に応じて@ComponentScanを指定してコンポーネントスキャン領域を指定すること
  • src/main/java/com/pepese/sample/config/WebMvcConfig.java
    • Spring MVC設定クラス
      • コンテンツネゴシエーションなどSpring MVCのDispatcherServletに関する設定に使用する
    • WebMvcConfigurerAdapter が継承されていること
    • @Configuration アノテーションを付与すること
    • @EnableWebMvc アノテーションを付与すること
  • src/main/java/com/pepese/sample/config/WebInitializer.java
    • web.xmlのJava Based Configuration
    • AbstractAnnotationConfigDispatcherServletInitializerを継承すること
      • WebApplicationInitializerの実装クラス
  • src/main/java/com/pepese/sample/controller/HelloController.java
    • 動作確認用のコントローラクラス
  • src/main/java/com/pepese/sample/service/HelloService.java
    • DIなどの動作確認用のサービスクラス

pom.xml

AppConfig.java

WebMvcConfig.java

WebInitializer.java

HelloController.java

HelloService.java

mvn clean package してTomcatにデプロイすれば動く。

XML Based Configuration

以下を作成する。Java Based Configurationと異なるファイルだけ記載する。
以下は不要になるファイル。

  • src/main/java/com/pepese/sample/config/AppConfig.java
  • src/main/java/com/pepese/sample/config/WebMvcConfig.java
  • src/main/java/com/pepese/sample/config/WebInitializer.java

以下は追加するファイル。

  • src/main/resources/META-INF/spring/applicationContext.xml
  • src/main/resources/META-INF/spring/spring-mvc.xml
  • src/main/webapp/WEB-INF/web.xml

applicationContext.xml

spring-mvc.xml

web.xml

mvn clean package してTomcatにデプロイすれば動く。

Spring Boot入門

Spring Bootで最小アプリケーションが動くまでの設定についてまとめる。
以下の2種類について記載する。

  • Spring Bootで実行可能jarの作成
  • Spring BootでAPサーバにデプロイ可能なwarの作成

上記は両方HTTP GETするとHelloが返ってくる簡単たRESTアプリ。

Spring Bootで実行可能jarの作成

以下を作成する。

  • pom.xml
    • Maven設定ファイル/POM
    • POMのdependencyに spring-boot-starter-* が含まれること
    • POMのbuild -> pluginsに spring-boot-maven-plugin が含まれること
      • mvn package 実行時に適切に実行可能jarを作成してくれる
  • src/main/java/com/pepese/sample/Application.java
    • Spring Bootアプリケーション起動クラス
    • @SpringBootApplication アノテーションを付与すること
      • @Configuration@EnableAutoConfiguration@ComponentScan をまとめたもの
  • src/main/java/com/pepese/sample/config/AppConfig.java
    • Spring設定クラス
      • DIやAOPなどの設定に使用する
    • @Configuration アノテーションを付与すること
  • src/main/java/com/pepese/sample/config/WebMvcConfig.java
    • Spring MVC設定クラス
      • コンテンツネゴシエーションなどSpring MVCのDispatcherServletに関する設定に使用する
    • WebMvcConfigurerAdapter が継承されていること
    • @Configuration アノテーションを付与すること
    • Spring Bootの場合、 @EnableWebMvc を付与する必要はない
      • Spring Bootを利用しないSpring MVCアプリケーションを作成する場合には付与する
  • src/main/java/com/pepese/sample/controller/HelloController.java
    • 動作確認用のコントローラクラス
  • src/main/java/com/pepese/sample/service/HelloService.java
    • DIなどの動作確認用のサービスクラス

pom.xml

Application.java

AppConfig.java

WebMvcConfig.java

HelloController.java

HelloService.java

実行

以下の2通り。

  • mvn spring-boot:runで実行してhttp://localhost:8080/へアクセス
  • mvn packageでビルドしてjava -jar target/springboot-sample-jar-0.0.1-SNAPSHOT.jarで実行してhttp://localhost:8080/へアクセス

Spring BootでAPサーバにデプロイ可能なwarの作成

意味あんの?なツッコミは無しで。
準備されたTomcatにデプロイしないといけないルールなプロジェクトは存在するんです。
以下を作成する。「Spring Bootで実行可能jarの作成」と異なるファイルだけ記載する。

  • pom.xml (変更)
    • Maven設定ファイル/POM
    • POMのdependencyに spring-boot-starter-* が含まれること
    • POMのbuild -> pluginsに spring-boot-maven-plugin が含まれること
      • mvn package 実行時に適切にデプロイ可能warを作成してくれる
    • POMのpackagingをwarにすること
    • POMのspring-boot-starter-tomcatの組み込み系APサーバのscopeをprovidedにすること
      • tomcatに限らずjetty等組み込み系APサーバは全て
  • src/main/java/com/pepese/sample/ServletInitializer.java (追加)
    • web.xmlのSpring Boot版
    • SpringBootServletInitializerが継承されていること
      • web.xmlのSpring MVC版である WebApplicationInitializer を継承している
    • configure メソッドをオーバーライドし、Spring Bootアプリケーション起動クラスをロードすること

pom.xml

ServletInitializer.java

実行

以下の2通り。

  • mvn spring-boot:runで実行してhttp://localhost:8080/へアクセス
  • mvn packageでビルドしてできたwarをTomcatにデプロイしてhttp://localhost:8080/springboot-sample-war/へアクセス
    • コンテキストパスは自分で調整して

補足

SpringBootServletInitializer はSpring Bootの起動クラスに継承して作成してもよい。下記の通り。

package com.pepese.sample;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }
}