Vue.jsを使ったSPAにおいてTwitter等でのリンク表示がいい感じになるようにする

Vue.jsでSPAを構成した際、TwitterなどのOGPが上手く表示されなかったので、対処した。 SPAとは?→シングルページアプリケーション この記事で扱っているSPAとは、シングルページアプリケーションを指す。 SPAについては少し以下の記事で触れたが、詳細は他のサイトの方が詳しいと思う。 OGPとは?→Webページのリンクを表示する仕組み OGPとはOpen Graph Protocolの略で、TwitterとかFacebookとかでリンクがいい感じに表示されるアレに使われているプロトコルのこと。 ↓これ。 Chart.jsで横軸が日付のグラフを作成する https://t.co/evu4HqqQ4f @aoki_kouyaさんから — 青木晃也 (@aoki_kouya) April 4, 2020 webサイトをいちから作る際、OGP対応していないと、Twitterとかでリンクを貼り付けても画像や説明文は表示されない。 そこらへんはTwitter側でなんとかしてくれるわけではなく、サイト作成者側が適切にOGP設定を行う必要がある。 SPAの場合はOGP設定にひと工夫必要 OGPは、具体的にはHTMLにmetaタグを設定することで対応できる。 例えば、以下のようなmetaタグを<head>要素内に設定する。 上記は私が作成したサイトの実装例になるが、他のサイトを調べると、head要素にprefix属性を適切に設定する必要があるようだ。 私は設定していなかったが、とりあえずTwitterあたりでは問題なく動いているように見える。 まあ、正しい対応ではないと思う。 このOGP設定だが、SPAの場合はひと工夫必要になる。 理由は、OGPによってリンクを作成する際、JavaScriptが動かないケースがあるため。 OGPによってリンクを表示する際、クローラーと呼ばれるプログラムによって、リンク先のページをスキャンする。 スキャン結果に従ってリンクを表示するのだが、TwitterやFacebookのクローラーはJavaScriptを実行してくれないらしい。 よって、JavaScriptによってmetaタグを生成しても、リンクには反映されない。 SPAでOGP設定を適切に行う場合はここら辺の対処が必要。 今回は特定条件時のみ静的ページを返すように実装 今回の結論、解決策になる。 調べてみると、(Vue.jsを用いた)SPAでのOGP設定については色々対応策があった。 いくつか参考にさせていただいたページを挙げておく。 上記のページの方法はページ内にも書かれている通り、全てのページで同じ内容のOGPになってしまう。 今回はそれぞれのページで異なるOGPを設定したいため、同じ方法はとらなかった。 上記のページは詳しく書いてあり、参考になりそうだったが、Firebaseを使ってない、使ったことがないため今回は同じ方法をとれなかった。 最終的には以下のページの方法を真似させていただいた。 上のページの方法は、TwitterやFacebookなど特定のクローラーに対してのみOGP対応用のテンプレートを返すというものになっている。 アプローチとしては一番最初に挙げたページと同じだが、こちらはクローラー検出用にControllerを作成して、テンプレートの出し分けをしている。 比較的容易に実装でき、ページごとに異なるOGP設定ができそうだったため、こちらの方法を採用した。 この方法の課題としては、OGP対応用のテンプレートを返す相手をピンポイントで指定する必要があるため、明示的に指定したクローラー以外に対しては対応できない点がある。 また、OGP対応用のControllerを新規に作成する必要があり、Controllerが単純に1個増える。 なお、各サービスのクローラーの情報は以下のサイトを参考にさせていただいた。 雑記 Twitterでのリンク表示内容確認には以下の公式のサイトが便利。 これからはじめるVue.js実践入門 山田 祥寛 Amazon Kindle 楽天 楽天Kobo

April 25, 2020 · 1 min

Chart.jsで横軸が日付のグラフを作成する

