Gatsby で任意の文字列から QR コードを生成する


コロナウイルスのパンデミックの多くの副作用の 1 つは、QR コードが (再び) 注目を集めたことです.最初に登場したときはどこでも見られましたが、ここ数年はゆっくりと再び姿を消しました.今までは、予防接種証明書やチェックインアプリはすべてQRコードを再び使用していました.

Gatsby で任意の文字列から QR コードを生成するには、複数の方法があります.通常、このような操作にはトランスフォーマー プラグインを設定しますが、現実的には、すべての文字列を QR コードに変換する必要はありません.したがって、createSchemaCustomization API を使用して、新しいフィールドを目的のノードに個別に追加し、特定の兄弟フィールドを変換できます.これにより、作業とビルド時間が節約されます.この YAML スキーマを例として取り上げることができます.

- name: Author's Homepage
  description: Visit the author's homepage for more information and other cool stuff
  link: https://www.lekoarts.de


Gatsby はそこから InformationYaml タイプを生成し、qrCodeDataURL フィールドから生成された QR コードのデータ URI を含む link という追加フィールドが必要です.次に、次のようにクエリできます.

query {
  informationYaml {
    name
    link
    description
    qrCodeDataURL
  }
}


これを行う方法を学ぶために読み続けてください!完成したコードは Codesandbox で見つけることができます.また、Filter Future Posts on a Gatsby Blog をチェックアウトして、同様の例で API を確認することもできます.

設定



変換したい特定のフィールドが設定された Gatsby プロジェクトが既にあると仮定しています.そうでない場合は、npm init gatsby を実行してマークダウン オプションを選択できます.次に、frontmatter を使用して追加のフィールドを追加できます.開発サーバーがまだ実行中の場合は停止します.

私の例では、Gatsby の GraphQL スキーマで InformationYaml として表される YAML ファイルを使用しています.この投稿のイントロでその形を見てきました.

必要な 2 つの依存関係をインストールします.

npm install lodash.get qrcode


QR コードの生成


gatsby-node.js ファイルを開き、インストール済みのパッケージとボイラープレートを追加して Gatsby's schema customization API を使用します.

const get = require("lodash.get")
const QRCode = require("qrcode")

exports.createSchemaCustomization = ({ actions }) => {
  const { createTypes, createFieldExtension } = actions
}


関数 createTypes を使用して、GraphQL 型を明示的に定義します (この場合、GraphQL SDL 構文).

タイプに新しいフィールドを追加する



QR コードはフィールド createFieldExtension で使用できるはずなので、目的の GraphQL タイプに追加する必要があります.

const get = require("lodash.get")
const QRCode = require("qrcode")

exports.createSchemaCustomization = ({ actions }) => {
  const { createTypes, createFieldExtension } = actions

  createTypes(`
    type InformationYaml implements Node {
      qrCodeDataURL: String
    }
  `)
}


しかし、ここでこのフィールドを照会すると、結果として qrCodeDataURL しか得られません.クエリを実行する前に、まずデータを生成する必要があります.

フィールド拡張の作成


null アクションを使用して、新しく作成された createFieldExtension フィールドで使用できるカスタム ディレクティブを作成します.

const get = require("lodash.get")
const QRCode = require("qrcode")

exports.createSchemaCustomization = ({ actions }) => {
  const { createTypes, createFieldExtension } = actions

  createFieldExtension({
    name: "createQRCode",
    args: {
      fieldName: "String!",
    },
    extend({ fieldName }) {
      return {
        resolve: createQRCode(fieldName),
      }
    },
  })

  createTypes(`
    type InformationYaml implements Node {
      qrCodeDataURL: String @createQRCode(fieldName: "link")
    }
  `)
}


しかし、このパズルの最後のピースが欠けています: qrCodeDataURL 関数です.フィールド拡張は、その結果を createQRCode フィールドの値として使用します. qrCodeDataURL には、使用するすべての createQRCode が渡されます (この例では fieldName ).

const get = require("lodash.get")
const QRCode = require("qrcode")

exports.createSchemaCustomization = ({ actions }) => {
  const { createTypes, createFieldExtension } = actions

  const createQRCode = (fieldName) => async (source) => {
    const string = get(source, fieldName)
    let qrCode = ``

    try {
      qrCode = await QRCode.toDataURL(string, { scale: 6 })
    } catch (err) {
      console.error(err)
    }

    return qrCode
  }

  createFieldExtension({
    name: "createQRCode",
    args: {
      fieldName: "String!",
    },
    extend({ fieldName }) {
      return {
        resolve: createQRCode(fieldName),
      }
    },
  })

  createTypes(`
    type InformationYaml implements Node {
      qrCodeDataURL: String @createQRCode(fieldName: "link")
    }
  `)
}

"link" のオプションの詳細については、GitHub page を参照してください.

結果の使用



これで、新しいデータをクエリできるようになりました.開発サーバーを起動し、qrcode の GraphiQL にアクセスします.スキーマを調べると、localhost:8000/___graphql が表示されるはずです.このデータ URI を画像として使用できるようになりました.次に例を示します.

import * as React from "react"
import { graphql } from "gatsby"

export default function Home({ data }) {
  return (
    <main>
      <h1>{data.info.name}</h1>
      <p>
        {data.info.description}: <br />{" "}
        <a href={data.info.link}>Visit the website</a> or scan this QR code:
      </p>
      <img
        alt="QR Code to the authors homepage"
        src={data.info.qrCodeDataURL}
      />
    </main>
  )
}

export const query = graphql`
  {
    info: informationYaml {
      name
      link
      description
      qrCodeDataURL
    }
  }
`