Vite はじめました編

javascriptでvueやreactみたいなフロントエンドフレームワークを使うほどのものを書いてるわけではないのですが、さすがに excel とか pdf とかブラウザでアーダコーダするようになってくると、javascriptのコードを書く量も多くなってJavaScriptライブラリの依存関係も多くなり、こりゃいかん!ってことで、今更ながら Vite を使いだしました。

で、困った問題が一つ、jQuery 自体は、import $ from ‘jquery/dist/jquery.slim’; とかでインポートして使えるんだけど、jQueryプラグインは、ほとんどの場合 window.jQueryが存在していることが前提なので (jQuery.fn に登録する) 、いくら Vite でも、jquery ブラグインを import とかで読み込んでもエラーで使えません。

で、 インポートした jquery を window に注入して、scriptタグを生成することで何とか回避するようにしました。

以下、jQueryのHTMLエディター Trumbowyg を使用するまでの手順。

Vite で プロジェクトにディレクトリを作る。

# テンプレートに valilla を選択、jquery,bootstrap,trumbowyg をインストール
>> npm create vite@latest sample -- --template vanilla
>> cd sample
>> npm i
>> npm i jquery bootstrap trumbowyg

npm create で生成された index.html や 画像、main.js などは必要ない、というか書き換えるので削除する。

index.html,main.js を用意
とりあえず、簡易的に index.html, main.js を書く。

index.html には、最低限のものだけ、このHTMLファイルに main.js をスクリプトタグで書いておく。
bootstrapとかの読込とか、jqueryとか、ブラグインとかは全部 main.js に書いて Vite にお任せするので、html に書く必要はない。

main.js は type=module で読み込む↑↑↑
とりあえず、↓のような感じ。

開発用サーバー立ち上げとビルド処理
Viteは 開発用のwebサーバーも内蔵しているので、とにかく開発環境を構築するのはホントにラクちん。

# 開発時は以下でビルトインサーバー立ち上げ、ファイルを書き換えると瞬時に反映される。
>> npm run dev

# 公開するときは、ビルドする。デフォルトだと dist ディレクトリが作られる。
>> npm run build

# ビルドされたものを確認するためのビルトインサーバー立ち上げ
>> npm run preview

Vite自体は vue とかのフロントエンドフレームワークを使う前提なんでしょうけど、フレームワークを使わないVanillaJSやjQueryを使う小規模の開発でも簡単にはじめられるので積極的に使っていこうと思います。

JavaScript Cache APIと有効期限

公開されている色んなWeb APIを使うと、簡単にデータを引っ張ってこられるので、便利ですよね。
ただ、有料のAPIとかだと、むやみにやたらにAPIサーバーにリクエストを出すとコストがかかってしまい、なんとかブラウザでlocalStorageとかでキャッシュさせたい! と思ってました。

最近のブラウザはCache APIでキャッシュを完全にコントロールできるようになっているようで・・・知らなかい事ばかり💦

https://developer.mozilla.org/ja/docs/Web/API/Cache

Cache APIは、fetchなどで得られたリクエスト(URL)とレスポンスを対にしてキャッシュしてくれるものの、自動的にキャッシュが削除されたり、とかいうのはできないみたいで、キャッシュを更新したければ、自分でそういう実装をしないといけないようです。

はじめは、fetchで得られたレスポンスにキャッシュした時のUNIX時間をセットして、使うときに、現在時刻と比較してやれば・・・と簡単に思っていたんですけど、fetchから取得したレスポンスのヘッダ情報はリードオンリーなので、書き込めず。。。
ググると、fetchで取得したレスポンスの情報をコピーして、新しいレスポンスオブジェクトを作って(new Responseして)それをキャッシュさせればいいみたい。

とりあえず思いつくまま、コードを書いた(エラーチェック無し)↓

これを

//もちろん、異なるoriginのURLの場合は Access-Control-Allow-Origin ヘッダに対応してないといけないが・・・
const url = 'https://hoge-hoge.com/get?xxx=yyy';

