2023/06/01・役立ち情報
経緯
Google Search Index用にサイトマップを作りたくなった。サイトマップの生成自体はsitemapパッケージでどうにかなるが、いちいち全部のルートを取得してリストを作るのは面倒臭い。そこで、nitroに備わっているクローラーを使って、サイト内にあるリンクからルート一覧を生成してみる。
nitroのクローラーは、HTMLに含まれる、「/」で始まるhref属性を含むタグを自動的に認識し、リンク先のルートを生成できる。
壁
nitroでは、クローラーによって自動的に動的ルートのページが生成される。しかし、クロール後のルート一覧を取得する方法が存在しない。そこで、ページを生成するタイミングでフックを挟んで、変数のリストに追加していくことにする。
コード
まず、sitemapパッケージをインストールしておく。
yarn add sitemap
次に、nuxt.config.tsのdefineNuxtConfigの上に以下を追加する。
const hostname = "<hostname>"
const routes: string[] = []
export default defineNuxtConfig({
...
続いて、defineNuxtConfigの中に以下を追加する。
export default defineNuxtConfig({
...
nitro: {
hooks: {
"prerender:route"(route) {
routes.push(route.route)
},
close() {
if (routes.length > 0) {
const links: SitemapItemLoose[] = routes.map(route => ({
url: route,
}))
const stream = new SitemapStream({
hostname,
})
return streamToPromise(Readable.from(links).pipe(stream))
.then((sm) => {
return fs.writeFileSync("dist/sitemap.xml", sm.toString())
})
}
},
},
},
...
})
2023/04/30・お知らせ
いつも本サイトをご覧頂きありがとうございます。
この度、本サイトのコメント欄において、Twitterログイン機能を削除 することといたしましたので、お知らせします。
経緯と今後の対応
こちらのお知らせに記載のものと同等です。
利用者側で必要な対応について
Twitterアカウントを利用してログインされている方は、今後は一度ログアウトしてしまうと、二度とコメントの編集や削除が出来なくなります。
必要なコメントの編集や削除は済ませた上で、ログアウト後に再度Googleアカウントもしくは、今後対応予定のApple IDを使用してログインしてください。
ご不便をおかけしますが、ご理解の程よろしくお願いします。
2023/04/30・お知らせ
いつも「原神素材ヘルパー」をご利用いただきありがとうございます。
この度「原神素材ヘルパー」において、Twitterログイン機能を削除 することといたしましたので、お知らせします。
経緯
現在、Twitterログインに利用していたAPIキーが「ポリシー違反」とのことで停止され、Twitterログインが機能しない状態となっています。これは恐らくTwitter APIのポリシー変更が関係していると思われますが、一切Twitterから連絡が無く、違反内容も全く示されていません。
APIキーを作り直すことも検討しましたが、一時的には動くようになっても再度停止される可能性が高いことから、Twitterログイン機能の削除を行うことにしました。
今後について
4月30日までに、Twitterログインボタンを本アプリから削除します。その代わり、Apple IDでログインできる機能を追加する予定です。
利用者で必要な対応について
Twitterを利用してアカウントを作成された方は、アカウントを削除し、Googleアカウントもしくは、今後対応予定のApple IDを使用して再度作成していただく必要があります。
データは端末にも保存されているため、アカウントを削除した端末と同じ端末で新規アカウントを作成していただければ、データが移行されます。
ご不便をおかけしますが、ご理解をよろしくお願いします。
2023/03/22・役立ち情報
問題発生
IntelliJ IDEA (というか全Jetbrains IDEで共通) でGitのコミットを署名する設定を、Macでこれに従って設定したところ、以下のようなエラーが出てコミットできなくなった。
error: gpg failed to sign the data
fatal: failed to write commit object
原因
いろいろ調べた結果、パスワード入力用のダイアログの表示に失敗している様子。
GPGではセキュリティーのためか、pinentryというソフトでGUIのパスフレーズ入力ダイアログを出し、コンソールに直接パスフレーズを入力することを避けるようにしている。しかし、macOS版のpinentry-macをインストールすると、pinentryとpinentry-macという2種類のコマンドが実行できるようになる。そして、なんと pinentryの方はmacOSでは動かない。
デフォルトではこのpinentryの方が使用されるようになっているため、エラーが発生している様子。~/.gnupg/gpg-agent.confでpinentryのパスを変更できるらしいが、なぜか設定しても反映されない。(いろいろ試したものの…)
そこで、シンボリックリンクの作成という力技で対処することにする。
対処法
まず、現在設定されているpinentryのパス と、 pinentry-macのパス を調査する。
前者は以下のコマンドで調べられる。
% gpgconf
gpg:OpenPGP:/opt/homebrew/Cellar/gnupg/2.4.0/bin/gpg
...
pinentry:パスフレーズ入力:/opt/homebrew/opt/pinentry/bin/pinentry
上の実行結果でいうと、/opt/homebrew/opt/pinentry/bin/pinentryの部分が現在設定されているパス。そして、このファイルを削除する。
% rm <現在設定されているpinentryのパス>
次に、pinentry-macのパスを調べる。
% which pinentry-mac
/opt/homebrew/bin/pinentry-mac
最後に、以下のコマンドでシンボリックリンクを作成する。
% ln -s <現在設定されているpinentryのパス> <pinentry-macのパス>
これでコミットできるようになるはず。
2023/03/14・役立ち情報
問題発生
OGPのサムネイル生成用に、Puppeteerを使ったCloud Functionsの関数をデプロイしようとした。
開発環境(エミュレーター)では正常に動作するのに、なぜかデプロイするとError: could not handle the requestと表示されて動作しなくなる。ログを確認すると、以下のようなエラーが出ていた。
Error: Could not find Chromium (rev. 1095492). This can occur if either
1. you did not perform an installation before running the script (e.g. `npm install`) or
2. your cache path is incorrectly configured (which is: /www-data-home/.cache/puppeteer).
For (2), check out our guide on configuring puppeteer at https://pptr.dev/guides/configuration.
どうやら「Chromiumが見つからねぇよ」というエラーの様子。
結論
以下の手順で解決できる。
functionsディレクトリに.puppeteerrc.cjsファイルを作成し、以下のような中身にする。
/**
* @type {import('puppeteer').Configuration}
*/
module.exports = {
cacheDirectory: require("path").join(__dirname, ".cache", "puppeteer"),
}
firebase.jsonに以下を追記する。(※JSONではコメントの記述はできないため、//以下は削除してください)
"functions": [
{
"source": "functions",
"codebase": "frontend",
"ignore": [
"node_modules",
".git",
"firebase-debug.log",
"firebase-debug.*.log",
".cache" // <= 追記
],
"predeploy": [
"npm --prefix \"$RESOURCE_DIR\" run lint",
"npm --prefix \"$RESOURCE_DIR\" run build"
]
}
],
package.jsonを以下のように変更する。(※JSONではコメントの記述はできないため、//以下は削除してください)
"scripts": {
"lint": "eslint --ext .js,.ts .",
...
"postinstall": "node node_modules/puppeteer/install.js" // <= 追記
},
...
"engines": {
"node": "16" // <= 16にする。詳細は下記。
}
解説
調べてみると、Puppeteerのv19で以下のような破壊的変更があった模様。
use ~/.cache/puppeteer for browser downloads
(https://github.com/puppeteer/puppeteer/releases/tag/v19.0.0)
ホームディレクトリはCloud Functionsのデプロイの対象にならないため、実際に実行される環境でChromiumが存在せず、エラーとなっているようです。
そのため、Puppeteerのインストール先をプロジェクト内に変更してやります。これが1.です。
ちなみに、この状態でnode_modulesを削除してnpm installし直すと、設定したパスに開発端末のOSに合ったChromiumがインストールされます。ここでfirebase deployしようとすると、「パッケージが大きすぎるためデプロイできません」のようなエラーが発生します。これは、Chromium本体がデプロイの対象となっているためで、除外してやる必要があります。これが2.です。まぁどちらにせよCloud Fuctionsの実行OSはLinuxなので、Linux以外を使って開発していると結局デプロイ時にLinux版がインストールし直されます。
あとは、Cloud Functionsではなぜかnpm install時にChromiumが自動的にインストールされないので、postinstallでインストールスクリプトを実行してやります。(3.)
また、Nodeの最新バージョンは18ですが、2023/03/14現在、Node 18用のイメージにPuppeteerの実行に必要なライブラリが含まれていないため、16にします。
2023/01/06・役立ち情報
経緯
GitHub連携を用いて、Cloudflare Pagesでページを公開し、一部のパスでFunctionが実行されるようにしたかったが、なぜかFunctionsだけデプロイされない。
公式ドキュメントの通り、プロジェクトルートにfunctionsディレクトリを作成し、その中にapi/showcase.tsを作り、example.com/api/showcaseでAPIが走るようにしたかった。しかし、そのままデプロイしてもNuxtの静的ページに飛び、Functionsに繋がらない。
対処法
pages functions not recognizedで検索したところ、https://github.com/cloudflare/wrangler2/issues/1859がヒットした。
結論としては、nuxt.config.tsに以下を追記する。
...
nitro: {
preset: "node-server",
},
...
https://github.com/cloudflare/wrangler2/issues/1859#issuecomment-1269616054によると、Nitroでは環境に応じて自動的に適切なプリセットが選択され、Cloudflare Pagesではcloudflare-pagesが設定されるようになります。本来はnuxt generate時に.output/publicに/functionsがコピーされるべきですが、Nuxt3の/serverとして扱われ、認識できるexportが存在しないことからレンダリング前に/functionsが空っぽにされ、結果全くデプロイされないようです。(私の認識が正しければ)
2022/12/13・動画ウラ話
ここ最近、CIにおいてfirebase login:ciで取得できるトークンを利用することが非推奨になり、Workload Identity 連携を使用することが推奨されるようになりました。今回は、それを用いてFirebase Hostingに自動デプロイするワークフローを作る方法を解説します。
img {
max-width: unset !important;
max-height: unset !important;
}
Firebaseの準備
まず、Firebase ConsoleからFirebaseプロジェクトを作成します。Google アナリティクスについては必要に応じて有効化します。今回は有効にしませんでした。
次に、自分のPCでディレクトリを作成し、firebase initします。選択内容は下を参照してください。
? Which Firebase features do you want to set up for this directory?
--> Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys
? Please select an option:
--> Use an existing project
? Select a default Firebase project for this directory:
--> workload-test-xxxxx (workload-test)
? What do you want to use as your public directory?
--> public
? Configure as a single-page app (rewrite all urls to /index.html)?
--> No
? Set up automatic builds and deploys with GitHub?
--> No
GitHubレポジトリの作成
GitHubでレポジトリを作成しておきます。方法については割愛します。
Workload Identity 連携の設定
Google Cloud Platform ConsoleからWorkload Identity 連携の設定をします。こちら にアクセスしてください。
「使ってみる」をクリックします。
「名前」を「GitHub Actions」にし*1、「続行」をクリックします。
*1 名前は任意ですが、今後この名称を使用して説明するため同じにすることを推奨します。
以下のように入力して「続行」をクリックします。
名称
値
プロバイダの選択
OpenID Connect (OIDC)
プロバイダ名
GitHub
発行元(URL)
https://token.actions.githubusercontent.com
オーディエンス
許可するオーディエンス
対象1
自身のGitHubプロフィールURL(https://github.com/<ユーザー名>の形式)
属性マッピングで以下のように設定します。(「マッピングを追加」をクリックすると2個目が表示されます)
Google
OIDC
google.subject
assertion.sub
attribute.repository
assertion.repository
次に、「属性条件」で「条件を追加」をクリックし、「条件CEL」に'<GitHubユーザー名>/<レポジトリID>' == attribute.repositoryの形式で入力します。
サービスアカウントの作成
次に、デプロイ用のサービスアカウントを作成します。コンソール上ではこのアカウントでデプロイしたことになります。左のメニューから「サービスアカウント」を選択し、上部の「サービスアカウントの作成」をクリックします。
まず、サービスアカウント名に「github-actions」など適当な名前を設定し、「作成して続行」をクリックします。次に、「このサービス アカウントにプロジェクトへのアクセスを許可する」で「ロールを選択」から以下の2つを追加します。
サービス アカウント ユーザー
Firebase Hosting 管理者
Firebase Cloud Functionsも利用している場合、以下の3つも必要になる場合があります。
Cloud Functions 管理者
Cloud Scheduler 管理者
Secret Manager 管理者
最後に「続行」「完了」をクリックします。
(※ロール設定は「IAMと管理」画面の左メニュー下「リソースの管理」→プロジェクトを選択→右側の情報パネルから編集できます。ロールを追加する場合は「プリンシパルの追加」から「新しいプリンシパル」にサービスアカウントIDを入力します。)
サービスアカウントとWI連携の紐付け
次に、この2つを紐付けます。左メニューから「Workload Identity 連携」をクリックし、先程作成したWIプール(GitHub Actions)をクリックし、上部の「アクセスを許可」をクリックします。「サービスアカウント」から先程作成したサービスアカウントを選択し、「保存」をクリックします。
ワークフローファイルの作成
ここでやっとワークフローを作成します。.github/workflows/deploy.ymlファイルを作成してください。以下が雛形になります。
name: Deploy
on:
push:
branches:
- main
workflow_dispatch:
repository_dispatch:
env:
workload_identity_provider: <Workload Identity プロバイダー>
service_account: <サービスアカウントID>
jobs:
deploy-to-hosting:
name: "Deploy to Hosting"
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
cache: yarn
- name: Install Firebase CLI
run: yarn global add firebase-tools
- name: 'Authenticate to Google Cloud'
id: auth
uses: 'google-github-actions/auth@v0'
with:
workload_identity_provider: ${{ env.workload_identity_provider }}
service_account: ${{ env.service_account }}
audience: https://github.com/<GitHubユーザー名>
- name: Deploy to Firebase Hosting
run: firebase deploy --only hosting
「Workload Identity プロバイダー」は以下の形式に従ってください。
projects/<プロジェクトID>/locations/global/workloadIdentityPools/<WIプールのID(github-actions)>/providers/<プロバイダーID(github)>
「サービスアカウントID」は左メニュー「サービスアカウント」より先程作成したサービスアカウントをクリックすると表示されるメールアドレスです。
肝は
permissions:
contents: read
id-token: write
の部分です。これがないと認証に失敗します。
お気づきかもしれませんが、そう。トークンなどの機密情報を人の手で管理する必要が一切ありません__。__設定を適切にすれば Workload Identity プロバイダーやサービスアカウントIDだけ知っていても誰も悪用できないため、ハードコードしても全く問題ありません。設定はめちゃくちゃ面倒臭いですが、セキュリティは最強です。
Pushする
最後に、このディレクトリをGitHubにPushすれば、public以下がデプロイされるはずです。めでたしめでたし。
2022/11/26・どうでもいいこと
割とフィーリングで適当に撮影して、「これ良くね」って思ったテイクを載せます。
※上の6つはiOS版で撮影しているため、画質が低いです。
2022/11/22・お知らせ
(この記事はHoYoLABに投稿したものと同じものです。)
こんにちは。
「原神素材ヘルパー」のv3.10.0を公開しましたので、何が変わったのかお知らせします。
(原神素材ヘルパーって何?って方はこちら)
武器を装備するキャラの登録
以前までは同じ武器は1つまでしか収集中マークできませんでしたが、キャラ単位でマークが行えるようになりました。
また、ゲームデータと同期する機能においても、上記機能を追加したことにより、武器の育成状況の同期が可能になりました。
「収集中の素材」リストの表示改善
(1分で作った比較画像)
収集中の素材」で「素材ごとに表示」をオンにした時の表示を大幅に改善しました。言葉で説明するより上の画像を見てもらったほうが早いと思います。
また、リストの親にもブックマークボタンを追加し、子となる素材を一括で収集中マーク解除できます。
最後に
1年ほど前に公開した本アプリですが、今も細々と更新は続けています。何かご意見がありましたら、コメント欄で頂けると助かります。
2022/11/19・役立ち情報
問題は起きた。
Jetbrains社のIDE、IntelliJ IDEA / WebStorm でNuxt3を使おうとすると、#importsからインポートしないとメソッドが解決されない。どうやら、VSCodeのプラグインはインポートしなくても解決できるようになっている模様。
これはめちゃくちゃ面倒臭い。
対処法
__imlファイルを編集し、.nuxtディレクトリを処理(インデックス)の対象に含めます__。通常、IntelliJ IDEAでは、「.(ドット)」から始まる隠しディレクトリはGUIでインデックスの対象に含めることができません。なので、プロジェクトの設定ファイルを直接編集します。
[プロジェクトルート]/.idea/[プロジェクト名].imlを開きます。そして、以下を追記します。
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<!-- 略 -->
<content url="file://$MODULE_DIR$/.nuxt" /> <!-- 追記 -->
<!-- 略 -->
</component>
</module>
こうすると、composableなどがimportなしで使えるようになります。