Vue3向けのコンポーザブルライブラリ作ってみた。

React向けのカスタムフックライブラリを見てみると、useListというカスタムフックがあった。
Vue3向けにこういうライブラリ作れそうだなーと思ったので、ライブラリの作成の練習としてやってみた。

とりあえず、結果としてできたのが以下です。npmへのリンクとGitHubへのリンクを貼ります。

www.npmjs.com

github.com

とりあえず、ライブラリ作成に関しての知見がゼロなので、Vueのコミュニティで「参考記事ないですかー」と問うたら、@kazuponさん(Vue-I18nというライブラリを作られている方)から、参考となる記事をいただいた。
Vueのコミュニティの暖かさに感謝。

参考となる記事をベースに、自分でライブラリを作ってみたら、かなり簡単にできた。
また作ろ

Laravel sailのシェルスクリプトの中身を見てみる。

Laravelの環境構築に便利なsail。curlコマンド一発で呼び出せて、withである程度好きな構成で立ち上げられる。
しかし、バージョンを指定して構築できない。

適当に素振りする程度だとあまり困らないが、ハンズオン的な資料を見つつやるとディレクトリ構成などがバージョン毎に異なっていて戸惑うことがある。
バージョン指定できない理由がわからないため、とりあえずシェルスクリプトの中身を見てみることにしてみた。

シェルスクリプトを覗いてみる

以下のURLをクリックすることで、ブラウザ上でシェルスクリプトの中身が見れる。
https://laravel.build/project_name

または、curlコマンドを利用してローカル上にファイルを作成する
curl https://laravel.build/project_name -o laravelsail.sh

とりあえず以下に展開してみる。あまり中身難しくなくてホッとした。
わかる範囲で、コメントを付けてみた。

# Dockerの有無確認
docker info > /dev/null 2>&1

# Ensure that Docker is running...
if [ $? -ne 0 ]; then
    echo "Docker is not running."

    exit 1
fi

docker run --rm \
    --pull=always \
    -v "$(pwd)":/opt \
    -w /opt \
    laravelsail/php82-composer:latest \
    bash -c "laravel new project_name && cd project_name && php ./artisan sail:install --with=mysql,redis,meilisearch,mailpit,selenium " # laravel/installerを利用してLaravelを構築して、sailをインストールしている

# プロジェクトフォルダに移動
cd project_name

# ここはよくわからない。なぜこの条件…?
# Allow build with no additional services..
if [ "mysql redis meilisearch mailpit selenium" == "none" ]; then
    ./vendor/bin/sail build
else
    ./vendor/bin/sail pull mysql redis meilisearch mailpit selenium
    ./vendor/bin/sail build
fi

CYAN='\033[0;36m'
LIGHT_CYAN='\033[1;36m'
BOLD='\033[1m'
NC='\033[0m'

echo ""

# 構築したディレクトリ配下の所有者を$USER変更
if sudo -n true 2>/dev/null; then
    sudo chown -R $USER: .
    echo -e "${BOLD}Get started with:${NC} cd project_name && ./vendor/bin/sail up"
else
    echo -e "${BOLD}Please provide your password so we can make some final adjustments to your application's permissions.${NC}"
    echo ""
    sudo chown -R $USER: .
    echo ""
    echo -e "${BOLD}Thank you! We hope you build something incredible. Dive in with:${NC} cd project_name && ./vendor/bin/sail up"
fi

Laravelのインストールにはlaravel/installerを利用している。
このlaravel/installerがバージョン指定できず、必ず最新のLaravelのバージョンを取得しているよう。なんでだろう。

Laravelの特定のバージョンを指定してインストールしたい場合には、laravel/installerを利用せず、composer経由でインストールを行えば良い。
コマンドとしては以下のようになる。
composer create-project "laravel/laravel={{ version_number }}" dirname

シェルスクリプトをバージョン指定できるように変更してみる。

先程の項で、シェルスクリプトを覗いた結果、どこの部分を変更すればLaravelの特定のバージョンを指定できるかがわかったので、それを反映してみる。

docker info >/dev/null 2>&1

# Ensure that Docker is running...
if [ $? -ne 0 ]; then
    echo "Docker is not running."

    exit 1
fi

docker run --rm \
    --pull=always \
    -v "$(pwd)":/opt \
    -w /opt \
    laravelsail/php82-composer:latest \
    bash -c "composer create-project 'laravel/laravel={{ version }}'  {{ project_name }} && cd {{ project_name }} && php ./artisan sail:install --with=mysql,redis,meilisearch,mailpit,selenium "

cd {{ project_name }}

# Allow build with no additional services..
if [ "mysql redis meilisearch mailpit selenium" == "none" ]; then
    ./vendor/bin/sail build
else
    ./vendor/bin/sail pull mysql redis meilisearch mailpit selenium
    ./vendor/bin/sail build
fi

CYAN='\033[0;36m'
LIGHT_CYAN='\033[1;36m'
BOLD='\033[1m'
NC='\033[0m'

