Next.jsでfaviconを設定する

PR

github.com

Projectの構成はこのような形

$ tree src/pages public
src/pages
├── _app.tsx
├── _document.tsx
└── index.tsx
public
└── static
    └── favicon
        ├── android-chrome-192x192.png
        ├── android-chrome-512x512.png
        ├── apple-touch-icon.png
        ├── browserconfig.xml
        ├── favicon-16x16.png
        ├── favicon-32x32.png
        ├── favicon.ico
        ├── mstile-150x150.png
        └── site.webmanifest

1. publicディレクトリし、画像を置く

project直下にpublicというディレクトリを作成してfaviconの画像ファイルを置いてください。 以前はstaticというディレクトリ名でしたが、非推奨になりました。

github.com

2. pages/_document.tsxを作成し、link tagを追加する

nextjs.org

import Document, { Head, Main, NextScript } from "next/document";

export default class MyDocument extends Document {
  render() {
    return (
      <html>
        <Head>
          <link
            rel="apple-touch-icon"
            sizes="180x180"
            href="static/favicon/apple-touch-icon.png"
          />
          <link
            rel="icon"
            type="image/png"
            sizes="32x32"
            href="static/favicon/favicon-32x32.png"
          />
          <link
            rel="icon"
            type="image/png"
            sizes="16x16"
            href="static/favicon/favicon-16x16.png"
          />
          <link rel="manifest" href="static/favion/site.webmanifest" />
          <meta name="msapplication-TileColor" content="#da532c" />
          <meta name="theme-color" content="#ffffff" />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </html>
    );
  }
}

3. build and exportして確認する

$ npm run build && npm run export

Next.jsでSVG画像をReact Componentとして描画する

@svgr/webpackを利用する。

react-svgr.com

npm install @svgr/webpack --save-dev

# or use yarn

yarn add @svgr/webpack --dev

next.config.js

module.exports = {
  webpack(config) {
    config.module.rules.push({
      test: /\.svg$/,
      issuer: {
        test: /\.(js|ts)x?$/,
      },
      use: ["@svgr/webpack"],
    });

    return config;
  },
};

github.com

react-svg-loaderを利用する

github.com

npm install react-svg-loader --save-dev

# or 

yarn add react-svg-loader --dev

next.config.js

const path = require("path");

module.exports = {
  webpack(config) {
    config.module.rules.push({
      test: /\.svg$/,
      include: [path.resolve(path.resolve(), "src/images")],
      use: ["react-svg-loader"],
    });

    return config;
  },
};

個人的には@svgr/webpackのほうがスマートに見えるのでそっちを利用する。お好みで。

TerraformでAWS LambdaLayer with Python を利用する

ほぼclassmethodさんの記事通りですが

ソースコード

github.com

$ tree
.
├── README.md
├── build-layer.sh
├── iam.tf
├── lambda
│   ├── function.zip
│   └── lib.zip
├── lambda.tf
├── provider.tf
├── requirements.txt
├── src
│   └── index.py
├── terraform.tfstate
├── terraform.tfstate.backup
└── variables.tf

DeployするLambda functionのソースコード

import os
import sys
import requests
from bs4 import BeautifulSoup


def lambda_handler(event: dict, context):
    response = requests.get("http://example.com/")
    bs = BeautifulSoup(response.text)
    return bs.title.name

lambda functionでrequestsとBeautifulSoupを使いたい。そのためにlambda layerを利用する。

Lambda Layer

見るのはlambda.tfとbuild-layer.sh

data "archive_file" "function" {
  type        = "zip"
  source_file = "./src/index.py"
  output_path = "lambda/function.zip"
}

data "archive_file" "layer" {
  type        = "zip"
  source_dir  = "./lib"
  output_path = "lambda/lib.zip"
}

resource "aws_lambda_layer_version" "layer" {
  filename         = "${data.archive_file.layer.output_path}"
  layer_name       = "lib"
  source_code_hash = "${data.archive_file.layer.output_base64sha256}"

  compatible_runtimes = ["python3.6"]
}

resource "aws_lambda_function" "example_lambda" {
  function_name = "example_lambda"

  runtime          = "python3.6"
  handler          = "index.lambda_handler"
  filename         = "${data.archive_file.function.output_path}"
  role             = "${aws_iam_role.iam_role.arn}"
  source_code_hash = "${data.archive_file.function.output_base64sha256}"
  layers           = ["${aws_lambda_layer_version.layer.arn}"]
}

肝になるのはlambda functionとlayerのsourceの参照先の違い。

lambda functionのソースコードproject/src/index.pyを利用するが、 lambda layerは lib/ を利用する。pipライブラリのinstallについてはnull_resourceを利用してterraformで完結しようとしたが、うまく出来なかったので、shellファイルで実行する。何か良い方法あれば教えてほしい

#!/usr/bin/env bash

if [ -d lib/ ]; then
  rm -rf lib/
fi

echo "bundle pypi packages"
pip install -r requirements.txt -t lib/python

find lib -type f | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm

pip installで lib/python を指定しているのはlambda functionからlambda layerを参照するpathを通すため。lib/packagesなどではpathが通らないので注意。 __pycache__と.pyc、pyoを削除しているが、これはpip installをしても__pycache__配下のファイルの影響で差分が発生してしまうから。

