始めに
Vue.jsを始めるに当たって、簡単に始めるためにvue-cliを作って環境を取ってくることがあると思います。
$ vue init webpack <project-name>
実はこのテンプレートは自作することができて、そのテンプレートを使うことができます。
こちらにテンプレートを作ってみたので、これを取ってくる場合は以下のようにします。
https://github.com/TakanoriOnuma/vue-template
$ vue init TakanoriOnuma/vue-template <project-name>
このカスタムテンプレートですが、結構作り方が見つからなかったのでまとめてみました。
テンプレートの基本構成
カスタムテンプレートを作る場合はざっくり言うと以下のような構成になります。
vue init
すると、templateディレクトリの中身がごっそりコピーされるので、設定がいらない場合は環境をそのままtemplateディレクトリに入れるだけでテンプレートができてしまいます。
ただ他のテンプレートを使っている人はわかると思いますが、lintを入れてみたり、vuexを入れてみたり、色々オプションを聞かれて必要なものだけ取り込まれていると思います。その辺の設定はmeta.jsで書き、ここで得られたフラグを元にコードの出し分けをします。
- template/ # template以下のものが全てコピーされます(設定で取り除いたりできます)
- meta.js # テンプレートを取り込む際に色々設定するところです
- README.md # なくても大丈夫ですが、一応
meta.jsの設定
meta.jsは以下のような設定をします。jsonでも設定は出来ますが、JSの方が細かい設定もできるのでこっちにしています(コメントもかけますし)。
module.exports = {
prompts: {
name: {
type: 'string',
message: 'Project Name'
},
description: {
type: 'string',
message: 'Description',
default: 'A Vue.js project'
},
author: {
type: 'string',
message: 'Author'
},
licence: {
type: 'string',
message: 'licence',
default: 'MIT'
},
devServerPort: {
type: 'string',
message: 'dev server port',
default: '4000'
},
// confirmがフラグになる
isUseStore: {
type: 'confirm',
message: 'is use Vuex Store?'
}
},
// 条件にマッチする時だけコピーする
filters: {
'src/javascripts/store/**/*': 'isUseStore'
},
// vue initで展開させないファイルを指定する
skipInterpolation: ['node_modules/**'],
complete: (data) => {
console.log('\nTo get started:');
// 別ディレクトリに生成する場合は出力先のディレクトリに移動するメッセージを出す
if (!data.inPlace) {
console.log(` cd ${data.destDirName}`);
}
console.log(' yarn install');
console.log(' yarn start');
}
};
promptsのところで各項目の質問を書きます。
文字列を受け取りたいときはtypeをstring
にして、true/falseのフラグはconfirm
にします。
ちなみにnameやauthorは勝手にデフォルトの値が設定されます。おそらくnameはディレクトリ名、authorはgitのauthorから取ってきていると思います。
filtersやskipInterpolationは後ほど説明します。
completeではテンプレートの読みこみが終了した時の処理を書きます。vue initでは第2引数にディレクトリ名を指定するのが通例ですが、ない場合はカレントディレクトリに読み込まれるのでその条件分岐も書かれています。
meta.jsで設定したパラメータを展開する
単純な展開
meta.jsのpromptに書かれたkey名が変数として使えるので、これを使ってテンプレートをカスタマイズしていきます。
変数の展開はmustash記法が使え、例えばREADME.mdだと以下のようになります。
name
とdescription
とdevServerPort
がプロンプトで設定した値が入る感じです。
# {{ name }}
{{ description }}
## 環境
+ node: 10.15.0
+ npm: 6.2.0
## インストール
`$ npm install`
## タスク一覧
### 開発サーバーの立ち上げ
`$ npm start`
[http://localhost:{{ devServerPort }}](http://localhost:{{ devServerPort }})にアクセスしてフロントエンドの開発をする。
### フロントエンドのコードのビルド
`$ npm run build`
dist以下に生成物を配置する。
フラグに応じた出し分け
今回はisUseStore
と言う変数を使ってVuexを使うかのフラグを持っています。これに応じてvuexをpackage.jsonに書くか否かを設定するので、package.jsonは以下のようになります。
以下のように{{#フラグ変数}} コンテンツ {{/フラグ変数}}
でフラグ変数がtrueの時だけコンテンツを出力します。
{
// dependenciesだけ記載
"dependencies": {
"reset-css": "^4.0.1",
"vue": "^2.5.21",
"vue-types": "^1.3.4"{{#isUseStore}},
"vuex": "^3.0.1"{{/isUseStore}}
}
}
storeの設定はstoreディレクトリに配置しており、ファイルごと取り除きたい場合はmeta.jsの方に記述します。
module.exports = {
// isUseStoreがtrueの時だけstore以下のファイルを出力する
filters: {
'src/javascripts/store/**/*': 'isUseStore'
}
};
Vue.jsにもmustash記法で展開したい場合
同じ要領でVue.jsにも書いていきたいですが、Vue.jsでもmustash記法が使われており、vue initで展開すると困る場合は\
でエスケープして設定します。
<template lang="pug">
div
img(src='../images/home.svg')
p Hello World!
TestComponent
{{#isUseStore}}
p counter
button(@click="onDecrementButtonClick") -
//- \{{ $store.state.count }}と書くことで展開後は普通の{{ $store.state.count }}になる
span(style="padding: 0 10px;") \{{ $store.state.count }}
button(@click="onIncrementButtonClick") +
{{/isUseStore}}
</template>
これで対応は出来ますが、テンプレートに書く場合は一々\
でエスケープしないといけません。もしVueファイルは展開しないのでしたらmata.jsのskipInterpolation
に書くといいです。(interpolationは「内挿」と言う意味らしいです)
ちなみにnode_modulesも書いているのは、ローカルで動作確認するときにnode_modulesも展開の対象になってしまったためです。(普通は必要ないです)
module.exports = {
// vueファイルやnode_modules以下のものは展開しない
skipInterpolation: ['src/**/*.vue', 'node_modules/**']
};
余談
mustash記法は別な表記方法で認識させることもできるらしいので、そっちでやると言う方法もありそうです。
ローカルで動作確認する
一々githubにあげて試していくのは面倒なのでローカルでインストールする方法を紹介します。
やり方は単純で、テンプレートの場所は相対パスで書くだけでいいです。
$ vue init ./vue-template vue-template-test
作ってみての所感
テンプレートを作ると以降の環境構築は非常に楽になりますが、テンプレートの開発はかなりめんどくさいです。
一々テンプレートを取り込んでみて動くかを確認しないといけないので、結構時間がかかります。
更に条件分岐が入るとエディタもエラーになってかなりコードが書きにくいです。
vue initではブランチ名を指定できるので、それぞれ分けて使っていく運用が割と楽なんじゃないかなぁって思っています。
$ vue init TakanoriOnuma/vue-template#vuex vue-template-test
まぁこの場合vuex+vue-routerとか複数のオプションがある場合は対応は厳しいですけど。基本的にカスタムテンプレートではそんなにパターンを用意しないほうがいいんじゃないかなと思っています。
参考資料
既にあるテンプレートを見ると結構参考になると思います。僕もよく分からないことが多かったので参考にしました。(completeの処理とか)
あとは公式ドキュメントですね。
終わりに
vue init
と言うコマンドですが、別にVue.jsじゃなくてもReactとかpugをビルドするだけの静的サイトとか、そう言うのでもテンプレートとして作れます。一度作ると使い回すのが凄く楽になるので、似たような環境をよく作る人は試してみてはいかがでしょうか。