GAミント至上主義

Web Monomaniacal Developer.

Vue.jsでPWAアプリをつくりはじめた

2018/07/12追記 公開しました

rirekisho.yagish.jp

2018/7/5追記

この記事で利用したテンプレートはすでにメンテナンスに入っており、今後はvue-cliプラグイン形式になるようです。
Webpackも3から4になっているので推奨です。


GitHub - vuejs-templates/pwa: PWA template for vue-cli based on the webpack template


vue-cli/packages/@vue/cli-plugin-pwa at dev · vuejs/vue-cli · GitHub


追記ここまで


bizoceanでは、ワードやエクセル形式の書式を配布しているが、ほとんど書式自体の編集が不要でワード・エクセルを使うまでもない書式もあるし、今後PCを使う人自体が減れば、どんどん利用も減っていくだろうと思う。

個人的にもワード・エクセルは高機能すぎてよくわからなくなるので使いたくない。

そんなことで2月から本格的に書式をWEB上で作れる新規サービスの設計&開発を始めた。

いろいろやるうちに、結論としてはVue.jsを使ったPWAが良さそうということになった。

初期版

Djangoのフォームと、ヘッドレスChromeを使ったHTMLからPDFへの変換サーバーを使ったもの。

ほぼDjangoで完結するのでこれはこれで保守性は良さげ。だけど、UI周りでグリグリしようとすると、Djangoはそういうのない(というより自由な)ので、勉強も兼ねてVue.jsを使うことにする。

雑食系WEB開発者としては、jsのフロントエンドの経験が必須だと思っていた。

Vue.jsをDjangoテンプレート上でつかう版

とりあえず本格的にVue.jsを使うのは始めてなので、CDNからのscriptタグを使って開発をはじめた。
テンプレートタグの{{ var_name }}は丸かぶりするけど、vue側はdelimitersで簡単に変更できる

var app = new Vue({
  delimiters: ['[[', ']]'],
  el: '#app',
  data: {
// 以下略

が、コンポーネントが3つか4つ程度ならscriptタグでなんとかなるけど、コードが長くなってきたり、書式の種類ごとにコンポーネント化をしたくなってくると早々に限界が来た。

単一ファイルコンポーネントがファイルごとに分けられて良さげ。

jp.vuejs.org
しかも事前にテンプレート描画処理をコンパイル的なことができるので、動作も早いらしい。

しかし、それにはwebpackが必要だった。。。

webpack使用してUIは全部Vue.js、DjangoはあとでAPI的なのつくるよ版

イマココ。

ついにずっと避けてきたnpmやwebpackと対峙することになった。フロントエンドは変化が激しすぎる上に設定が多すぎるイメージで落ち着くまで待ちたかった。

これからやるならPWAがいいよね、オフラインでも動くし、Googleも推してるし、Safariも対応しそうだし、ってことで下記のvueの公式PWAテンプレートを元に書きかけのものを移植した。

GitHub - vuejs-templates/pwa: PWA template for vue-cli based on the webpack template

npm、nodeを開発サーバーに直に入れたくないので、おなじみのDockerを使った。いろいろインストールしまくったり、ぐちゃぐちゃになってもホストマシンは汚れずリセットできるので安心。
Dockerfileはこんな感じで、appディレクトリをdocker run時に-vでマウントして開発する。

FROM node:9-slim
RUN mkdir /varuna/
RUN apt-get update --fix-missing && apt-get -y upgrade

RUN apt-get install -y \
    git \
    bzip2

RUN npm install -g vue-cli

COPY app app
EXPOSE 8080
WORKDIR /varuna/app/shanyang-project
CMD ["bash"]

何かのインストール時に必要なbzip2とかgitをとかいれたり、忘れたけどいくつかのエラーを潰して、やっとnpm run devできたと思ったら、最初の難関は、Lintのエラーの嵐。

セミコロンがいらんとか、インデントがどうとか、変数名がどうとか。300個は直した気がする。もっと早くやっておけばよかった。

npmの開発サーバーはファイルを更新すると勝手に更新してくれるので再読込すら不要で便利。

まだ表に出せる段階ではないけど、いくつかもっと早く知っておきたかったことをメモ。

vue.js関連

コンポーネント親子間のデータ受け渡し

コンポーネント入れ子が深くなってきたら、親子間のデータの受け渡しはほぼ必須となる。
親から子はプロパティ(props)、子から親はカスタムイベント(emit)は死守すべき。
jp.vuejs.org

this.$rootとかで出来なくはないけど、ルーティングを入れたりし始めると破綻する。

また、親子より遠くなると途端に面倒になるので、なるべく深くせず、またルーティングで分けすぎない方がいい。

最初、書式の編集、プレビューのルーティングを分けたが面倒すぎたので、編集とプレビューは同じコンポーネント内に出して、表示の切り替えをすることにした。

状態が複雑になってきたら素直にVuexを使ったほうがいいと思うけど、今回はまだそんな複雑ではないので使ってない。
vuex.vuejs.org

Atomの設定

いつもサーバー側プログラムはvimだけど、他の人とリアルタイム編集作業が便利なのでAtomを使い始めた。
保存時にフォーマットするAtom Beautifyとか、vue対応を入れたら便利になった。

ここらへん参照
qiita.com

vue-router

公式のルーター。URLで状態を変えることができ、個別ページの共有や、ブラウザバックなどができるようになるので、ほぼ必要になると思う。

コンポーネントへの分割も必要となり、いろいろ理解も進むので早めにやってしまったほうが良かった。

公式テンプレートでrouterを使用すると、main.jsは下記のようになっており、メインのアプリケーションすらもコンポーネント化が必要なる。

new Vue({
  el: '#app',
  router,
  template: '<App/>',
  components: { App }
})

紹介 | Vue Router

PWA

PWAに関してはまず、Googleの公式を理解するのが一番良さそう。まだ途中。
はじめてのプログレッシブ ウェブアプリ  |  Web  |  Google Developers

ローカルへのデータ保存

編集中の文字列の自動保存など、最初一番簡単なLocalStorageを使ってみたけど、パフォーマンス的にあんまり良くないらしい。いろいろ探しているとMozillaが作っている良いlocalForageというライブラリがあり、さらにそれをVueで簡単に使えるライブラリもあった。

これを使えば、環境に合わせて一番いい機能を使ってくれる。PWAのP、プログレッシブ的なことをやってくれる。最初からこれを使えばよかった。

www.npmjs.com

ビルドしたファイルの確認

npm run buildするとdistディレクトリにまとまったやつができる。恐れていた開発中に動いたけど、ビルドしたら動かないという問題は今のところない。ほぼテンプレートそのままだからか。

でもPWAはhttpslocalhostではないと動かない。開発用にSSLのサーバーをいちいち用意するのは面倒なのでlocalhost一択。

Googleのドキュメントにも出てくるけど、Chromeの拡張でできてしまうがあった。なんでもできるな。

Web Server for Chrome - Chrome Web Store

今後

やっとVueの2%ぐらいは理解できた気がして、作りたいものを所々つまづきながらも書けるようになってきた。

まずはHTML,JSで単体で動けるようなものを作り、PDF変換とか、ログインとかデータのバックアップ等必要に応じてDjangoAPIを作っていく。

UI側が全部Vue.で済めば単なる静的ファイルの配信だけなのでGAEに置いてしまってもいいかもしんない。HTTPSロードバランサーとCloud Storageでもできるけど、GAEは安いうえにSSL証明書自動更新がついて便利になったので。

そしてPWA最適化を行い、サクサクスマホWEBアプリを作りたい。