webサイト上で横軸が日付情報のグラフを作りたかったのでChart.js周りで色々調べた。 横軸が単純な数値じゃない場合は面倒くさくなるかなと思っていたが、Chart.jsが非常に使いやすく、すんなりできた。 最終的に作ったもの 画像で貼ろうと思ったが、結構サイズが大きいのでリンクで貼り付けておく。 Chart.jsとは グラフ類を描画するためのJavaScriptライブラリ。 HTMLの<canvas>要素に2Dグラフィックを描画できる。 ライセンスはMIT。 Chat.jsのインストールと使い方 基本的な使い方を公式に従って確認してみる。 インストール 今回はとりあえず手軽そうなCDNを使う。 よってHTMLに以下のタグを追加する。 <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script> なお、ここで Chart.bundle.min.js を選択したのは、今回日付データを扱うため。 Chart.min.js の方は日付データを扱うためのライブラリMoment.jsが含まれていない。 使い方 HTML側はグラフ描画用の<canvas>タグを作成する。 先ほどのCDNの参照及び今回作成するJavaScriptの読み込みを合わせて、HTML側のソースは以下のようになる。 index.html JavaScript側は公式のサンプルを参考にして以下のようにする。 main.js これら2つのファイルを適当なところに保存して、index.htmlをブラウザで開く。 以下のようなグラフがブラウザ上に表示される。 横軸が日付情報のデータをプロットする サンプルが動いたので、今回扱いたい、横軸が日付情報のデータをプロットする。 HTML側は特に変更せず、JavaScript側を以下のように変更する。 main.js 参考ページ main.jsを上記のように変更し、index.htmlをブラウザで開くと以下のようなグラフが描画される。 横軸が日付になっており、横軸の間隔もデータに合わせていい感じになっている。 まとめ Chart.jsを使って横軸が日付情報のデータをプロットできた。 色々と描画オプションがあるようなので、それぞれ変更させるとどのようにグラフが変化するか、また今度まとめたい。 確かな力が身につくJavaScript「超」入門 第2版 狩野 祐東 Amazon Kindle 楽天 楽天Kobo

April 5, 2020 · 1 min

Laravel+Vue.jsでSPA(シングルページアプリケーション)を作成した

今回作成したサイト 今回作成したサイトは以下のサイト。 ClubPage 私が所属している電子工作サークルのホームページを作った。 このブログからcssを流用しているので、見た目がだいぶ似ている。 構成 Laravel Vue.js バックエンドはLaravel、フロントエンドはVue.jsを使っている。 シングルページアプリケーションとは 今回はシングルページアプリケーション(SPA)という構成を採用した。 シングルページアプリケーションとは シングルページアプリケーション(英: single-page application、SPA)とは、単一のWebページのみから構成することで、デスクトップアプリケーションのようなユーザ体験を提供するWebアプリケーションまたはWebサイトである。必要なコード(HTML、JavaScript、CSS)は最初にまとめて読み込むか[1]、ユーザの操作などに応じて動的にサーバと通信し、必要なものだけ読み込みを行う。 Wikipediaより というものらしい。 これまでRuby on RailsやDjangoとかを使ってwebサイトを作ってみてきたが、どれも各ページ毎に、サーバ側でHTMLの生成を行うマルチページアプリケーションだった。 今回はLaravelでwebAPIを作成し、そのAPIから取得した情報を、Vue.jsを使ってブラウザ上に表示するような構成にした。 なぜSPAにしたのか 理由は1つで、今回参考にしたサイトがSPAを採用していたから。 今回参考にしたサイトは以下のサイト。 このサイトにあるチュートリアル、書かれている情報量がかなり多くて、これだけの情報をタダで得られるのが信じられない。 今回初めてLaravelとVue.jsを触ったが、このサイトのおかげで色々と基礎を学ぶことができた。 今回学んだこと、感じたこと インタフェース部とエンジン部の分離はやはり重要 今回の構成はAPI(Laravel)と表示部(Vue.js)を分離している。 たとえばhttps://home.lchika.club/api/tagsにアクセスすれば、Laravelの機能によって、タグの一覧をJSON形式で取得できる。 こういったAPIから取得した情報をVue.jsで処理して、ブラウザにレンダリングする。 このように分離することで、UIを変えたいときは、基本的にVue.jsの部分のみを修正するだけですむ。 Laravelの処理部は一切手を加える必要がない。 まあ、一般的なwebフレームワークを使っていれば、実装の分離は適切に行われているが、ある一部分のフレームワークをごっそり切り替えることはできない。 今回の構成では、例えばフロントエンドにReactを使いたければ、Laravel部分はそのままで、フロントエンド部分をごっそり切り替えられる(と思うけど、Laravel-mixとかの関係で難しいのかもしれない…)。 このように、インタフェースとエンジン部の分離で得られる効果はやはりでかいなと思った。 ローディング表示がないとwebサイトの質が落ちる これは個人的な印象かもしれないが、ローディング画面の表示はユーザにとって(ある程度)重要だなと思った。 現状ではローディング表示は実装していないため、読み込み直後は一部のコンテンツが表示されていないし、一部のコンテンツについては結構な時間表示されないことがある。 これはサイト利用者側からすると、違和感を覚える要因になり、満足度の低下につながると思った。 YouTubeとかもローディング中はコンテンツ表示部をグレーで表示したりしている。 最初はこれ意味あるのか?と思っていたが、今回自分でJavaScriptを多用したサイトを構築してみて、こういった対応も重要だなと思った。 WYSIWYGエディタの選定は毎回の課題 今回はブログのようなサイトを構築したので、フォームから記事を投稿できる必要があった。 さすがにHTML直打ちで入力はできないし、リッチテキストエディタを採用する必要があった。 毎回どのリッチテキストエディタを使うか苦労するが、今回も例に漏れず苦労した。 とりあえず今のところはCKEditorを使っている。 ただ、まだ課題があって、iframeの挿入が上手くいっていない。 いつも大体、リッチテキストエディタまわりは 画像の挿入 画像の整形 外部コンテンツの挿入 目次の作成 あたりで詰まっている。 今回はまだ目次の作成について考えていないので、目次が必要になった時に多分また詰まる。 SPAのパフォーマンス向上はバンドルサイズの削減こそ正義 今回作成したサイトのパフォーマンス向上については以下の記事に書いた。 最初特に何も考えずにサイトを作っていたら、パフォーマンスが崩壊した。 今もパフォーマンスが良いとは言えないが、バンドルサイズを削減することで、パフォーマンスが向上した。 こういったパフォーマンス向上のための施策は必要不可欠だなと感じた。 まとめ 今回はLaravelとVue.jsを使ってサイトを作った。...

