Open22

Cloudflare Pages + Astro + Stylus

CbrnexCbrnex

久しぶりにサイトの改修をしていると、以下のエラーが出た。(途中からなのはそもそも記録として残していなかった)

Cannot find module '@layouts/Layout.astro' imported from '/home/cbrnex/w/pages/src/pages/index.astro'
CbrnexCbrnex
<link rel="preconnect" href="https://fonts.googleapis.com/" crossorigin />
<link rel="dns-prefetch" href="https://fonts.googleapis.com/" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link rel="dns-prefetch" href="https://fonts.gstatic.com" />
<link rel="preconnect" href="https://fonts.googleapis.com" />

自分で見ていて、これ重複してるじゃんと思ったが、実際のところは
<link rel="dns-prefetch" href="https://fonts.gstatic.com" />もいらないっぽい。(ChatGPTがhttps://fonts.googleapis.com/のDNS解決にはhttps://fonts.gstatic.comの解決も含まれると言っていただけだが・・・。本当か?)

CbrnexCbrnex

アイコンのコンポーネントをリファクタリングしていて、ifの使い方がいまいちわからなかったが、

{
    href &&
      (opensNewTab ? (
        <a href={href} title={title} target="_blank" rel="noopener noreferrer" />
      ) : (
        <a href={href} title={title} />
      ))
}

こうすれば

  • hrefがそもそもないときはaタグを出力しない
  • opensNewTabに真が指定されているのみ、新規タブとして開く
  • opensNewTabが偽もしくは指定が無い場合は、新規では開かないaタグを出力する

みたいなことができるっぽい。

if文はJSXの中で書け

CbrnexCbrnex

Markdownのスタイルが指定できず、Markdown側で呼び出してるレイアウトでスタイルタグにis:globalと記述しても変化なし。[slug].astroにスタイル指定しても変化なし。結果として[slug].astroにスタイルシートをインポートしたら適用された。仕様っぽい?

CbrnexCbrnex

replaceメソッドで正規表現が間違っているのか、置き換わらなかった

- string.replace("/\s/g", "+")
+ string.replace(/\s/g, "+")

どうやらクオートはいらないらしい

CbrnexCbrnex
font 1rem/1.5rem "Fira Sans", "Zen Kaku Gothic New"

display=swapを指定したが、時間経過で適用された。何がそうしているのかは不明。

CbrnexCbrnex

stylusでオブジェクトを定義したいとき、

fonts = {
    sans: "Fira Sans", "Trebuchet MS", Verdana, Arial, sans-serif
}

のような定義はできない(,を一つのメンバとして見るため)。

また、

bg = rgb(248, 248, 255)
@media (prefers-color-scheme dark)
  bg = rgb(8, 8, 16)

これも想定通り動かない(オブジェクトで@mediaを書くとそもそも文法エラー)。

CbrnexCbrnex

Markdownのスタイルを変更したいとき、Layoutでimportしているスタイルシートは読み込まれない(場合がある)。このとき、Layout自体にis:globalでスタイルを指定しても、[slug].astroにis:globalでスタイルを指定しても何も変わらない。[slug].astroimport "@styles/md.styl"を記述して、md.stylを変更すれば適用されるが、気に食わない。

CbrnexCbrnex

Svelteが全く動かず(詳しく言えばsetIntervalが動作しない?)問題が発生していたが、importが原因のようだった(ブラウザ側のコンソールにエラーが出る)。

// Uncaught (in promise) SyntaxError: ambiguous indirect export: Titles
import { Titles } from '@scripts/lib/blog'
// 正しく読み込める
import * as blog from '@lib/blog';
const { Titles } = blog;

原因はViteっぽい?

https://github.com/vite-plugin/vite-plugin-commonjs/issues/15

CbrnexCbrnex

astro-iconというインテグレーションで、

<Icon name="simple-icons:discord" />

<style lang="stylus">
    [data-icon]
        font-size 2rem
</style>

以上のようなスタイリングができる。かっこいい。
同じことをするには、

<Link href="/">top</Link>

<style lang="stylus">
  [data-link]
    font-size 10rem
</style>
Link
---
export interface Props {
  href: string;
}

const { href, ...props } = Astro.props;
---

<a href={href} {...props} data-link><slot /></a>

このように定義するみたい。console.log(props)をすると、{ 'data-astro-cid-j7pv25f6': true }のような出力がされる。

output
<a href="/"
   data-astro-cid-j7pv25f6=""
   data-link=""
   data-astro-source-file="C:/Users/username/w/pages/src/components/Link.astro"
   data-astro-source-loc="10:38">
  this is
</a>
output
[data-astro-cid-j7pv25f6][data-link] {
  font-size: 10rem;
}

出力は以上のようになる。以前はclassでスコープを表現してたはずだけど、JS/TSの予約語だから属性セレクタを使うやり方に変わったのかな。詳細についてはStyles & CSS: Styling in Astro - Passing a class to a child componentに書いてある。日本語のドキュメントはこのやり方がまだ書かれていないみたい。このやり方を見つけるのに丸二日かかったし、正直ドキュメントの上にいつ編集したのか書いてくれたら助かるんだけども。

CbrnexCbrnex

いや、そもそもv3の時点でこのやり方になっているから普通にドキュメントがミスってるっぽい。

CbrnexCbrnex
// Example: Use the function syntax to customize based on command
server: ({ command }) => ({ port: command === 'dev' ? 4321 : 4000 })

// 例: コマンドに応じてカスタマイズするためには関数の構文を使用します
server: (command) => ({ port: command === 'dev' ? 4321 : 4000 })

前者は英語のドキュメントで、後者は日本語のドキュメントである。
下のコードは動作しない(エラーにはならないが、常にポートは4000が使われるようになる)。

CbrnexCbrnex
Argument of type 'typeof import("C:/Users/taiko/w/pages/node_modules/.pnpm/@iconify+svelte@3.1.6_svelte@4.2.16/node_modules/@iconify/svelte/dist/index")' is not assignable to parameter of type 'ConstructorOfATypedSvelteComponent'.

Possible causes:
- You use the instance type of a component where you should use the constructor type
- Type definitions are missing for this Svelte Component. If you are using Svelte 3.31+, use SvelteComponentTyped to add a definition:
  import type { SvelteComponentTyped } from "svelte";
  class ComponentName extends SvelteComponentTyped<{propertyName: string;}> {}

https://iconify.design/docs/icon-components/svelte/
https://www.npmjs.com/package/@iconify/svelte

@iconify/svelteをモノレポのSvelteコンポーネントから呼び出したときに表示された
モノレポのツールは使用せず、pnpm workspaceを用いて設定していたのでモノレポの設定に何かしらの問題があると考えていた。

https://www.reddit.com/r/sveltejs/comments/u4w0nm/vscode_svelte_ts_monorepo_recommendations/

以上のような投稿もあるので、VSCodeのSvelte拡張機能が依存関係で何かしらのバグが発生したと考えた。
このエラーが表示されるのはVSCode上だけであり、ビルドも問題なくできる。また、ルートのプロジェクトではこのエラーが発生しない。

https://github.com/iconify/iconify/issues/272
https://svelte.jp/docs/v4-migration-guide#sveltecomponenttyped-is-deprecated

しかし、私の予想は大きく外れた。
SvelteComponentTypedが非推奨となっていて、SvelteComponentに置き換えなければならないとのこと。最初のエラーに書いてある@iconify+svelte@3.1.6_svelteだが、これが古かった模様。アップデートしたら当該エラーは表示されなくなった。