GAミント至上主義

Web Monomaniacal Developer.

Google Cloud FunctionsでNode.js 8が使えるようになってる件

Python3.7に引き続き。
これで偉大なるasync/awaitが使えるようになった。
id:takuya_minami373がasync/awaitが無くて困ってPythonで書き直すか、と思ってたところのナイスタイミングで気づいてくれた。
f:id:uyamazak:20180731115545p:plain
おそらくLTSだし、これで気兼ねなくCloud Functionsをjsで書いていけそう。

Vue Cli 3への開発環境移行でつまづいたこと

yagish履歴書は2018年2月ごろから開発を始めた影響で、開発環境が古かったので現時点で最新のVue Cli 3を使った環境に変更中。
rirekisho.yagish.jp

cli.vuejs.org

導入の流れは以前の記事参照
uyamazak.hatenablog.com

つまづいて時間を無駄にした点をいくつかメモしておく。

環境変数(process.env.NAME)が読み込めない

ドキュメントをよく読めば済む話。
以前はjs形式の設定ファイルに書いていたものが、.envファイルになった。

cli.vuejs.org

で、前のから移植して

.env.development

SITE_TITLE=【開発】ブラウザでつくれる履歴書「yagish(ヤギッシュ)」

のように書いて、

process.env.SITE_TITLE

で使おうとしていたが、undefinedになっていた。
でもNODE_ENVだけはそのまま。

以下をよく読めば大丈夫だった。

Using Env Variables in Client-side Code
Only variables that start with VUE_APP_ will be statically embedded into the client bundle with webpack.DefinePlugin. You can access them in your application code:

このバージョンからは頭にVUE_APP_ がついていないと展開されないらしい。
そのため、こう↓して

VUE_APP_SITE_TITLE=【開発】ブラウザでつくれる履歴書「yagish(ヤギッシュ)」
process.env.VUE_APP_SITE_TITLE

こうすれば問題なく使えた。
下手にHOSTNAMEみたいな他でも使う名前を使っちゃうと意図しない上書きが発生するので、明示的でいいかな。

編集後のオートリロードが動かない

ブラウザで開いてコンソールを見ていると

sockjs.js?9be2:1601 GET http://172.17.0.6:8080/sockjs-node/info?t=1533004647392 0 ()

みたいなエラーが定期的に発生していた。
ホットリロード関連の通信のよう。
このIP(172.17.0.6)はyarn serveなどで開発環境を起動すると

  App running at:
  - Local:   http://localhost:8080/
  - Network: http://172.17.0.6:8080/

  Note that the development build is not optimized.
  To create a production build, run yarn build.

と出ていた。Dockerの内部IP?で外からは繋げられないので変更したかったができなかった。
ググるとwebpack-dev-serverの設定のhostとかuseLocalIpを変えるのが出てきたけど、ここは変わらず。

試行錯誤の末、vue.config.jsのdevServer設定内のpublicで変更できた。
// vue.config.js
module.exports = {
devServer: {
public: '192.168.2.70:2104',
host: '0.0.0.0',
port: '8080'
}
}

ここで見つけた。これで6時間ぐらいハマってしまった。
https://github.com/webpack/webpack-dev-server/issues/882

使ってたライブラリが動かない

なんかよくわからないけどいろいろとエラーが出て動かない日本語関連ライブラリがあった。
最終更新が3年前なので直すのはあきらめた。

www.npmjs.com

このライブラリ名でググると最近更新されていて同じようなライブラリが見つかった。

www.npmjs.com

こっちの方が使いやすいがimportでちょっとはまった。
環境によると思うけどドキュメント通りの下記では読み込めず

import toHiragana from 'jaco/lib/toHiragana';

ファイルのパスを書いた下記なら読み込めた

import toHiragana from 'jaco/lib/fn/toHiragana';

何が原因なのかはよくわかってないけど新しくなって、使いやすくなって動いたのでよし。

あとPWA関連も大幅に変更されてるので、これから頑張る

古いバージョンのライブラリに対して新しいバージョンのドキュメントを見ながら設定をがんばってた