$ sh build-layer.sh
$ terraform plan
$ terraform apply

参考

Markdown文書で画像の表示にURLを使わず埋め込む

今回から技術記事はHatenaBlogに書いていこうと思います。

忘備録

Markdownに画像を表示する場合、どうしていますか。おそらくimgurやGitHubなどに画像をアップロードしてURLを参照していると思います。

imgur.com

![airplane](https://homepages.cae.wisc.edu/~ece533/images/airplane.png)

が、機密性のある画像のURLをpublicに公開したくはないが、Markdownで書きたい場合はどうすればよいか。

A. Data URI schemeを使う

Data URI Schemeとはと言う方はWikipediaをどうぞ。

ja.wikipedia.org

何でも良いですが、画像をbase64 encodingします。

$ base64 airplane.png > airplane_base64.txt
![airplane](data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAIAAAB7GkOtAAAAB3RJTUUH0AESFgINTbbB1gAAAAlwSFlzAAC4jAAAuIwBzPa7LwAG32VJ.....)

この様に画像のURLを使わずに画像を埋め込むことが出来ました。

f:id:teitei_tk:20200425113315p:plain
markdown preview

問題点

GitHub flavored markdownではセキュリティ上に理由でbase64を利用した画像は使えません。

github.com

この点はGitHub flavoerd markdownを利用する時点である程度publicな文書だと思うのでおとなしくGitHubに画像をアップロードして使ったほうが良さそう。

ワイヤレスヘッドホン "Bose QuietComfort 35" レビュー

5年ほど前に使っていたヘッドフォンがご臨終なされました。

ついに長年使っていたヘッドフォンが壊れてしまった。南無。

使っていたのは Audio-TechnicaATH-A900というやつを使っていました。

audio-technica アートモニターヘッドホン  ATH-A900

audio-technica アートモニターヘッドホン ATH-A900

確か1万〜2万の間だったかな。そういった意味では十分にペイしたかなと思います。南無。

というわけで新しいヘッドフォンを探した。

イヤホンでも良いんですが、個人的にはヘッドフォンが良いなという事でヘッドフォンをメインに探してみました。
今回重視した点としては

  • ワイヤレスヘッドホンであること
  • 通勤時〜仕事中でなるべくシームレスに使えること
    • 通勤中はiPhone ~ 社ではMacに繋げることが出来る。
  • そこそこの音質

というわけで色々探していたら友人がBose QuietComfort 35を使っているとの事だったので、
いろいろと調べてみて、実際に店舗で視聴をして購入を決めた。

新しいヘッドホンを手に入れた。が、オタクなのでアニソンしか聞かないし、無駄感あるのは無視しておきます。

www.bose.co.jp

購入を決めた理由

ワイヤレスヘッドホンであること

これまであまり意識をしていなかったのですが、ワイヤレスヘッドホンは神。 線が無いので、仕事中席から少し離れて飲み物を取りに行く際にもつけたままなのはかなり良い。
通勤中も、仕事中もだいたいヘッドフォンをつける or 首に下げておいています。

無線LANが当たり前になっている今日このごろですが、改めてWirelessの利点を認識した。 Bluetoothが使えない端末のために有線のケーブルも入っているので、問題ない。

Nintendo SwitchBluetoothに対応してクレメンス・・・。

iPhone ~ Macでシームレスに使えること

これに関しては想像以上に良かったです。
専用のアプリでBose Connectというアプリがある。

www.bose.co.jp

これで接続先、iPhoneへの同期、接続先を選ぶことが出来る。 Bose Connectなのか、"QuietComfort 35"だからなのかは分からないが、同時に2台まで接続が出来る。

例えばFireTvStickに繋ぎながら冴えない彼女の育て方♭を見つつ、iPhoneFate G/Oをやるという事が出来る。
もちろん、両者の音は聞こえます。

接続先に繋いだ or 切れた場合は、機械音声でデバイスの接続状況をヘッドフォンから教えてくれるのでそこも体験としては良かった。
なお、発音する言葉は(お察し下さい

そこそこの音質

そこまで音質にはこだわらないが、でも一応の音質は欲しいと思っていたのでここは視聴して聞いてみた。
耳が貧弱なので、どういった音声なのかというのは分からないが、一定以上の音質であることは間違いないと思う。

使ってみた感想

Bluetoothなので不安定

無線の宿命なのか音がぶつ切りになることが多いです。
安定しているときもあるし、不安定なときもあったりと再現条件が謎。
まあ、ここは仕方ないかなと思っている。

バッテリーの持ち

バッテリーはそこそこ持つ印象です。
届いて初日にほぼほぼフル稼働で1日使ってみた結果、およそ40%ぐらい減りました。

物理ボタン

全てアプリというわけではなく、電源と音量調整、再生停止のボタンが物理である。
電源のオン・オフは1秒ほどで出来るので使わない時はすぐにオフにすることが出来る。

実はAudioTechnicaのATH-CKS55XBTというワイヤレスイヤホンを持っていたのですが、
電源のオン・オフが面倒で使わなくなった経緯があった、ここも良かったです。

所感

ぶつ切りになる事はありますが、どこに行くときでも持ち歩けるぐらいの大きさで、 なおかつワイヤレス、iPhoneをハブにして色んなデバイスに繋ぐことが出来るなど、かなり良い製品だと思います。