March 15, 2020 · 1 min

Laravel+Vue.jsでLighthouseのスコアを0点から97点にした(バンドルサイズ削減)

Laravel+Vue.jsで作成していたwebサイトの応答速度が激遅だったので、対策を実施した。 環境 Laravel 6.14.0 Vue.js 2.6.11 対策前はページロードに20秒かかっていた 特に何も考えずにwebサイトを作っていたら、トップページのロードに20秒ほどかかっていた。 これではさすがにwebサイトとして成立しない。 Googleが提供しているwebページ分析ツールLighthouseを使ってパフォーマンスの測定を行ったところ、以下のような結果になった。 堂々の0点である。提示されている対応策の詳細を見ると、以下のように書かれていた。 どうやらバンドル後のapp.jsのサイズが約4MBと、超巨大になっているらしい。対応策としてapp.jsのサイズ削減を行った。 対策1:本番用ビルド設定を適用する バンドルサイズ 3.86MB(app.js) → 1.59MB(app.js) 解説 そもそもビルド設定が間違っていた…。ビルドコマンドとして npm run dev を実行していたが、これは開発用のビルドコマンドらしい。 本番用のビルドコマンド npm run prod を実行したところ、バンドルサイズは3.86MB→1.59MBと、約40%になった。 Lighthouseの結果 0点→10点に上昇した。 対策2:gzipで圧縮する バンドルサイズ 1.59MB(app.js) → 395KB(app.js.gz) 解説 以下のページを参考に、gzipでapp.jsを圧縮した。 そのままコピペで適用できた。 Lighthouseの結果 10点→63点に上昇した。 対策3:ページごとにJSファイルを分割する バンドルサイズ 395KB(app.js.gz) → 243KB(app.js.gz) 解説 以下のページを参考に、ページごとにJSファイルを分割した。 こちらも特に詰まることはなく、ほぼコピペで実装できた。 この対策を実装したことで、ビルド後のJSファイルが以下のように、分割されて生成されるようになった。 Lighthouseの結果 63点→87点に上昇した。 対策4:bootstrap-vueの選択的インポート バンドルサイズ 243KB(app.js.gz) → 129KB(app.js.gz) 解説 対策1~3で、あらかた大きなところは対策できたと思ったので、より細かいところを対応するため、webpack-bundle-analyzerを使ってバンドル結果の分析をした。 webpack-bundle-analyzerの出力結果は以下のようになった。 この結果から bootstrap-vue ckeditor lodash あたりのサイズが大きいらしいことが分かった。...

March 8, 2020 · 1 min