PWAのプラグインの設定が反映されないなぁと2時間ぐらいがんばったていたが、気づいたらインストールしてるバージョンが古く、まだ存在しないオプションを設定していた。
Vue Cli 3関連は全体的にまだ開発が進んでるけど、PWAのは特にまだbetaだったので気を付けるべきだった。
package.jsonも頻繁にメンテしていった方がよさそう。

インストールしてたやつ(iconPathsがない)
www.npmjs.com

現時点の最新版
www.npmjs.com

vue-routerでtitleとdescriptionを動的に切り替える

yagishの公開から2週間ぐらいたち、Googleサーチコンソールをみるとtitleタグが同じ、descriptionが同じという、SEO対策でよくある初歩的な警告を目にしたので、なんとかする。

rirekisho.yagish.jp

SPAのSEOはまだ情報が少なくSSR(さーばー・さいど・れんだりんぐ)しないとダメみたいな記事もある。でもSSRをしてないyagishでそんな警告が出るってことはすでにボットがレンダリングしてちゃんと読んでいるもよう。

現在、WebpackでビルドしたフォルダをFirebase Hosting置くだけですみ、運用が楽すぎるので、可能な限り今後もSSRなしでいきたいと思う。

fetch as googleも問題なさそうだし、SEOのためだけのSSRはコスト的にどうなんだろうと思った。

で、titleとmeta descriptionの設定をしてみた。

最初のルーティング設定は下記のような感じで、URL内の変数formatIdを使って履歴書の種類を取得しているが、titleは固定なのでその書式名はtitleに入っていない。

router/index.js

const router = new Router({
  mode: 'history',
  routes: [
    {
      path: '/format/:formatId',
      component: formatDetail,
      props: true,
      name: 'formatDetail',
      meta: {
        title: '詳細 - ' + SITE_TITLE
      }
//省略

router.afterEach((to, from) => {
  if (to.meta && to.meta.title) {
    document.title = to.meta.title
  }
})

そのため、formatIdを渡すとその書式のタイトルなどを返す関数を作る。
データがどこにあるかで実装は大きく異なると思うので、省略する。
ちなみに現在のyagishはローカルのjsファイルにオブジェクトとして書いてあるのでfilterで取ってきてる。

const getFormatMeta = function (formatId) {
  const result = () =>{  /* formatIdでデータを取得する処理 */ }
  return {
    title: result.title,
    description: result.description,
  }
}

次にtitleはdocument.titleで簡単に取得できるが、metaタグのdescriptionは一発では取れずちょっと面倒なので、html側でidを振って、安心と信頼と実績のgetElementByIdで取得することにする。

index.htmlのhead内

    <meta name="description" id="head-meta-description" content="yagish(ヤギッシュ)はブラウザ上で履歴書がつくれる無料サービスです。記入例や入力補助機能がついた履歴書テンプレートを選んで入力するだけ。自宅でも外出先でも、スマホでもパソコンでも、必要なときにいつでも履歴書を作成できます。">

要素とindex.htmlに記述済みのものを変更前にデフォルト値として取っておく。

router/index.js

const metaDescriptionElement = document.getElementById('head-meta-description')
const defaultDescription = metaDescriptionElement.content

// afterEachに追加
router.afterEach((to, from) => {
  if (to.meta && to.meta.title) {
    if (to.params.formatId) {
      const formatMeta = getFormatMeta(to.params.formatId)
      document.title = formatMeta.title + ' - ' + to.meta.title
      metaDescriptionElement.content = formatMeta.description
    } else {
      document.title = to.meta.title
      if (to.meta.description) {
        metaDescriptionElement.content = to.meta.description
      } else {
        metaDescriptionElement.content = defaultDescription
      }
    }
  }
})

とりあえず動いたけど、タイトルを整形する関数とかいろいろ整理しないとページが増えてきたらこのままではやばそう

速習Vue.js 速習シリーズ

速習Vue.js 速習シリーズ

Vue.jsとFirebaseで作るミニWebサービス (技術書典シリーズ(NextPublishing))

Vue.jsとFirebaseで作るミニWebサービス (技術書典シリーズ(NextPublishing))