GitBook on Windows

GitBook の導入手順などをメモ。基本的なところはドキュメントに書いてありますが。

V2 changes - GitBook Documentation

前提

nodenpm のバージョンは以下の通り。

> node -v
v8.11.2
> npm -v
5.6.0

尚、手元の環境が Windows だからなのか、いろいろと思った通りに動作しないところがあります。が、GitHub の issue にワークアラウンドが載っています。一応、PR があるはずなんだけど、マージはされてないっぽい?開発があまり活発じゃないんだろうか...。

インストール

gitbook-cli をインストール。初回の gitbook 実行時にコマンドがインストールされます。

> npm install -g gitbook-cli
> gitbook --version
CLI version: 2.3.2
GitBook version: 3.2.3

プロジェクト作成

適当にプロジェクトフォルダを作成して初期化。

> mkdir sample
> cd sample
> gitbook init

プラグインインストール

今回は次のプラグインを使っています。

----- (2018/06/11 追記) -----
当初、gitbook-plugin-puml を使おうと思ってたのですが、gitbook-plugin-uml を使うことにしました。事前に以下の手順が必要になります。

  • Graphviz インストール
  • 環境変数 GRAPHVIZ_DOT を設定 (dot.exe ファイルのパスを設定する)

また、手元の環境では、gitbook-plugin-uml のインストールでコケるので、git config --global url."https://".insteadOf git:// を実施。(パッケージをインストールしたら戻すこと)
(参考) https://stackoverflow.com/questions/31744852/npm-install-giving-error-while-accessing-git-url
----- (追記ここまで) -----

まずは、npm パッケージをインストール。

> npm install gitbook-plugin-uml
> npm install gitbook-plugin-livereload

プロジェクトのルートに book.json を作成します。

{
  "plugins": [
    "-sharing",
    "uml",
    "livereload"
  ],
  "pluginsConfig": {
    "uml": {
      "charset" : "UTF-8"
    }
  }
}

プラグインインストール。

> gitbook install

ビルド

以下のコマンドでビルドします。プロジェクトのルートに _book が生成されるので、これを Web サーバーにデプロイします。

Windows 環境ではエラーになることがあります。ワークアラウンドは下記参照。

> gitbook build

ローカルで確認する場合は以下のコマンドを実行します。ローカルでサーバーが起動して localhost:4000 にアクセスすると画面が表示されます。また、ローカルでファイルを編集するとライブリロードされます。

Windows 環境ではエラーになることがあります。ワークアラウンドは下記参照。

> gitbook serve

PDF 出力

PDF 出力には ebook-convert というコマンドが使われるようです。このコマンドを使えるようにするには Calibre をインストールします。

calibre - Download for Windows

以下のコマンドで PDF を出力します。

> gitbook pdf ./ hoge.pdf

HTML / PDF のスタイルを変更する

book.json を編集します。

{
  "plugins": [
    "-sharing",
    "uml",
    "livereload"
  ],
  "pluginsConfig": {
    "uml": {
      "charset" : "UTF-8"
    }
  },
  "styles": {
    "website": "styles/website.css",
    "pdf": "styles/pdf.css"
  }
}

新しく css ファイルを作成して、カスタマイズするスタイルを定義します。HTML は Chrome の開発者ツールで class などを特定できますが、PDF のスタイルはちょっと分かり辛いかも。おそらく以下がオリジナルのファイルなのでこれを参考にする。

~/.gitbook/versions/3.2.3/node_modules/gitbook-plugin-theme-default/_assets/ebook/pdf.css


ワークアラウンドをまとめます。

gitbook servegitbook build でエラーになる場合

~/.gitbook/versions/3.2.3/lib/output/website/copyPluginAssets.js を以下のように編集します。

return fs.copyDir(
    assetsFolder,
    assetOutputFolder,
    {
        deleteFirst: false,
        overwrite: true,
        confirm: true // これを false に書き換える
    }
);

(参考) https://github.com/GitbookIO/gitbook/issues/1309#issuecomment-273584516

また、旧バージョンの gitbook ではエラーになりません。ただし、この方法だと検索機能が利用できなくなります。

旧バージョンをインストール。

> gitbook fetch 2.6.7
> gitbook -v 2.6.7

旧バージョンを指定してコマンドを実行。

> gitbook serve --gitbook=2.6.7
> gitbook build --gitbook=2.6.7

(参考) https://github.com/GitbookIO/gitbook/issues/1379#issuecomment-303628878

