webpackを試してみた[JavaScript][webpack][超入門]
今回はjsを触っていて「requireとかってどうやってやるんだろう」とか「依存関係とかってどういう風に付き合っていくんだろう」と思って調べてみたらwebpackに行き着いたので、とりあえず使ってみたメモとして。
よく並んで耳にする Browserify
や RequireJS
との比較は今回は行いませんmm (webpackが初めてなので!mm)
とりあえずwebpackが最後発というのはわかった。
webpackとは
JavaScript用のモジュール管理ツールです。
リソースの依存関係を解決して、複数ファイルをまとめたファイルを生成することができます。
コンパイルができるイメージでしょうか。
jsだけでなく、cssや画像なども扱う事が可能なようです。
Symfony2を使っているので話を出すと、Symfony2でいうところのassets的な感じですかね〜。
なんとなく便利そうなのはわかったので使ってみる
インストール
簡単インストール。
npm install webpack --save-dev
チュートリアル
公式のやつをなぞって試してみます。
webpackの超基本的な使い方
jsファイルとしてentry.js
を、htmlファイルとしてindex.html
をそれぞれ作成します。
entry.js
document.write("It works.");
index.html
<html> <head> <meta charset="utf-8"> </head> <body> <script type="text/javascript" src="bundle.js" charset="utf-8"></script> </body> </html>
html内でbundle.js
というファイルが読み込まれていますね。知らない子ですね。
このbundle.js
がwebpackを用いてビルドされたjsファイルとなります。実際にビルドしてみましょう。
ビルド
webpack ./entry.js bundle.js
bundle.jsが生成されました!この状態でindex.htmlをブラウザで見てみると...?
おぉ〜。It works.
の文字。いい話。
これでentry.js
以外にもファイルが増えたとてbundle.js
を読み込んでいれば勝手に反映されそうなので変更が楽で良さそうですね。
以上でとりあえずのwebpackの使い方はわかりました。
entry.jsが依存しているファイルを増やしてみる
依存解決を試してみましょう。
content.js
を追加し、それを entry.js
内で読み込むようにしてみます。
content.js
module.exports = "It works from content.js.";
entry.js
document.write(require("./content.js"));
ビルド
webpack ./entry.js bundle.js
index.html
を見てみると...?
おぉ〜なるほど。ちゃんとcontent.js
で書かれた内容が表示されていますね。
依存関係をよしなに解決して動作させてくれています。素晴らしい!
ローダーを使ってみる
ローダー
webpackは、ローダーを追加してあげることで、jsの他にもcssなど、様々なファイルをビルド対象に取ることができます。
このローダーを使う例として、cssファイルをビルドに含めるようにしてみましょう。
ローダーの追加
ローダーの使い方一歩目
npm install css-loader style-loader --save-dev
cssを読み込むために必要なcss-loader
と、cssをスタイルに適用するためのstyle-loader
の2つをインストールします。
先ほどの例を、cssを用いるように変更してみましょう。
style.css
body { background: yellow; }
entry.js
require("!style!css!./style.css"); document.write(require("./content.js"));
このように、ローダーを用いるときは!
区切りで記述をします。
style
がstyle-loader
を、css
がcss-loader
を表しています。
もちろんstyle-loader
のようにフルネームで書いても大丈夫です。
ローダーを紐付けてビルドする
ビルド時にファイルの拡張子とローダーを紐付けることもできます。
webpack ./entry.js bundle.js --module-bind "css=style\!css"
この場合は読み込み時の記述は以下の様で大丈夫です。
entry.js
require("./style.css"); document.write(require("./content.js"));
コンフィグファイルを用いる
設定ファイルを用いてビルドすることもできます。
設定ファイルにはビルド対象のファイル(entry.js
)や、出力先のファイル(bundle.js
)だったり、ローダーのような設定を記述することもできます。
webpack.config.js
module.exports = { entry: "./entry.js", output: { path: __dirname, filename: "bundle.js" }, module: { loaders: [ { test: /\.css$/, loader: "style!css" } ] } };
設定ファイルを記述した場合は、ビルド実行はwebpack
だけでOKです。
webpack
ファイル変更を検知して自動ビルドする
webpackのビルド時に --watch
オプションを付けることで変更された時に自動的に再ビルドが走るようにもできます。
webpack --watch
このようにとても簡単にjsをビルドしながら操れるようになりました。これはハッピーになれそうですね!
導入までしんどい事がないので積極的に使っていこうとおもいます。
参考
今回のチュートリアルで触れた部分のコードはこちら。
npm installでローカルインストールしたライブラリのコマンドを使えるようにする[npm][JavaScript]
npmでライブラリをインストールするときに、-g
をつけずにインストールをするとnode_modules
下にインストールしたライブラリが入ります。
そのときにライブラリ側が提供しているコマンドを実行しようとした時、例えばwebpack
だと
./node_modules/webpack/bin/webpack.js
みたいなところを実行しなくてはいけないのかな〜辛いな〜と思っていたらそんなことなく解消出来たのでメモ。
話は簡単で、実は./node_modules/.bin/
というディレクトリ下に実行可能なコマンドは入っているので、そこにパスでも通してあげればグローバルに入れた時と変わらずコマンド実行できるようになりました。
export PATH=$PATH:./node_modules/.bin
とでもすれば解決できました。めでたしめでたし。
体調[自戒]
久々に体調を崩してしまったしちょっと良くなったと思ってアクティブに動いたらぶり返してしまって先週は散々だった。
体調微妙になったらとっとと会社休んで寝ろ。その方が結果的に時間短縮して復活出来るぞ。
今週は頑張るぞい(˘ω˘)
Vue.jsに入門してみた[JavaScript][Vue.js]
ちょっときっかけがあってVue.jsを初めてお勉強してみたので勉強メモ。 JS界隈、全体的に疎さがあるので、関連用語の説明も加えつつ書いてみます。
Vue.jsとは
Vue.js はインタラクティブな Web インターフェイスを作るためのライブラリ。 MVVMパターンのViewModelレイヤに注目していて、ViewとModelを双方向バインディングによって接続しています。
特徴
Vue.jsはざっと以下のような特徴があります。
公式ドキュメントも全て日本語化されていて、ありがたやといったところでした。 公式ドキュメントの物量としてもざっと読むだけなら全然1日かからないくらいだったので本当学習コストは低めだなぁと感じました。
MVVMパターンとは
MVVMパターンとは、Model/View/ViewModelの3つの責務にGUIアプリケーションを分割するパターンのことです。
その中でVue.jsはViewModelレイヤを担っていますよっていうところですね。
Vue.js公式からもってきている画像ですが、すごい関係がスッキリまとまっていて良いです。
双方向バインディングとは
双方向データバインディングとは、データの変更があったらUIの表示を更新し、UIの変更があったらデータの更新する、といった処理を自動的に行う機能を指します。
これができているとViewで表示される内容とModel内で処理されている内容が同期がとれて良いですね。
Vue.jsはこの双方向データバインディングをシンプルに行うことに重点を置いています。
インストール
インストール方法は公式ドキュメントにお任せしますmm
Vue.jsの提供する機能
Vue.jsとしてのまず押さえる必要のある機能は大まかには以下に並べるくらいです。
以下のサンプルに沿って必要知識をまとめようかと思います。
インスタンスプロパティ
基本中の基本としてはel
とdata
が挙げられます。
el
Vueインスタンスが管理する対象のDOM要素です。 View部分の担当です。
data
Vue インスタンスが監視しているデータオブジェクトです。 Model部分の担当です。
ざっくりとした図ですが、赤枠がel
関連、青枠がdata
関連です。
el
で監視対象を指定して、その監視範囲に対してdata
を用いてほげほげする感じですね。
このようにhtmlはあくまでフレームとして用いて、実データの方はjsの方に持たせるといった分担が綺麗にできるようになりスッキリしますね。
他にも何種類かインスタンスプロパティは用意されているのでご参考くださいmm
ディレクティブ
ディレクティブとは、DOM 要素に対して何かを実行することをライブラリに伝達する、マークアップ中の特別なトークンです。
Vue.jsを触るようになるとよくよく目にするようになります。
赤枠がディレクティブ、青枠がそのディレクティブが対象とするdata等が入ってきます。
青枠のところは用いるディレクティブによって色々変わってきます。
例えば、 v-on
ディレクティブはclick:
から始まりますが、これはv-on
ディレクトリ固有のものになっていたりします。
APIリファレンスをよく読んで正しく使うようにしましょう。
ディレクティブは、大きく以下の4種類に分類されます。
- リアクティブディレクティブ
- リテラルディレクティブ
- エンプティディレクティブ
- カスタムディレクティブ
リアクティブディレクティブ
リアクティブディレクティブは、それ自身を Vue インスタンスのプロパティやインスタンスの文脈の中で評価される表現にバインドすることができます。 配下のプロパティや表現の値が変更されたら、それらのディレクティブの update() 関数が同期的に呼ばれます。
リテラルディレクティブ
リテラルディレクティブは、データバインディングを生成せず、単に文字列リテラルを属性値として取ります。 その要素の値を素の文字列として取り扱い、何ともバインドしようとしません。 このディレクティブが行うのは、文字列の値を bind() 関数に渡して実行することだけです。 リテラルディレクティブはその値の中で Mustache 表現を使用できますが、それらの表現は最初のコンパイルの際に一度だけ評価され、データの変更に対して反応しません。
エンプティディレクティブ
エンプティディレクティブは、属性値すら期待せず、単純にその要素に何かを一度きり行います。
このように色々なディレクティブがあるので、詳細は以下のAPIリファレンスをご参照の事。 恐らくこのリファレンスに頻繁にお世話になりながらコードを書いていく感じになるのかなと思います。
カスタムディレクティブ
カスタムディレクティブは、データの変更に伴い DOM がどのように変更されるかを定義することができる仕組みです。 有り物だけではちょっとつらいみたいな状態になった時に拡張出来る仕組みです。
Mustacheスタイルのバインディング
{{ }}
これですw
mustache
は口ひげの意で、{
が口ひげっぽいかららしいですね。
mustache.jsというテンプレートエンジンと同様の構文ですね。
ざっくりいうと変数展開ができます。
フィルタ
フィルタは、本質的には「値を取り、加工し、加工した値を返す」関数です。マークアップ内ではパイプ(|)で表され 、一つ以上の引数を続けることができます。
View を更新する前の生の値を処理するために使われる関数です。
変数に対してある処理を行ってから反映をさせることができるようになります。
デフォルトでは以下のフィルタが用意されています。
- capitalize
- 先頭文字を大文字にする
- uppercase
- 全部大文字にする
- lowercase
- 全部小文字にする
- currency
- 引数に好きな通貨単位を取る(ex. $)
- pluralize
- 引数に取った値を複数表記にする(ex. item => items)
- json
- 引数にインデント幅を取ってjson表記にする
- key
v-on
ディレクティブとセットで使える- 「エンターキーが押されたとき」みたいなのを表現できる
- filterBy
v-repeat
ディレクティブとセットで使える- 引数にフィルタリング条件を取って元配列の内容をフィルタリング出来る
- orderBy
v-repeat
ディレクティブとセットで使える- 引数にソート条件を取って元配列の内容をソート出来る
カスタムフィルタ
コレ以外にもフィルタ欲しい...ってなった時にはカスタムフィルタを定義することも可能です。
Vue.filter('reverse', function (value) { return value.split('').reverse().join('') })
のような感じで定義可能です。
その他
他にも色々用意されてます!
本当に最小限といった形で入門記事を書いてみましたが、今回出した例の範疇を越えて行くと色々な機能も他にもあります。
あたりは今回は触れなかったので追々触れられたらいいな〜と思ってます。
でもこの辺りまでしっかり見ていったとしても、大して学習は時間はかからなさそうだなぁという感想なので、本当に軽めな良いフレームワークだなぁというのが所感です。
良い感じの例も公式で準備してくれてます:)
ここに置いてあるソースとかを眺めてみても勉強になるかなと思います!
基本は公式をみてれば良さそう
公式ドキュメントがしっかりしているので、公式ドキュメントと仲良くなればおおかた作っていけるかなぁという感触があります。
自分もしっかり読んで使っていこうと思います!
第一印象としてはすごく使い始めやすそうだなぁという感じだったので、引き続きちょっと触って行きたいと思います!
DoctrineCacheBundleでMemcachedを使おうとした時にハマった話[Symfony2][DoctrineCacheBundle][Memcached]
Symfony2プロダクトでMemcachedを使おうとした時には、DoctrineCacheBundleが使えます。
基本的にはカジュアルにコンテナから取り出せて便利〜って感じだったのですが、ElastiCacheを使おう〜って思った時にガンハマりしたので備忘録として。
どうハマったか
端的にいうと、「yaml記法で書かれた設定ファイルのホスト名がよしなに書き換えられてしまう」せいで、ElastiCacheにつながらない、という問題に直面して、苦労したお話です。
原因がわからず詰まっていた
DoctrineCacheBundleってElastiCache使えないとかある…?なぜできないぐぬぬ…
— なかにしごう (@gomachan46) 2015, 7月 16
しかもMemcached取り出してresetServerList()してからsetしなおすと普通に動くようになるとかなんなの…
— なかにしごう (@gomachan46) 2015, 7月 16
なんか間違えてるんだろうか...
— なかにしごう (@gomachan46) 2015, 7月 16
(´;ω;`)ウッ…(´;ω;`)ウッ…(´;ω;`)ウッ…(´;ω;`)ウッ…
— なかにしごう (@gomachan46) 2015, 7月 16
どう書き換えられたか
このREADMEの
# app/config/doctrine_cache.yml doctrine_cache: providers: my_memcached_cache: memcached: servers: memcached01.ss: 11211 memcached02.ss: port: 11211
を参考にして、設定ファイルを以下の様に書いていました。
# app/config/doctrine_cache.yml doctrine_cache: providers: my_memcached_cache: memcached: servers: hoge-fuga-01.abcdef.0001.apne1.cache.amazonaws.com: 11211 hoge-fuga-02.abcdef.0001.apne1.cache.amazonaws.com: 11211
的な感じで。
これがなんと、コンテナから取り出した時にはホスト名がそれぞれ
hoge_fuga_01.abcdef.0001.apne1.cache.amazonaws.com hoge_fuga_02.abcdef.0001.apne1.cache.amazonaws.com
に自動的に書き換えられた状態でセットされてしまう、というものでした。 yamlの仕様かYmlParserの仕様かDoctrineCacheBundleの仕様かContainer周りの仕様か追いきれてないですが、とりあえずこうなってしまうようですorz
どう解決したか
READMEのxmlの例を見て推測しつつ、次のようにやってみたら出来ましたw
# app/config/doctrine_cache.yml doctrine_cache: providers: my_memcached_cache: memcached: servers: server1: host: hoge-fuga-01.abcdef.0001.apne1.cache.amazonaws.com port: 11211 server2: host: hoge-fuga-02.abcdef.0001.apne1.cache.amazonaws.com port: 11211
この様にするとホスト名を文字列的に明示してかけるのでよしなに書き換えられる事なく無事つなげることができました。
原因がわかってみれば大したことはなかったのですが、なかなか問題の切り分けがしづらく苦戦しました...
ということで、DoctrineCacheBundleを使ってMemcachedを扱うときは、「ホスト名やポート名は明示するようにしましょう」という備忘録でした。
2.7から始めるSymfony2[PHP][Symfony]
Symfony2のLTSである、Symfony2.7がちょっと前にリリースされました。
LTSということで、Symfony2.7は3年間はサポートするよ!っていうなかなか安定感のあるバージョンになっています。
The Release Process (Contributing to Symfony)
サポート期間が長いのでギョーミーな部分にもSymfony2を導入するハードルも下がるしSymfony2を新規で導入することも増えるんじゃないかなぁと思います。
ということで今回は「これからSymfony2を始めるには」といったところの記事を書こうかなと思います!
「今まで使ったことないけど、試してみようかな?」的なところの助けになれば幸いです。
今回はSymfony2の導入から簡単な構造の説明までをできたらと思います。
インストーラーの導入
Symfony2は、2015/03/26から、新しいインストーラーが導入されて、以前よりも簡単に便利にSymfony2をインストールできるようになりました。
なのでこれからはこのインストーラーを使ってサクサクSymfony2プロダクトを始めるのが良いでしょう!
まず以下の様にしてインストーラーを入れます。
sudo curl -LsS http://symfony.com/installer -o /usr/local/bin/symfony sudo chmod a+x /usr/local/bin/symfony
Windowsだったら
c:\> php -r "readfile('http://symfony.com/installer');" > symfony
このようにするだけです:)
なお、ちょっとWindowsが手元にないのでここからはLinux/Mac OS Xベースで書いていきますmm
プロジェクトの作成
インストーラーがサクッとインストールできたので、次は早速プロジェクトを作成しましょう。
symfony new <プロジェクト名> 2.7
この様にコマンドを実行すると、よしなにSymfony2.7で動くプロジェクトを作成してくれます:)
なお、2.7
の部分はお察しの通りSymfony2のバージョンを表していて、任意のバージョンのSymfony2をインストール可能です。2.6
でも、2.5
でも、好きなように入れることができます。
また、上記の例ではSymfony2.7の中でも最新バージョンを入れてくれますが、2.7.1
のように詳細までバージョン指定することでその指定したバージョンを入れることもできます。
逆にバージョン指定をしないでコマンド実行をするとその時の最新バージョンで動くプロジェクトが作成できます。
さて、コマンドを実行すると以下のように表示されるかと思います。
Downloading Symfony... 4.95 MB/4.95 MB ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ 100% Preparing project... ✔ Symfony 2.7.1 was successfully installed. Now you can: * Change your current directory to /Users/g-nakanishi/hogehoge_symfony * Configure your application in app/config/parameters.yml file. * Run your application: 1. Execute the php app/console server:run command. 2. Browse to the http://localhost:8000 URL. * Read the documentation at http://symfony.com/doc
これでプロジェクト作成は完了です。いやはや簡単。
また、Symfony2にはその環境でちゃんとSymfony2が動作するかどうかのチェックスクリプトが同梱されていて、そのスクリプトを実行すれば簡単に動作をするかも確認できます。
php <プロジェクト名>/app/check.php
こちらを実行するとphp.ini
を見つつ動作チェックを行ってくれます。
プロジェクトの動作確認
もう実はバッチリSymfony2は動くようになってくれています!
確認してみましょう。
プロジェクトに入って、サーバーを起動してみます。
cd <プロジェクト名> php app/console server:run Server running on http://127.0.0.1:8000 Quit the server with CONTROL-C.
サーバー起動まで行えたら、ブラウザでhttp://127.0.0.1:8000/app/example
にアクセスしてみます。
これでHomepage.
のように画面上に表示されていればSymfony2はしっかり仕事をしてくれています。
プロジェクトの構造
Symfony2プロジェクトは、以下の様な構成になっています。
├─ app/ │ ├─ console │ ├─ cache/ │ ├─ config/ │ ├─ logs/ │ └─ Resources/ ├─ bin/ ├─ src/ │ └─ AppBundle/ ├─ vendor/ └─ web/
app
アプリケーション固有の設定や、アプリケーションの核になるファイル、キャッシュやログの格納されるディレクトリなどが詰まったディレクトリです。
console
Symfony2が提供しているコマンド群を実行するためのスクリプトです。
先ほど実行したphp app/console server:run
のようにして使用します。
また、自作したコマンドをこのconsole経由で実行可能にすることもできます。
cache
キャッシュディレクトリです。Symfony2は色々な部分でキャッシュを行って高速化を行っていますが、そのキャッシュ群はこのディレクトリに格納されます。
config
アプリケーション固有の設定は、このconfigディレクトリ下に格納されます。 データベースの設定であったり、ロガーの設定であったり、ルーティングの設定であったり、各種様々な設定は軒並みこちらのディレクトリに集まります。
logs
ログが集まるディレクトリです。(特になんも言えなかった)
Resources
主にアプリケーション全体に共通となるhtml等を置くディレクトリです。
bin
実行可能な便利コマンド群を置くディレクトリです。 シンボリックリンクを置いておいたりもできます。
src
実ソースコードが置かれる部分です。
Symfony2は全てがBundleという単位で管理されているため、そのBundle群がこのsrc下に集まっています。
Bundleというのはプラグインに近いような概念で、自分たちで書いていくアプリケーションコードに関してもBundleという形で作成していきます。
web
俗に言うpublicなディレクトリで、ここにはブラウザ等からアクセス可能なものが配置されます。
vendor
外部ベンダーの作成したライブラリ等が格納されます。
git等のバージョン管理時にはignoreしておいたら良いかと思います。
終わりに
今回はとりあえず「これくらいカジュアルに始められるよ!」というのを伝えたくて本当に導入部だけ書いてみました。
Symfony2、PHPでアプリを書くなら一択くらいには気に入っているので、ぜひ使う人口が増えるとうれしいです。
次やる気がでれば導入後の入門記事とかも書きたいな〜
AASMライクなPHP用StateMachine 1.1.0 released!![PHP][Doctrine]
以前このブログでも紹介した、
PHP用のステートマシンライブラリのv1.1.0を公開しました!
Rubyの有名なステートマシンgemであるaasm/aasm · GitHubぽいカジュアルに使えるステートマシンが欲しくて開発しています。
v1.0.0ではステートマシンとしての最小限の機能である状態遷移を管理する
機能のみを提供していましたが、v1.1.0では以下のような機能を追加しました。
- 間違った遷移をしようとした時に例外を投げるのではなくfalseを返すようにするオプションの実装(WhinyTransitions)
- 直接代入による状態遷移を向こうにするオプションの実装(NoDirectAssignment)
- コールバックメソッドの有効化(Callbacks)
- イベント開始前(beforeEvent)
- 旧状態退出前(beforeExit)
- 旧状態退出時(exit)
- 新状態入場前(beforeEnter)
- 新状態入場時(enter)
- 遷移後(afterTransition)
- 旧状態退出後(afterExit)
- 新状態入場後(afterEnter)
- イベント終了後(afterEvent)
- 引数を伴うコールバックメソッドへの対応
- 状態名取得メソッドの実装
これで色々なフックポイントでコールバックメソッドを実行できるようになったので、痒いところに手が届きやすくなったかなーと思っています!
また、状態名を取得するメソッドも用意出来たので、これで定数などで状態名を保持するような二重管理っぽい状況も打破できそうです:)
リポジトリは以下です。
設定ファイル不要でアノテーションだけで状態管理できるようになるのでお手軽ですよー! また、Symfony2でお馴染みのDoctrineが提供しているアノテーション機能を用いて作成していますが、Symfony2で無くてもプレーンなPHPに対して使用可能になっているのでぜひどうぞ。
せっかく作ったライブラリなので普通に使えるようにしっかり育て続けていきたいと思います!