tyankatsu’s blog

カレーと炭酸が苦手なほうれん草好きマンの技術ブログとか

Gridsomeを使ってみる【開発環境編】

最近仕事でGraphQLを触る機会が多く、APIは全部GraphQLみたいにエンドポイント一つになってくれないかなーと思っていたら、こちらのようなパッケージが登場しました。 現時点ではv0.2.5です。 https://gridsome.org/

Gridsomeとは

ざっくりと

  • GraphQLレイヤーを内包している(https://gridsome.org/docs/graphql)
  • 外部API(WP REST APIとか)をGraphQLレイヤー向けに変換するのでAPIが使いやすい
  • vueファイル内で独自タグを採用している(<page-query>とか)ので、vueファイル内でGraphQLライクに情報を引っ張れる
  • JAMstackを目指していて、static site generatorになっている。(SSRにもできるらしいけど未確認)
  • graphiqlみたいな機能を搭載している
  • 独自コンポーネントが存在する(https://gridsome.org/docs/link)
  • v1.0.0に向けて機能を足していっている途中。ロードマップ GraphQL

開発するにはいろいろ足りない

vue-cliのエコシステムみたいなのがあればよかったんですが、それもないので自前で用意していきます。 以下使用したパッケージと用途です。

パッケージ 用途
gridsome Gridsomeの大元
gridsome/packages/source-wordpress GridsomeでwordpressAPIを使用するため
stylelint stylelintを効かせる
stylelint-config-prettier prettierとstylelintのバッティングルール回避
stylelint-config-recess-order stylelintのルール拡張
stylelint-config-sass-guidelines stylelintのルール拡張
eslint eslintを効かせる
eslint-config-airbnb-base eslintのルール拡張
eslint-plugin-vue eslintのルール拡張
eslint-config-prettier prettierとeslintのバッティングルール回避
eslint-plugin-prettier eslint使用時にprettierも使用
commitizen cz-cliでcommit commentを作る
fixpack package.jsonのフォーマットをする
lint-staged commit時にlintを適用させる
postcss-loader postcssを使用するため
autoprefixer ベンダープレフィックスを自動で効かせる
sass-loader vueファイル内でsassを使用するため
node-sass vueファイル内でsassを使用するため
sass-resources-loader 変数のimportとかの手間を省くため
npm-run-all npm scriptの並列・直列処理のため
dotenv 環境によって値を変えたり、見せたくない値を設定するため

これらの中で使い方が迷いそうなもの設定例を見ていきます。
なお、著者のnode環境は以下のとおりです。

  • node: v10.11.0
  • npm: 6.4.1
  • yarn: 1.10.1
  • node管理ツール: ndenv

こちらのリポジトリで試行錯誤中です。
github.com

環境変数を異なる環境で使い分ける

Gridsomeでwordpressを使用するためにはgridsome.config.jsに以下のような記述をします。

{
      use: "@gridsome/source-wordpress",
      options: {
        baseUrl: "WEBSITE_URL",
        typeName: "WordPress",
        perPage: 100,
        concurrent: 10,
        routes: {
          post: "/:year/:month/:day/:slug",
          post_tag: "/tag/:slug"
        }
      }
    }

baseUrlにはwordpressのURLを記入します。
これが例えば開発環境ではhttp"//localhost:3000で、本番はhttp://www.example.comだったりすると、都度書き換えるのは面倒です。 そのためdotenvを使用し、.envファイルを参照してGridsomeを起動させることにします。

// .env
VUE_APP_BASE_URL = http://exapmle.com

// gridsome.config.js
require("dotenv").config();
module.exports = {
  plugins: [
    {
      use: "@gridsome/source-wordpress",
      options: {
        baseUrl: process.env.VUE_APP_BASE_URL,
        typeName: "WordPress",
        perPage: 100,
        concurrent: 10,
        routes: {
          post: "/:year/:month/:day/:slug",
          post_tag: "/tag/:slug"
        }
      }
    }
  ]
};

これでbaseUrl: process.env.VUE_APP_BASE_URL
baseUrl: 'http://exapmle.com',と同じになりました。

dotenvを使用する際には.envは.gitignoreでgit管理対象外にしましょう。

これでnpm scriptsにこのように書けば環境変数を使い分けることが可能になります。

"scripts": {
  "gs:build": "gridsome build",
  "build": "run-s env-production gs:build",
  "gs:develop": "gridsome develop",
  "develop:dev": "run-s env-develop gs:develop",
  "develop:prod": "run-s env-production gs:develop",
  "env-develop": "cp config/env/.env.develop ./.env",
  "env-production": "cp config/env/.env.production ./.env",
}

config/env.env.develop.env.productionを作ったので、それらを適宜.envにコピーして使い分けます。

clientサイドでもprocess.envを使用したい

vue-cliにはこのような機能があるのですが、webpack.DefinePluginの機能で実現しているようです。
Gridsomeには標準ではこのような機能は搭載されていないので自力で搭載する必要があります。

config/env.jsというものを作成してみます。

let originEnv = require("dotenv").config();
originEnv = originEnv.parsed;

function middleware(value) {
  if (value === "true") return true;
  if (value === "false") return false;
  if (value === "0" || value === 0) return 0;
  return value || null;
}

exports.getEnvs = () => {
  let env = {};
  for (let key in originEnv) {
    if (originEnv[key]) {
      env["process.env." + key] = JSON.stringify(middleware(originEnv[key]));
    }
  }
  return env;
};

dotenvはプロジェクト直下にある.envを見ます。
その中身を取り出してオブジェクトに変換し、それぞれのキーのprefixをprocess.envにしました。

// .env
HOGE = hogehoge
FUGA = fugafuga

// env.jsを介すと
{
  process.env.HOGE: 'hogehoge',
  process.env.FUGA: 'fugafuga',
}

console.log(process.env.HOGE)
// => 'hogehoge'

.envからオブジェクトが作成できるようになったので、これをDefinePluginに設定します。

gridsome.config.jswebpack-chainを使えるので、このように書きます。

const path = require("path");
const { DefinePlugin } = require("webpack");
const env = require(path.join(__dirname, "/config/env.js"));

module.exports = {
  chainWebpack: config => {
    config.plugin("env").use(DefinePlugin, [env.getEnvs()]);
  }
};

これでvueファイル内であってもprocess.env.XXXXが使えるようになりました。

vueファイル内でscssが使いたい

これは

yarn add node-sass sass-loader -D

するだけで使えるようになります。

autoprefixerが使いたい

必要なパッケージをインストールし、プロジェクト直下にファイルを設置します。

yarn add postcss-loader autoprefixer -D
// .postcssrc

module.exports = {
  plugins: {
    autoprefixer: {}
  }
};

こちらもプロジェクト直下に設置しましょう。

.browserslistrc

> 1%
last 2 versions
not ie <= 8

以上です。

sassの変数をいろいろなところで使用したい

yarn add sass-resources-loader -D
const path = require("path");

module.exports = {
  chainWebpack: config => {
    const oneOfsMap = config.module.rule("scss").oneOfs.store;
    oneOfsMap.forEach(item => {
      item
        .use("sass-resources-loader")
        .loader("sass-resources-loader")
        .options({
          resources: [
            path.resolve(`${__dirname}/src/styles/`, "variables/importer.scss")
          ]
        })
        .end();
    });
  }
};

以上です。

Nuxtみたいにページ間遷移にtransition効かせたい

現状機能が搭載されていません。 v1.0で搭載される予定のようです。

とりあえずの対処法として

// layouts/Default.vue
<transition-group name="page" tag="main" appear>
    <div key="main">
        <slot></slot>
    </div>
</transition-group>



.page-enter-active,
.page-leave-active {
  transition: 0.4s;
}

.page-enter,
.page-leave-to {
  opacity: 0;
  transform: translateX(20px);
}

とすればいけますが。(1.0が待ち遠しい!!!)

感想

著者はnuxtはあまり触ったことはなく、職場でvue-cli@3を使用したプロダクトの開発をしているので、いろいろ設定がしんどかったです。
特にdotenvは手こずりました。
本記事がGridsomeを試す際の何らかの手助けになれば幸いです。

次回予告

Gridsomeを使ってみる【apiにクエリ発行編】として、 実際にwordpressの記事を取得して表示させるまでを紹介したいと思います。