ライブリロードでエラーになる場合

Windows 環境ではライブリロード時にサーバーが停止することがあります。以下の手順で回避できます。

  1. gitbook serve を実行
  2. _book フォルダを削除する

以降、ファイル編集後、正常にサーバーが再起動してリロードされるようになります。

(参考) https://github.com/GitbookIO/gitbook/issues/1379#issuecomment-320579569

gitbook-plugin-puml で日本語が文字化ける場合

gitbook-plugin-puml で日本語を使うと文字化けして表示されます。これは、plantuml-encoder の 1.2.4 で修正されているようです。が、gitbook-plugin-puml の package.json が plantuml-encoder@1.2.3 になっています。(2018/06/08 時点では 1.2.5 が最新の模様)

(参考) https://github.com/markushedvall/plantuml-encoder/issues/4

<プロジェクトフォルダ>/node_modules/gitbook-plugin-puml/package.json を編集します。

"dependencies": {
  "plantuml-encoder": "1.2.3" // これを 1.2.5 に変更
},

<プロジェクトフォルダ>/node_modules/gitbook-plugin-puml/コマンドプロンプトを起動。

> npm install

これで gitbook build or gitbook serve すると正しく日本語が出力されるようになります。

Vue.js で ToDo アプリを作る

以前、PWA の学習を兼ねて、Firebase にデプロイしたアプリを PWA 化してみる計画を立てたのですが、対象のアプリがイマイチなので、その代わりに Vue.js で ToDo アプリを作りました。

今のところ ToDo のデータは LocalStorage に保存するようにしています。次回は Firebase Realtime Database に保存するようにしてみようかと。で、PWA のアプリとして Firebase にデプロイ。

ソースコードはこちら。

github.com


以下、備忘録。

環境構築

> vue init pwa todo-app
> cd todo-app
> npm install
> npm run dev

Vuex Plugins

ToDo データの永続化は Vuex の Plugins の仕組みを利用して、mutations に commit するタイミングで LocalStorage に保存する。

Vuex | プラグイン

あと、前からちょっと気になってたけど、actions に dispatch するタイミングでフックする仕組みはないだろうか...。

次にやること

Vuex の Plugins のところで、LocalStorage に保存しているところを Firebase Realtime Database を使うように差し替えられないか試してみる。

Vue.js アプリを Firebase にデプロイしてみる

Firebase を使ってみようと思います。ひとまず、以下の続編としてアプリを Firebase にデプロイしてみようかと。

Vue.js でウィジェットっぽいもの (仮) その2 - kntmr-blog

ソースコードはこちら。

github.com


以下、備忘録。

Firebase Console

Firebase Console でプロジェクトを作成する。「国/地域」には日本を選択する。

Project Overview から「ウェブアプリに Firebase を追加」をクリックしてコードスニペットをコピーする。

Firebase CLI

Firebase CLI をインストールする。

> npm -g install firebase-tools

ログインする。

> firebase logout
No need to logout, not logged in
> firebase login
? Allow Firebase to collect anonymous CLI usage and error reporting information? Yes # ブラウザが起動するのでログインする

Firebase

依存モジュールに Firebase を追加する。

> npm install firebase --save

src/main.js を編集。

import firebase from 'firebase'

// 上でコピーしたコードスニペットを記述する。
var config = {
  apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  authDomain: "APPNAME.firebaseapp.com",
  databaseURL: "https://APPNAME.firebaseio.com",
  projectId: "APPNAME",
  storageBucket: "APPNAME.appspot.com",
  messagingSenderId: "xxxxxxxxxxxx"
};
firebase.initializeApp(config);

ビルド & デプロイ

ビルドする。

> npm run build

Firebase プロジェクトとして初期化する。

> firebase init
? Are you ready to proceed? Yes
? Which Firebase CLI features do you want to setup for this folder? Press Space to select features, then Enter to confirm your choices. Hosting: Configure and deploy Firebase Hosting sites
? Select a default Firebase project for this directory: APPNAME # 既存のプロジェクトを選択
? What do you want to use as your public directory? dist # npm run build で dist に出力されるため、dist を指定する
? Configure as a single-page app (rewrite all urls to /index.html)? Yes
? File dist/index.html already exists. Overwrite? No # index.html は上書きしない

Firebase にデプロイする。

> firebase deploy
# Hosting URL: https://APPNAME.firebaseapp.com のURLにアクセス

これからやりたいこと

PWA の学習を兼ねて、Firebase にデプロイしたアプリを PWA 化してみる予定。

