2018/07/12追記 公開しました
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
PWA
PWAに関してはまず、Googleの公式を理解するのが一番良さそう。まだ途中。
はじめてのプログレッシブ ウェブアプリ | Web | Google Developers
ローカルへのデータ保存
編集中の文字列の自動保存など、最初一番簡単なLocalStorageを使ってみたけど、パフォーマンス的にあんまり良くないらしい。いろいろ探しているとMozillaが作っている良いlocalForageというライブラリがあり、さらにそれをVueで簡単に使えるライブラリもあった。
これを使えば、環境に合わせて一番いい機能を使ってくれる。PWAのP、プログレッシブ的なことをやってくれる。最初からこれを使えばよかった。