Vue.js
全くの初心者が手探りで導入しただけのメモなので注意。(しかも特に何も作っていない)
vue.js is 何者?
- 立ち位置はここがわかりやすかった
- 公式
かつて主流だったjQueryでの開発では、htmlとjsとcssでidやclassを合わせたりAjaxで書き換えたりの行ったり来たりが必要になり、規模が膨らむと追い切れない。 また、SPA(Single Page Application)という開発スタイルが台頭してきた。 これはコンテンツ毎にページ遷移するのではなく、読み込む土台のhtmlは1つで、あとはjavascriptで必要な時にコンテンツを書き換えるもので、こうなるとさらに複雑になる。
それをフレームワーク化したのがReactやAngularJSなどだが、こちらはこちらで大規模案件向けなので準備が大変だし使用するツールの学習コストも高い。
vue.jsは、それよりはすこーし柔軟に、ライブラリ(フロントサイド)としてもフレームワーク(サーバーサイド)としても使える。上の2つよりも後発。
ライブラリとして(小さく)使うには、単にhtmlでvue.jsを読み込んで、htmlをvue.jsに従った記法で書く。簡単な条件分岐や変数のhtml⇔js間同期など、本来はclassを揃えてjsで処理を書かなくてはいけないものを、html内に簡潔に記述できる。これは実行時にjsによって書き換えられる。
フレームワークとして(大きく)使うには、サーバーサイドで.vueというファイルを記述する。これはコンテンツ毎のhtml,js,cssなどをまとめて書けるファイルである。 実際にサーバに配置するのはこれをコンパイルしたものであるが、html,js,cssをコンテンツ単位で記述できるため開発時の見通しが良くなり、機能追加も簡単になる。
基本的には上述のようなSPAの開発に特に適合するっぽいので、どちらかというとそういうサイトの開発に用いるのがいいのだろう。
準備
- Windows
- Nodist を用いてインストールした Node.js
- IDE: PhpStorm 2018.3
node.js はインストール済みとして、vue-cli のインストール。
> nodist dist node.js本体の最新版が出てないか調べて、アップデートしておく(任意) > nodist ls > nodist latest > node update リポジトリの更新 > node install --global vue-cli vue-cli をグローバルにインストール
また、(実際では後から気付いたが)PhpStormの設定で、nodeとnpmのパスをきちんと設定しておく(後述)
新規プロジェクト
PhpStorm [New Project] で左ペインから [Vue.js] を選択、その際、Locationは存在するフォルダだと警告が出るので、プロジェクトフォルダのあらかじめの作成はしないでおく。
[Project template]はよくわからないのでデフォルトのwebpackをそのまま使用。
[Next]を押す。プロジェクト名や作成者など聞かれる(package.jsonに記録されるもの。他でも使われるのかはわからん)ので、適当に答える。
[Vue build] は、ほとんどのユーザにお勧めらしいので [Runtime+Compiler] を選択。他の選択肢は[Runtime-only]。
'vue-router' をインストールするか聞かれる。調べると、SPAにおいて、各画面をあたかもページ遷移したようにURLを書き換え、戻る/進むの履歴にも加えるツールらしい? 一気にいろいろ手を付けると訳わからなくなりそうだけど、セットで使う記事が結構あったので入れてみる。
'ESLint' を使うか聞かれる。Yesで。presetを聞かれるので、Standardで。
Unit testを用意するか聞かれる。Yesで。test runnner にはデフォルトのJestを選択。
e2e testを用意するか聞かれる。Noで。
これまでの要望に添ったツールを、プロジェクト生成後に自動インストールするか聞かれる。npmを使ってインストールしてもらう。
指定したLocation直下にindex.html、その他数多くのファイルとフォルダが生成される。
プロジェクト生成後の設定
npmの場所がちゃんと設定できてなかったので、する。これは[Langage & Frameworks] ⇒ [Node.js and NPM] ⇒ [Package manager] に、“bin\npm-cli.js”のあるフォルダを選択((Nodist-install-dir)\npm)
サーバを立ち上げる
右上の実行ボタンが集まっている箇所に、最初から'npm start'の実行設定が用意されている。実行すると、'npm run dev'で開発用ローカルサーバが立ち上がるとともに、初回ビルドが走る。
localhostの、コンソールに表示されるポートから作成中のページを確認できるようになる。更新はリアルタイムで反映される。
さて
どのファイルがどういう役割を果たすんだ……
こういうフレームワークは大量のファイルがどかっと配置されて、ひもといていくのに気力を要する。がんばる。
とりあえず、vue.jsは独自の言語で記述した後にコンパイルしてhtmlやjsを生成するっぽいので、編集するならsrcあたりだろう。
src/ |- assets/ | `- logo.png |- components/ | `- HelloWorld.vue |- router/ | `- index.js |- App.vue `- main.js
チュートリアルに倣う。App.vue で、トップページの内容が表示されているようだ。
ただ、App.vueでは上半分のロゴについての記述しか見当たらない。残りの内容は components/HelloWorld.vue
に見つかった。
App.vueが全てのルートとなるのは間違いなさそうで、そこには「HelloWorld.vue」を見ればよいことはどこにも書かれていない。どこかで指示されているはずなので探すと、router/index.js
に見つかった。これは、vue-router の機能のようだ。また、routerフォルダをimportする指定はmain.js
に記述されていた。
必ず使用される[App.vue + main.js] ⇒ router/ の読込指定 ⇒ HelloWorl.vue の読込指定
ページのソースを見ると、ルートにあるindex.html
と内容がほぼ同じなので、静的な一番大枠の構造はここで作りつつ、中身をvueで作っていく、という作業工程のイメージか。
ソースとindex.html
は全く同じでは無く、読み込むjsなどの記述が抜け落ちている。これは、ソースはコンパイルされた結果なため。コンパイルは、以下で出来る。少し時間はかかるが、終わったら (root)/dist/
以下に index.html
とjs,cssが作成され、jsが埋め込まれた状態となっている。
> npm run build
<template> <div id="app"> <img src="./assets/logo.png"> <router-view/> </div> </template> <script> export default { name: 'App' } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'HelloWorld', component: HelloWorld } ] })
<template> <div class="hello"> <h1>{{ msg }}</h1> <h2>Essential Links</h2> <ul> <li> <a href="https://vuejs.org" target="_blank" > Core Docs </a> </li> <li> <a href="https://forum.vuejs.org" target="_blank" > Forum </a> </li> <!-- ...略... --> </ul> <h2>Ecosystem</h2> <ul> <li> <a href="http://router.vuejs.org/" target="_blank" > vue-router </a> </li> <!-- ...略... --> </ul> </div> </template> <script> export default { name: 'HelloWorld', data () { return { msg: 'Welcome to Your Vue.js App' } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h1, h2 { font-weight: normal; } /* ...略... */ </style>
再構築
設定とかは置いといて、編集するファイルはわかった。生成されるのはあくまでjsなので、これだと常に同じページを返すことになりそうだ。(動的ではあるものの、閲覧者や時刻などに応じて内容を変化させることができない)
サーバ上のファイルを操作したり、セッションを使ったり、DBからリアルタイムの情報を取ってきたり、そういったサーバーサイドの処理まで包括したツールではないように見える。(という認識でいいよね?)
そういう機能は、Vue.jsではなく、Node.jsのモジュール、もしくはPHPなどのcgiの管轄となるのだろう。
Node.jsのモジュールをサーバ側で使うとすると、Node.jsのサーバを立てることになる。本番環境がVPSなどだといいが、共有レンタルサーバでは常駐プログラムは一般的に実行できない。ので、一般的に用意されているApache + PHPを使うという選択になる。
Webpackで利用される開発サーバ(webpack-dev-server)は、PhpStormでのVue.jsプロジェクト作成時に初期状態から使え、監視によりファイル更新時に自動リロードがかかるなど開発に便利なのだが、当然ながらPHPは解釈できない(やろうと思えば出来なくもないみたいだが)。
その代わり特定のURLへのアクセスを別のドメインに飛ばす機能があるので、それを使い、Vagrantで起動しておいた仮想マシンにPHPへのアクセスだけ飛ばすことになる。
// ...略... module.exports = { dev: { // ...略... // proxyTable: {}, // ↓ proxyTable: { '/api': { target: 'http://192.168.33.10', // Vagrant上のマシンのIP }, }, // ...略...
DevServer立てて仮想マシン立ててIDE起動して、メモリが心配。
PHPフレームワークのLaravelなどでは、PHPとVue.jsを共存させる構成になっているらしい。構成だけでも盗んでくるのはありか。
……と思ったけど、Vue.jsに触ったばかりの自分では裏で何をしているのかわからない。 環境構築して実際のレンダリング結果を見ようとしたが、チュートリアルに書かれているとおりのコマンドを実行してもpackage.jsonの依存関係のエラーで環境が用意できなかった。原因がどこにあるのかは不明だが、こういうことに取られる時間が多くなってしまうので依存関係の手を広げたツールは苦手。
閑話休題。
上記のような事情で、Vue.jsを使いつつサーバではPHPも使いたい場合、Vagrantなどを併用して別途サーバを立てることで可能になる。 Vagrantを使うと、よくある設定では「(プロジェクトルート)/public」がApacheのドキュメントルートになるので、Vueの出力先もそっちにあわせる。
// ...略... build: { // Template for index.html index: path.resolve(__dirname, '../public/index.html'), // Paths assetsRoot: path.resolve(__dirname, '../public'), assetsSubDirectory: 'assets', assetsPublicPath: '/',
(ProjectRoot)/ |- build/ (vue.js) |- config/ (vue.js) |- node_modules/ (Node.jsライブラリ) |- public/ (公開用データ) | |- api/ (phpのAPIを配置, 開発用サーバから飛ばす) | |- assets/ (imgとかjsとかcssとか) | `- index.html (ビルド後のやつ) |- src/ | |- assets/ | |- components/ | |- router/ | |- App.vue | `- main.js |- vendor/ (PHPライブラリ) |- index.html (ビルド前のやつ) |- composer.json (PHP用) |- package.json (Node.js用) `- Vagrantfile (Vagrant用)
PHPで出力されるHTMLに対して、Vue.jsで自動生成された.jsを埋め込むのはどうやる? 出力ファイル名を固定して直接入れるのだろうか。
最低限のSEO対策
Vue.js をフレームワークとして使って、それのみで完結させた場合、デフォルトの構成では、index.htmlは<div>要素が1つだけあるhtmlからcssとjsを読み込んでいるだけの、内容も何も無いページとなる。(jsに情報が詰め込まれている)
Googleのクローラさんはjavascriptを解釈すると言われているが、全てのクローラさんがそうではないので、内容も何も無いページと見做される可能性がある。
まぁ、別に個人サイトなど不要なら不要だし、ちゃんとやるならもっとちゃんとやらないといけないので中途半端ではあるが、最低限のメタタグでページ内容を伝えておく。
... <head> <meta name="keywords" content="キーワードA,キーワードB,キーワードC"> <meta name="description" content="ページの内容"> ...
しかし、フルVue.jsで作る時、どうするのがいいんだろうね。
結局
一般に、フレームワークを使う際のメリットは、
- プロジェクト全体を管理しやすく考えられているため、規模が大きくなってもこんがらがらない
- 典型的な書き方を、短い記述で、デザイン崩れやセキュリティ的にも堅牢に書ける
- cssのベンダプレフィックス、htmlとjsで作る投稿フォームなど
フレームワークを使う際のデメリットは、
- フレームワークの流儀に従わねばならず、元となる言語に加えてフレームワーク独自の書き方も覚える必要がある
- わずかな例外的な処理のために流儀をちょっとだけ逸脱したくても、融通が利かない、または却って記述量が増える
- 簡単に書けたり汎用性を持たせるため、内部では複雑なことをしていることも多く、どこがどう影響してるのか全体像を把握しづらい
Vue.jsも、ご多分に漏れずそういった側面はあるのだが、まだ比較的軽量で、わりと把握しやすくていい感じだと感じた。(自分がNode.js周りのツールに少しだけ慣れてきたこともあるかも知れない)
特に、ページの要素をコンポーネントで分割して、それ単位でHTMLとjsとcssを記述管理できるのは、非常にすっきりできて、魅力だった。
でも、ちょっと複雑なことをしようとするとコンポーネント間のデータ受け渡しとかで破綻する気も正直する……ので、1画面で完結し、各機能が独立してる、つくりやすいサイトをもっと作りやすくするためのツールとして使えそう。
Web開発における様々な場面でノウハウが蓄積されて「崩れにくいデザインの指定方法」「利便性やセキュリティ的にやっておいた方がいい処理」などが把握しきれないほど多方面で出てきているので、フレームワークの恩恵が大きくなっているなあとは思う。(もちろん、よくわからないまま使うのは危険とは言われているが)