AWS導入ガイドセミナー2018年春編 〜クラウド移行のコツはポイントを押さえて効率よく〜 に行ってきた

先日、AWS導入ガイドセミナー2018年春編 〜クラウド移行のコツはポイントを押さえて効率よく〜 に行ってきました。簡単に所感をまとめます。

dev.classmethod.jp

所感など

各所で聞く話もありましたが、クラウドについては素人ということもあり、改めていろいろとクラウド移行のメリットを感じました。セキュリティについては、様々な要件に対応できるだけのサービスが予め用意されているところは心強いですね。あと、初期コストだけでなく、日々の管理やシステム更改などのことを考えれば、長期的に見てもコストのメリットがあるようです。

また、移行パターンについては初めて知ったのでとても参考になりました。移行パターンから検討するなら確かにクラウドベンダーと協業するのはありだなと思います。

ただ、当然のことではありますが、協業してクラウド周りをクラウドベンダーに丸投げしてると、短期的にはビジネスとして成立するかもしれませんが、既存ベンダーはいずれこの業界から淘汰されることになるんだろうなと...。

既存ベンダーもAWSのサービスを利用した案件を提案できるようにノウハウを身に付けていく必要があると感じています。IoT やビッグデータ、AI を活用するプラットフォームであるというような話もありましたし。

ひとまず、社内外問わず小規模でもいいので、AWSを導入して実績を積んでいかないとなぁ、と思う今日この頃です。


以下、メモから抜粋。

クラウドが変化させる今のIT・これからのIT

  • クラウドはコンピュータリソースを提供しているだけではない
    • 例えば、IoT, AI を使うためのインフラ
  • 金融業界、SMB (中小企業) などのお客様が使っている時代
  • オンプレ⇒クラウドに移行する理由
    • オンプレはシステム更改が必要になる
    • キャパシティプランニングの難しさ (リスクヘッジのため余分なリソースを購入している)
  • AWSは初期費用ゼロ、従量課金
    • AWSはどんどん値下げする (利益をユーザーに還元する文化)
    • ハードウェア費用、減価償却費は削減できる
    • 必要なときにすぐに使える (必要に応じてスケールアウト/スケールアップできる)
    • システム更改が不要なので、長期的に見てもコスト削減が見込める
  • いろいろな認証を取得して、セキュリティやコンプライアンスの要件を満たす
    • 「自社データセンターの方がリスクが高い」
    • クラウドベンダーはセキュリティに投資している (これがビジネスのキモと言っていい)
    • VPC, Direct Connect, アベイラビリティゾーン (データセンターレベルで冗長化している)
    • 大阪ローカルリージョン (災害対策向け、基本は東京リージョンを使う)
  • 日本法準拠、通貨、管理UIの日本語化 ⇒使い易い
  • パートナーコミュニティの充実
  • VMware Cloud on AWS
    • オンプレの VMware 環境をそのままAWSに移行できる
    • AWSサービスと組み合わせられる
  • IoT, ビッグデータ, AI は三位一体で動くもの
    • インターネット常時接続、構造化/非構造化データ、機会学習/ディープラーニング
    • S3をハブにしてデータを各サービスで活用する
    • AWSではデータを収集して付加価値を提供している

AWSを使うとき、ネットワークの検討、忘れてませんか?

  • 金融、医療、公共などの業界で使われるようになっている
  • 現在は基幹部分にもクラウドが活用され始めてる
  • セキュリティの確保が重要
  • ネットワークの検討はかなり後工程になっているのが実情
    • 現状分析⇒企画⇒設計のうち、設計あたりで検討している
  • AWSのネットワーク設定でハマる
    • BGPの設定 (やったことないひとは多い)
    • 閉域ネットワークを作るのは大変
    • AWS独特のルーティング仕様がある
    • AWS内のネットワーク設計の理解が必要
  • インターネット経由のAWS利用はセキュリティが心配
  • モバイル経由だと通信速度がネック
  • 専用線は納期、価格の面がネック
  • フートコネクト (CloudGateway)
    • NTT東では閉域ネットワークでサービスを提供する
    • フレッツ回線があれば素早くAWSに接続できる環境が準備できる
    • 今までの閉域ネットワークのサービスに比べれば安価である
    • AWSと閉域ネットワークを直接接続しているので高速