// window.caches チェックして対応していない場合は、通常の fetchを使用する。
const json = ('caches' in window) ? await cachedFetchJson(url) : await fetchJson(url);

とりあえず、1回目はfetchが走り・・・


ブラウザのキャッシュを無効にしているにも関わらず、2回目は、fetchは走っていませんでした。


AIイラスト体験

twitterでおすすめとかでTLに流れてくるツイートの中に、AIグラビアの画像がたまたま流れてきて「グラボを買えばできるよん」みたいな感じだったので、やり方を調べてやってみた。

#ChillOutMix

まずはdGPU、GeForceのグラボがいるみたい。ググるとGeForce RTX-3060 12GBのものを買えばいいみたい。
買う前に今のパソコンで使えるかどうか。。。今のPC環境は、ストレージを除けば5年以上の前のもの。

  • CPUはCore i7 8700 (無印)
  • メモリは32GB (8GB x 4)
  • 電源は10年前に買った玄人志向の550W 80PLUS GOLD
  • M/BはASUSのPrime Z370-A

という構成。一応 PCIe rev3なので、PCIe rev4のRTX-3060はギリ、搭載できる。
メーカーによって推奨電源が650Wだったり、550Wだったりと若干不安は残るが、認識しなければ電源も買い替えればいいし・・・ということでちょうど在庫があったGIGABYTEの GV-N3060EAGLE OC-12GD R2.0を買って、取付け、UEFIで認識しているのを確認してWindows起動成功。

NVIDIAサイトからドライバをダウンロードしてインストールしたらちゃんと使えるようになった!
一応5〜6時間ぶっとおしで動画エンコードしながらPC使って見ても落ちないので電源は 550W でも十分使えそう。
ちなみに、GPUが100%で振り切っている状態で、UPSの状態を確認したら負荷電力がMAXで280〜360Wぐらい。CPUが K型番じゃなく無印の省電力版Core i7なので、まだちょっと余裕があるみたいな感じ。

次に、AIイラストの環境構築。システム自体は、Python3 で動く Stable Diffusion と Web UIで動かすみたいで、これもググると、githubからcloneするだけらしい。

PythonとGit は、コマンドプロンプトから winget でインストールすれば一瞬でインストールできる。

> winget install -h Python.Python.3.10
> winget install -h Git.Git

コマンドプロンプトを一度閉じ、もういちど コマンドプロンプトを出してから作業。正しくインストールされていれば、pythonとgitにPATHが通っているはずなので、gitもしくはpythonを叩いて確認する。

あとは適当なフォルダ(ディレクトリ)を作って、そのディレクトリで git cloneして、webui.bat をコールすれば、初回起動は時間はかかるが2回目からすぐに起動できる。

> git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git
> cd .\stable-diffusion-webui
> .\webui

さて、あとは、ChilloutMix とかいうモデルファイルを入れたり、LoRAというものを探して入れたり、ググるといっぱいやり方がでてくるので割愛するけど、旬な話題みたいで、いっぱいブログ記事がヒットするんだけど、詳しくないので、どれが正しい情報なのか、イマイチ分からない。
しかも使われている用語がわけわからんので、一つ一つ調べて前に進めるしかない、と諦めてる。

試行錯誤しながら、画像を生成してみた。

#ChillOutMix

なんか手が6本になったり、股から足がニョキニョキ生えた画像が出てきたり、やたらヌード画像になったり、まだ呪文(プロンプト)の入力が分からん。。。。

しばらく遊んでみます。。。

WindowsとCertbotとSSL証明書と。

備忘録的エントリになります。

レンタルサーバーとかだと、LetsEncryptの Certbot で運用・・・なんてできませんよね。
LetsEcryptに対応している(コンパネとかで)レンタルサーバーだといいんですが、対応していない場合、なんとかして LetsEncrypt のフリーのSSL証明書をゲットしなければなりません。

探し方が悪いのかググっても情報がバラバラで何がどうなってんのかさっぱり分からない。かなり試行錯誤しながら、SSL証明書の取得および更新を半自動化するスクリプトを組むことができました。

