Vue.js始めるおれおれアドベントカレンダー2016 – 7日目
色々やろうとしたらやっぱりファイルの管理とかが手間なので、ぼちぼちツールを導入します。
なにそれ
Browserify transform for Vue.js components, with scoped CSS and component hot-reloading.
(Broserifyを使って)Vueのコンパイル的なアレをしてくれるツールです。対象のファイルはJSではなく、HTMLテンプレートとJSの両方を含む *.vue
という拡張子のファイルだそうだ。
hot-reloading は自分の環境だと特にそれっぽい動きはしてくれてない。ウェブブラウザが別マシンだから?
ところでこういうのをコンパイルと呼んで良いんだろうか。
試行錯誤の記録
色々エラー出たりしたので置いておきます。
まず今まで使ってたひとつしかないJSファイルを単純にvueifyに突っ込んだら、ちゃんと動いてくれた。変換なしで通してくれたみたい。
続いてVueとVuexを require()
で読み込むようにしたら、エラー。
Error: [vuex] must call Vue.use(Vuex) before creating a store instance.
あ、まあそうですね。さくっと Vue.use(Vuex)
を追加。
で次。
[Vue warn]: Failed to mount component: template or render function not defined.
(found in root instance)
んーコンポーネントの template
をHTMLに書いてちゃ駄目か。そりゃそうだ。
でJS側に持ってきても駄目だった。あれ? あーそうか本体(コンポーネントにしてない部分)もこっちに持ってこないとか。どうやら main.app
から全体を司る App
を render()
で出力するのが定石らしい。(合ってる?)
でやったら、何故か画面が空っぽになる、何も出てこない……。と思ったら return
してなかった。ああーそっか!
よしまあじゃあ一度全部消して、READMEの例の通りにやってみよう。
Error: Parsing file /path/to/you/work/dir/App.vue: 'import' and 'export' may only appear at the top level (23:0)
えー。
export default {}
を module.exports = {}
にしたら解決。よくわかってない。
ともかくこれで動いた!
ただ、最終的な出力ファイルの位置でエラーが出てくるのでわかりづらい。browserifyの方のオプションで --debug
を与えるとソースマップを付けてくれるんだけど、うーんわかりづらい。
まとめ
環境
こんな感じになりました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | { "scripts" : { "start" : "npm run vue-watch" , "vue-build" : "browserify -t vueify -e src/main.js -o out/app.js " , "vue-watch" : "chokidar src/* -c 'npm run vue-build'" }, "dependencies" : { "browserify" : "^13.1.1" , "chokidar-cli" : "^1.2.0" , "vue" : "^2.1.4" , "vueify" : "^9.3.0" , "vuex" : "^2.0.0" }, } |
src/
に元のファイルを、out/
に出力ファイルを置くものとします。npm run vue-build
でビルドします。npm run vue-watch
でファイル監視してビルドします。chokidar
はファイル監視してコマンド実行するやつです。べんり!
Hello World!
- src/main.js
1 2 3 4 5 6 7 8 9 10 11 12 | const Vue = require( 'vue' ); const Vuex = require( 'vuex' ); // 今回使ってないけど Vue.use(Vuex); const App = require( './App.vue' ); new Vue({ el: '#app' , render: function (createElement) { return createElement(App); }, }); |
- src/App.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | < style > h1 { font-style: italic; } </ style > < template > < div class = "container" > < h1 >{{message}}</ h1 > </ div > </ template > < script > module.exports = { data: function() { return { message: 'Hello World!', }, }, }; </ script > |

はあー、なるほどこんな感じですか!
コンポーネント
別のファイルにして require()
する感じ。無理やり感あるけど分割して、ついでにVuexも突っ込みます。
- App.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | < template > < div class = "container" > < my-title ></ my-title > </ div > </ template > < script > var MyTitle = require('./MyTitle.vue'); module.exports = { components: { MyTitle: MyTitle, }, }; </ script > |
- MyTitle.js
1 2 3 4 5 6 7 8 9 10 11 12 13 | < template > < h1 >{{title}}</ h1 > </ template > < script > var store = require('./store.js'); module.exports = { data: function() { return store.state; }, }; </ script > |
- store.js
1 2 3 4 5 6 7 | const Vuex = require( 'vuex' ); module.exports = new Vuex.Store({ state: { title: 'Hello World!' , }, }); |
見た目はさっきと一緒。
よくわからないこと
store.state
を直接 data
に指定しない?
data: store.state
と書いたらこんなん言われた。
[Vue warn]: The "data" option should be a function that returns a per-instance value in component definitions.
毎回 function()
書いて return
しないといけない?
export default
を使うには?
これも未来JavaScriptの機能だよね。 import
するやつ。例の通りに書いたのに駄目だった。コンパイル時にエラーになる。どうしたら良かったんだろうか。バベる? いつ?
hot-reloading
使えたら便利そうだけど。
lint
そろそろVue的な書き方に合わせたい。セミコロン欲しい派だけど、しばらく書いてれば慣れるだろう……。
おしまい
ビルドなしで強力なのが導入できて便利~というのがVueの最初の印象だったんだけど、結局ビルドするようになりました。まあ「ちゃんと」やろうとしたらそうなるよね。例えjQueryでも。とはいえ簡単だし、jQueryでちゃんと整えるよりやっぱり簡単じゃないだろうか。