クラウドを使ってより効率的なセキュリティ対策を!抑えるべきポイントはココ

  • 物理的なセキュリティ機器はクラウドに持っていけない
  • 責任の共有モデル
  • セキュリティ規制/標準の準拠
    • 各セキュリティ要件に対応した各種AWSサービスが用意されている
    • ただし、AWSを使う側は設定する必要がある
  • ミドルウェアなどの脆弱性AWSを使う側が対応しないといけない
  • Deep Security (トレンドマイクロ)
    • ウィルス対策、Webレピュテーション (危険なWebサイトへのアクセスをブロック)
  • セキュリティの自動化 (不正アクセスの検知/遮断、ウィルス感染時の自動隔離/自動復旧)

クラウド移行のパートナー活用術 〜これがクラウド移行の現実解〜

  • クラスメソッドメンバーズ (導入、コンサル、支払などの代行)
  • 導入企業の広がり、ユースケースの広がり
  • 既存ベンダーに依頼するか or 内製するか or クラウド専業ベンダーに依頼するか
    • 既存ベンダーはクラウドの知見に対する不安がある
    • 内製はリソースが確保できないなどの不安がある
    • クラウドベンダーは既存業務の知識に対する不安がある
  • 移行パターン
    • オンプレの構成ではクラウドのよさを生かし切れない
    • システム刷新はシステムのライフサイクルに合わず余計なコストになる
  • 既存ベンダーとクラウドベンダーを組み合わせる
    • 多数のAWSサービスでいろいろ対応できる反面、専門家の支援が欲しい
    • インフラ、OS、アプリ、業務のスキルをすべて一社で賄うのは難しい
    • 適材適所でベンダーを使い分ける
  • 移行パターンに応じてベンダー同士で協業する
  • クラウドベンダーと協業する場合は初期段階から参画し、移行パターンから検討する

移行パターンについては以下の25ページあたりに書いてあります。

www.slideshare.net

その他、以下のあたりが参考になりそうです。

git rebase メモ

備忘録。基本的に svn を使うことが多いので、たまに Git を使うとコマンドを忘れている件...。

git rebase コマンドを実行する。-i HEAD~2 とすると直近2つのコミットが表示される。

> git rebase -i HEAD~2

そして、これを

pick <commit_hash> hogehoge
pick <commit_hash> fugafuga

こうする。

pick <commit_hash> hogehoge
f <commit_hash> fugafuga

fugafuga のコミットが hogehoge のコミットに統合される。実際はコミットをひとつにまとめた新しいコミットになると思われる。なので、新しいコミットには別のハッシュ値が割り当てられる。

ただし、未コミットの変更がある場合は rebase できない。変更を戻すか、git stash で一時的に退避させる。

JJUGナイトセミナー「Java SE 10 / JDK10 リリース特集」に行ってきた #jjug

先日、JJUGナイトセミナー「Java SE 10 / JDK10 リリース特集」に行ってきました。簡単に所感をまとめます。

jjug.doorkeeper.jp

メモから抜粋。(資料が公開されたら貼っておきます ⇒ 2018/03/29 追加しました)

JDKリリースモデル変更について

  • 5/17 Java Day Tokyo 2018
  • OpenJDK
    • 無償提供
    • GPLv2 + Classpath Exception
    • 6ヶ月単位でリリース
    • 3ヶ月単位でパッチリリース
  • Oracle JDK
    • 有償のみ
    • 1バージョン8年サポート (他のOracle製品同様)
    • 3ヶ月単位でパッチリリース
    • 3年間隔でリリース
    • 新しいリリースモデルに準拠するのは Java 11 以降
    • 9, 10 は OpenJDK のリリースモデルに準拠
  • ドキュメントは OpenJDK から提供される
  • Deprecated の運用ルールはそのまま (1年で削除される)

JDK10の追加機能解説 - JEP286/ローカル変数の型省略(var記法)を中心に

www.slideshare.net

  • JEP 286
  • ローカル変数の型推論
  • 初期化のときに型宣言を省略して読み易くする
  • ローカル変数は for ループ, for-each, try-with-resources を含む
  • ローカル変数の型推論 != 動的型付け
  • コンパイラの話でありランタイムレベルの話ではない
  • 従来のコードが簡潔に書けるようになる
  • 型が明確であれば読み辛くなることはないはず (もちろんすべてに当てはまるわけではない)
  • なぜローカル変数だけなのか
    • フィールドやメソッドの引数などの影響は複数のファイルにまたがるため
  • Denotable types
  • varが常に何らかの型でリプレースできるとは限らない
  • varは型の名前には利用できない (Varは大丈夫)
  • 変数名には利用できる
  • var var = new var();
  • 書き易さより読み易さ
  • ローカルコードで理解できることが大事 (どう動くか判断できること)
  • IDEなどのツールに依存するべきではない
  • 明示的に型を宣言するのはトレードオフ (すべてのローカル変数をvarにすることは避ける)