echo ""

if sudo -n true 2>/dev/null; then
    sudo chown -R $USER: .
    echo -e "${BOLD}Get started with:${NC} cd project_name && ./vendor/bin/sail up"
else
    echo -e "${BOLD}Please provide your password so we can make some final adjustments to your application's permissions.${NC}"
    echo ""
    sudo chown -R $USER: .
    echo ""
    echo -e "${BOLD}Thank you! We hope you build something incredible. Dive in with:${NC} cd project_name && ./vendor/bin/sail up"
fi

大した変更はしてなくて、laravel newしているところをcomposer create-projectとしただけ。 使う機会あるかわからないけど、自分向けに。
withの部分やdevcontainerはお好きなように。

【備忘録】Laravel + Vue3 + Inertia.jsの環境構築方法

最近、LaravelとVueの組み合わせで苦しいという話があって、Inertia.jsがそれを救ってくれるかもしれないという話からInertia.jsを素振りし始めた。
ただ、Inertia.jsのInstallationでつまづいたので、備忘録として、ブログに残しておく

Laravelの環境構築

sailを使って、Laravelの環境構築を行う。DBはmysqlよりpostgresを利用したいため、withクエリでpgsqlを指定する。

# Laravelの環境構築
curl -s "https://laravel.build/{{ project_name }}?with=pgsql" | bash
# {{ project_name }}に移動
cd {{ project_name }}

サーバーサイド側の設定

Laravelの環境構築が終わったらサーバーサイド側の設定を行っていく。
sailコマンドは、.bashrcまたは.zshrcにaliasを設定しているものとして、進めていく。

inertiajs/inertia-laravelのインストール

sail composer require inertiajs/inertia-laravel

インストール完了後は、以下コマンドを実行してミドルウェアを生成する。

sail artisan inertia:middleware

app/Http/Middleware/HandleInertiaRequests.php が生成される。

app/Http/Kernel.phpの修正

先手順で生成したファイルを、app/Http/Kernel.phpファイルに追記する。

<?php
// 省略
protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \App\Http\Middleware\HandleInertiaRequests::class, // <- 最後に追記
    ],

    'api' => [
        // 省略
    ],
];

optional1: tightenco/ziggy をインストールする

この手順は公式にもないため、オプションとなるが、設定をするとVueファイルからLaravelのルーティングをroute('routing.name')このように指定可能となるため、便利。
以下コマンドで、tightenco/ziggyをインストールを行う。

# インストール
sail composer require tightenco/ziggy

テンプレート追加

エントリポイントとなる、bladeファイルを追加する。
または既存のwelcome.blade.phpファイルをリネームする

touch resources/views/app.blade.php
# or
mv resources/views/welcome.blade.php resources/views/app.blade.php

テンプレート修正

先手順で追加したapp.blade.phpファイルの内容を以下の内容に変更する

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
    @routes
    @vite('resources/js/app.js')
    @inertiaHead
</head>
<body>
    @inertia
</body>
</html>

@routesについては、optional: tightenco/ziggy をインストールするの項をスキップした場合は不要となる。

クライアントサイド側の設定

クライアントサイドの設定を行っていく。
このあたりの手順でつまづいた。

必要なパッケージのインストール

sail npm install @inertiajs/vue3 vue @vitejs/plugin-vue

vite.config.jsの設定

vite.config.jsの設定を行う

import { defineConfig } from "vite";
import laravel from "laravel-vite-plugin";
import vue from "@vitejs/plugin-vue";

export default defineConfig({
    plugins: [
        laravel({
            input: ["resources/css/app.css", "resources/js/app.js"],
            refresh: true,
        }),
        vue({
            template: {
                transformAssetUrls: {
                    base: null,
                    includeAbsolute: false,
                },
            },
        }),
    ],
});

optional2: pluginを作る

optional: tightenco/ziggy をインストールするの項をスキップした場合は不要な手順。

tightenco/ziggyをインストールしただけでは、Vueのtemplateからroute にはアクセスできないので、プラグインを作成し、Vueのtemplateからアクセスできるようにする。

以下コマンドでディレクトリとファイルを作る

mkdir resources/js/plugins
touch resources/js/plugins/ziggy.js

プラグインを作ると言っても中身は単純で、以下の様に記載すれば良い。

export default {
    install(app) {
        app.config.globalProperties.$route = route;
    },
};

app.jsを編集

app.jsの編集を行う

import "./bootstrap";
import { createApp, h } from "vue";
import { createInertiaApp } from "@inertiajs/vue3";
import ziggy from './plugins/ziggy'

createInertiaApp({
    resolve: (name) => {
        const pages = import.meta.glob("./Pages/**/*.vue", { eager: true });
        return pages[`./Pages/${name}.vue`];
    },
    setup({ el, App, props, plugin }) {
        createApp({ render: () => h(App, props) })
            .use(plugin)
            .use(ziggy)
            .mount(el);
    },
});