まずはCertbotのインストール

私は ガチガチのWindows ユーザーなので、まず最初に WSL1(Ubuntu 20.04)でやろうとしましたが、Certbotの公式サイト(https://certbot.eff.org/)に載ってる説明されている方法だと、snapdをインストールして・・・と書かれているのですが、WSL1ではsnapdは非対応でした。

WSL2とsystemd稼働環境だといけるみたいですが、WSL2はあまり使いたくありません。で、残る選択肢は Windowsで動作するCertbotをインストールするしかありません。

Windows版のcertbotのインストールはWinGetを使うと超絶カンタンです。
コマンドプロンプトから、下記のようにコマンドを叩くだけ。途中権限昇格がポップアップされますが、大丈夫でしょう。

 >> winget install certbot

通常、C:\Program Files\Certbot\binに実行ファイルが格納されていますので、環境変数 PATH に追加しておくといいでせう。

Linuxとかだと、関連するファイルは、/etc/letsencrypt/ に配置されてるようですが、Windowsだと、C:\Certbotに関連するファイルが作成されるようです。

一つ注意点として、certbotを実行する際、管理者権限が必要です。まず管理者権限のコマンドプロンプトで実行しないと、エラーになります。

SSL証明書の取得

インストールが完了したらほぼ作業は終わり。あとは、下記のようなCMDファイル(batファイルでもいいけど)を書いた方がいいです。
インストールして初回実行時だけ、メールアドレスの登録プロセスが出ますが、特別な理由がない限り、メールアドレスは登録しておいた方がいいでしょう。SSL証明書の期限切れ前に、メールで知らせてくれます^^;

今回は証明書の取得をウェブサーバー上で行うのではなく、自分のPCで証明書を取得しますので、Manualプラグインを使用します。ドメインの認証方法は、通常と同じくデフォルトのhttp認証でドメインの認証を行います。

要するに、自分がそのドメインのオーナーかどうかは、レンタルサーバー上へ FTPなどで認証ファイルを置くことで認証を行います。
認証ファイルをレンタルサーバーへ転送するには、cURL を使います。Windows10から curl.exe が標準でバンドルされるようになってるはずです。

読めば大体分かりますが・・・、
(1) –manual で Manualプラグインを使用します。
(2) -d でSSL証明書を取得したいドメイン名を指定。
(3) –key-type で rsa を指定。レンタルサーバーがRSAしか対応していない場合は指定する。
(4) –agree-tos, –manual-public-ip-logging-ok は指定しないと途中で聞いてくるので初めからYes。
(5) –manual-auth-hook,–manual-auth-cleanup は、後述。

最後の(5)で、–manual-auth-hookと–manual-auth-cleanupは、認証情報をセットアップ、クリーンアップするスクリプトを指定します。
これは下記のように、certbotを実行中、http認証する前、後にコールされ実行されます。

※この2つのフックについては、公式?のドキュメント、Pre and Post Validation Hooks 参照のこと。

具体的には、スクリプトが実行されるとき、ドメイン名や、認証テキストなどが環境変数を通して渡されますので、環境変数から渡されたパラメータを使用して、レンタルサーバーへcURLを使って放り込みます。具体的には、以下のようなスクリプトを用意します。

上記ファイルにも書きましたが、FTPサーバーへのアカウントを直書きしているので、そのままコピペはダメです。あくまでサンプルですので、暗号化・復号化は自分で実装してください。

※ また、FTP以外のSCPとか使ってレンタルサーバーにアップしている人・・・cURLのほかにも SCPもWindows10以降はバンドルされているので、その辺はテキトーに書き換え必要。

正常に認証が通れば、SSL証明書が、C:\Certbot\live\ドメイン名 ディレクトリに証明書が生成されているはずです。
実際には、シンボリックリンクになってますが。これらのファイルをレンタルサーバーのコンパネで設定してください。

SSL証明書の更新

LetsEncryptは3か月(90日)しか使えません。自前のサーバーでは、crondなりで更新スクリプトを回せばいいのですが、 レンタルサーバーだと全部手動になります。
少しでも楽するため、SSL証明書の更新処理だけは自動化したいですよね。

更新の際も認証が必要になりますので、上記で使った certbot-preauth.cmd,certbot-postauth.cmdを使いまわします。。。

certbot renew する際の注意点として、複数のドメインの証明書をcertbotで管理する際、特定のドメインを指定して更新、というのは現状できないみたいで、renewするときはすべてのドメインを一括して更新されてしまいます。

-d でドメインを指定しても、エラーになり、いずれドメインを指定できるようにする、という旨のメッセージが出ます。まぁ、バージョンが上がれば、そのうちドメインを指定して更新処理(certbot renew)することができるようになるでせう。

と、まぁ、http認証をmanualプラグイン(手動)で運用できるようになりました。888888。

・・・ですが、ワイルドカードSSL認証の場合は、デフォルトのhttp認証ではなく、dns認証をするしかありません。
やり方は上記とほぼ同じですが、–preferred-challenges dns を付け足し、-d で アスタリスクをつけたドメイン名を指定するだけ。
ただし、自動化するには、–manual-auth-hookでDNSのTXTレコードを設定する処理が必要です。
DNSの設定をAPI経由などでできないと無理っぽそう。

ブラウザでPDFファイルの画像化

持病の影響で急性腎不全を患い、少しばかり入院していました。はぁ~、健康って大事ですよねぇ。。。
というのは、さておき。

コーディング・メモです。

PDFファイルの画像を生成するため、アップロードしたPDFファイルをサーバーで(具体的には ImageMagickで)処理していました。
周知のとおり、ImageMagickでPDFファイルを処理するとセキュリティー云々があってごく限られた場合に使用するようにしていました。
ImageMagickはいいですね、もう画像関連の処理は全部コイツに任せたいぐらいですが、4~5年前に脆弱性に関する情報がいっぱい出て使うのをためらっています。2022年末になってもまだ同じ状況なのでしょうか?よく分かりません。

というわけ・・・でもないのですが、サーバーサイドでImageMagickに頼らず、ということになるとImageMagickの代替を探すか、自作するしかありませんが、画像のアルゴリズム他に関する知見はほとんどないので自前でなんとか、というのはできない。となると、クライアントでどうにかするしかありません。

幸いにも、最近のウェブ環境ではJavaScriptでどうとでもなります。
PDFフォーマットの解析・表示には、MozillaさんがPDF.js を公開してくれてます。今更ですが。

A general-purpose, web standards-based platform for parsing and rendering PDFs.
PDF.js

これを使うと、File,Blobなどで取得したPDFデータを HTMLに書いたcanvas要素にレンダリングしてくれます。
canvas要素にレンダリングしてくれたら、あとは canvas要素の画像を取得して Blob に変換してあげて、サーバーにPDFとともに生成した画像を送信してやれば、サーバー側で重い処理を走らせずに済みます。

上記サイトにサンプルがあるので、チョチョっといじれば、簡単に実装できる、いい時代です。
最初、ダウンロードしたファイルのどれが必要なのかよく分かんなかったですが・・・、最終的に、以下のように buildディレクトリとcmapsディレクトリさえあれば、事足りるみたい。

.
└── pdfjs
    ├── build
    │   ├── pdf.min.js
    │   ├── pdf.sandbox.min.js
    │   ├── pdf.worker.entry.js
    │   └── pdf.worker.min.js
    └── cmaps/*

とりあえず動作デモ
ソースを見れば大体何をやってるかは分かると思います。チョーカンタン。

input[type=file]要素でファイルを読み込んで、それをそのまま渡すと変換した画像のFileオブジェクトを返してくれるような関数を書いてみました。再利用しやすいようにとりあえずモジュールとして書いた。

これを、下記のようにコール。

ものすごく、簡単。

上記のデモはこっち。