既存コードを一気に var に置換するとかは NG です。あと、原則やガイドラインは以下にまとまっています。とても重要。

orablogs-jp.blogspot.jp

個人的に興味深いのはこれ。これが問題になることはあまりないとは思いますが。

// ORIGINAL
List<String> list = new ArrayList<>();

// Inferred type of list is ArrayList<String>.
var list = new ArrayList<String>();

あと、おもしろかったのはこれ。

PriorityQueue<Item> itemQueue = new PriorityQueue<Item>();

// OK: both declare variables of type PriorityQueue<Item>
PriorityQueue<Item> itemQueue = new PriorityQueue<>();
var itemQueue = new PriorityQueue<Item>();

// DANGEROUS: infers as PriorityQueue<Object>
var itemQueue = new PriorityQueue<>();

// DANGEROUS: infers as List<Object>
var list = List.of();

var とダイアモンド演算子を併用すると Object として型推論される模様。後日、同僚と話してたんですが、var とダイアモンド演算子を併用するときはコンパイルエラーにするとか、IDE で警告出すとかしてもよさそうですねという話になりました。

もう1つおもしろかったのはこれ。

// ORIGINAL
byte flags = 0;
short mask = 0x7fff;
long base = 17;
 
// DANGEROUS: all infer as int
var flags = 0;
var mask = 0x7fff;
var base = 17;

たぶん32ビット以下の値が int として型推論される模様。

あと、きしださんのエントリ。

d.hatena.ne.jp

Java 10でぼくたちの生活は どうかわるの?

www.slideshare.net

  • Java XX で動かしてみる
  • Java XX でコンパイルしてみる
  • jdeps や jdeprscan で内部APIか非推奨APIを使ってないか確認する
    • jdeps : 依存関係を調べる
    • jdeprscan : 非推奨APIを使ってないか
  • Parallel Full GC は効果的だが、そもそも Full GC が頻発するような状況自体がよくない
  • LTS のバージョンごとにアップデートするといきなり削除されている API が出てくるかも
    • 基本的には @DeprecatedforRemoval=trueAPI が将来的に削除される
  • immutable コレクションの確認/作成を自前でやってるところは標準 APIcopyOf で置き換え推奨
  • RuntimeMXBean でプロセスIDが取得できる

Java 9, 10 は Java 11 サポートに向けて検証するために利用するのがよさそうとのこと。Java 8 から 9 を乗り越えるのが大変っぽい。それ以降はそれほど大きな壁はないはず。

Spring の @Validated と Bean Validation の javax.validation.groups.Default と groups について

実際の挙動がイメージとちょっと違うのでメモる。

パターン1

バリデーショングループのインタフェースで javax.validation.groups.Default を継承しないパターン。

interface Group {}

@NotNull
private String foo;
@NotNull(groups = Group.class)
private String bar;

Controller で @Validated とする場合、groups が未指定 or Default.class を指定したアノテーションのフィールドがバリデーション対象になる。ここでは foo のバリデーションが実行される。

一方、Controller で @Validated(Group.class) とする場合、Group.class を指定したアノテーションのフィールドがバリデーション対象になる。ここでは bar のバリデーションが実行される。

パターン2

バリデーショングループのインタフェースで javax.validation.groups.Default を継承するパターン。

interface Group extends Default {}

@NotNull
private String foo;
@NotNull(groups = Group.class)
private String bar;

Controller で @Validated とする場合、groups が未指定 or Default.class を指定したアノテーションのフィールドがバリデーション対象になる。ここでは foo のバリデーションが実行される。

一方、Controller で @Validated(Group.class) とする場合、Group.class を指定したアノテーションgroups が未指定 or Default.class を指定したアノテーションのフィールドがバリデーションの対象になる。ここでは foobar のバリデーションが実行される。

まとめ

当初、パターン2の挙動がイメージと違ってたんですが、こうやってまとめてみると別におかしくないですね...。Group インタフェースは Default インタフェースのサブインタフェースなので、is-a の関係になります。なので、パターン2において、Default を指定したときは Group.classアノテーションは対象外になるし、Group を指定したときは Default.classGroup.classアノテーションが対象になるのは当たり前ですね。