まとめ

こんな感じで環境構築完了できた。
あとは、Laravelで普通に開発進めていけばSPAの開発が進んでいくので、体感はよいけどMPAの利点を捨てるのがどうなんだろうか…
SSRできるけど、本番環境にNode.js必要となるしね

ちなみにtightenco/ziggyを利用した際に気づいたんだけど、Laravelのルーティング設定毎にsail artisan ziggy:generateを実行しないといけないのがめんどくさい。自動化できないものかな

2023/07/19追記: ziggyが自動的に生成されなくてだるいっていう話は、構築ミスによるものだった。
tightenco/ziggy#advanced-setupに記載されてる。
ただ、若干嫌な点としてroutingの情報がheadに全て載る。
@route使わないほうがいいかもなぁ。

date-ioっていうライブラリが便利そう。

Vuetify3系のアップデートとかを追ってて、2023年06月23日現在、Labsに含まれているuseDateっていうAPIを見ていて、date-ioという見慣れないライブラリがあった。少し調べたら、Material-UIのデートピッカーとかにも使われていた。

要は、Moment.jsとか、date-fnsとか、luxonとかの日付操作ライブラリの抽象化を行ってくれるライブラリで、date-ioを通すことで各ライブラリで異なるAPIを吸収してくれるもの。
手動でインターフェースの拡張可能なのでAPIが案件にフィットしなくても自分で解消できそう

とりあえずdate-ioとMoment.js組み合わせてサクッと作って後々いい感じのライブラリに切り替えるっていうのもそんなに負荷かからずにできそうなのかな。

試したリポジトリ github.com

GistPadがよいです。

GistPadという拡張機能がなんか人気っぽいので、VSCodeに入れたらたしかに便利だった。
いままでgistはほぼほぼ局所的にしか使ってなかったんだけど、VSCodeからラフに使えるのであれば今後も利用は増えそう。
正直、gistというサービスいまいち利用シーンが自分になかった。共有したいコードはリポジトリ作るし、メモ用途の場合はgitのadd, commit, push辺りの手順を踏むのがダルいから積極的に使おうと思わない。
でも、GistPadはこの辺り解消してくれてめちゃくちゃよかった。PublicとSercret気をつけないとなー(小並感

【小ネタ】style要素にcontenteditableつけるとブラウザでリアルタイムにスタイリングできる

これ元ネタはTwitterで見たんだけど、いいねもブックマークもしていなかったのでどこかに流れてしまった。 備忘録含めてこちらにメモ。

body要素内にstyle要素を配置して、contenteditable属性を付与。style要素にdisplay: block; white-space: pre;のスタイルをあててあげると不思議とブラウザ上でリアルタイムにスタイリング可能な領域ができあがります。

github.com

上記clone後、index.htmlをブラウザで開くとなんとなく言ってること分かると思う。

仕様的な部分ってどうなの。

body内にstyle要素を含めるのは適切じゃないので、飽くまでお遊びです。
参考:HTML Standard 日本語訳

でもcontenteditable含むグローバル属性は指定可みたい。draggableとかautofucusとか要らなくね?なんとなく雑感。

実務では恐らく役に立たないけど、覚えとくと少しドヤれる…かも

追記

見つけた。これこれ。

DenoのWebフレームワークfreshでパスワード生成アプリ作ってみた

作りました。めちゃくちゃ雑だけど。

random-passwd-gen.deno.dev

リポジトリ: github.com

なんで作ったのか。

fresh触りたかったから。
あと業務でVue2系しか触っていないので、React系統のライブラリを触っておきたいなーと思ったので。
これでなにかを解決!とかは全くないです。

機能

一応紹介しておきます。
以下の機能をアプリの主機能として実装してます。
正直特に言うことないです。ハイ。

  • パスワード生成
  • CSVに出力する機能

freshとはなに?

island architectureというのを採用しているフレームワークで、
サーバー側でレンダリングされる静的な部分と、インタラクティブJavaScriptによる動的)な部分を独立して表示させることが可能です。
今回作ったアプリでいうと、インプットフォーム周りと、生成したパスワードを一覧表示するテーブルをインタラクティブな部分として表示させています。

パスワード生成アプリの画像。薄赤部分がインタラクティブな部分

作ってみて

まぁ、楽しい。
今回のようなアプリケーションだと、freshのカスタムハンドラという機能を用いてサーバー側でパスワード生成してフロントに渡して出力するということも可能でした。
今回はサーバー側に処理させると割とすぐにタイムアウトになっちゃうのでフロント側に寄せたんですが、あんまり効果感じなかった…(謎 このアーキテクチャがメジャーになっていくのなら、設計が結構大変になってくるのかなと思った。

直接関係はないけど、フォームの処理結構手こずってしまった。expressとかちゃんと触ったことがなかったので、今後はNodejs、Denoのサーバ系の処理ちゃんと書けるようになりたいな〜