VTuberの簡易ランキングサイトを作った

概要 適当に抽出したVTuberについて、チャンネル登録者数増加数のランキングサイトを作成した。 1日1回、午前5時30分ごろ更新。 構成 Golang + Gin + Bootstrap 雑記 Golangを使ったwebアプリを初めて作成した。Golangは未使用の変数、importがデフォルトでコンパイルエラーになるのが印象的だった。ルールが厳格な印象。 YouTubeの現在の仕様で、チャンネル登録者数が多いほど、刻み幅が大きくなる。その刻み幅分を超えないと、増加量が0になってしまうので、1日単位だと正確なランキングにならない。 今回のサイトを作るにあたって、既存サイトを調べてみた。色々凝っているサイトが多数あった。やはりここら辺(YouTube周り)は色んなビジネスが成り立っているんだろうなと思った。 改訂2版 みんなのGo言語 技術評論社 Amazon Kindle 楽天 楽天Kobo

January 17, 2020 · 1 min

Djangoで記事をカード型で表示するようにした

参考サイト Bootstrap公式ドキュメント https://getbootstrap.com/docs/4.3/components/card/ Card decksの部分をほぼそのまま使った。 css部分は以下のQiitaの記事を参考にさせていただいた。 https://qiita.com/iwato/items/840b831ad66fec0dd4c1 コード html <div class="col-sm-4"> <div class="card card-link post-card"> <a href="{% url 'posts:post_detail' post.id %}"></a> <img class="card-img-top" src="{{ post.middle_image.url }}" alt="thumbnail"> <div class="card-body"> <h5 class="card-title">{{ post.title }}</h5> </div> <div class="card-footer"> <small class="text-muted">published at {{ post.published|date:"Y/n/j" }}</small> </div> </div> </div> 一行に最大3つ記事を表示するためにcol-sm-4を指定している。 記事のサムネイル、タイトル、公開日を表示するようにしている。 css /*div要素全体にリンクをつけるために必要な要素*/ .card-link { position: relative; } .card-link a { position: absolute; top: 0; left: 0; height:100%; width: 100%; } .post-card { margin-top: 5px; margin-bottom: 5px; } カード全体にリンクをつけるために....

October 3, 2019 · 1 min

Djangoでタグクラウドを実装した

参考ページ https://programmer-jobs.blogspot.com/2012/12/djangodjango-taggit.html django-taggitとdjango-taggit-templatetagsがあればできるらしい。 実装した流れ 1 setting.pyを確認し、taggitが導入されていることを確認(taggitは昔すでに導入済み) ただ、taggit-templatetagsは導入されていなかった。 2 pip install django-taggit-templatetagsでインストール 3 setting.pyのINSTALLED_APPSにtaggit-templatetagsを追加 INSTALLED_APPS = ( ... "taggit", "taggit_templatetags", ... ) 4 pip freezeでインストールしたtaggit-templatetagsのバージョンを確認 $ pip freeze ... django-taggit-templatetags==0.2.5 ... 5 requirements.txtに4.で確認したバージョン情報を追記 ... django-taggit-templatetags==0.2.5 ... 6 デプロイ 7 動作確認したらエラー発生 File "...templatetag_sugar/parser.py", line 5, in <module> from django.db.models.loading import cache No module named 'django.db.models.loading' django.db.models.loadingがないらしい。 google先生に聞くと、django.db.models.loadingはDjango1.9で廃止され、現在はdjango.appを使う必要があるようだ。 https://stackoverflow.com/questions/36234635/what-is-the-equivalent-of-django-db-models-loading-get-model-in-django-1-9 8 tamplatetag_sugar/parser.pyを修正 - from django.db.models.loading import cache + from django.apps import apps ....

September 15, 2019 · 1 min

GitHub Pagesを使って静的サイトを公開した

概要 GitHub Pagesを使って簡易ブログを公開しました。 https://kouya17.github.io 構成 公開環境:GitHub Pages 静的サイトジェネレータ:Hugo テンプレートテーマ:aether 雑記 無料でサイト公開できるのはすごい。 静的サイトジェネレータとしてHexoも検討したが、ネット上の情報が中国語中心だったため断念した。 作成物に関する投稿はGitHub Pagesのほうにして、こちらはより雑多なものを扱うことにする。 独習Git 翔泳社 Amazon Kindle 楽天 楽天Kobo

May 2, 2019 · 1 min