ricomintea’s diary

好きなものを好きでいる

『「わかる」とはどういうことか』 を読んだ

雑談

ウェッブのエンジニアとしてあるいは楽しめる趣味のひとつとして、ある技術を学ぶという行為をそこそこやってきた。

知見のまとめられた記事、体系的に解説している書籍、ハンズオン形式のチュートリアル。主観としてやったものは多くないが、そういうことに興味がない人たちに比べたら触れている方なんじゃないかとも思う。

見た・読んだ・手を動かしてやってみた・小さいものながら自作した。そのうちのいくつかは記事にしたり、稀に関わりの深いコミュニティでLTや勉強会で話したりもしたが、「それをやっただけ」止まりで「わかった」・「理解した」という感覚には繋がっていなかった。

よくある「エンジニアは記事を書け」みたいなものを実践している人にはすごい!最高!と称賛を送るが、自分でそれをやっても「記事を書いただけ」になってしまう。

やってみたけどわかってる?作ってみたけど理解してる?

...

「理解してる」ってなんだ?そんなところからこの本を見つけた。

本について

筑摩書房 ちくま新書 著者 山鳥 重 Yamadori Atsushi

主題 「わかる」とはどういうことか 副題 認識の脳科学

www.chikumashobo.co.jp

感想とかのポエム

「わかる」の基本 区別する

知覚の働きの基本はこのように「違いがわかる」ことにあります。この区別の力はもともと備わっているものですが、それだけでは十分ではありません。その働きをより優れたものにするためには、その能力をいっそう鍛えてやる必要があります。 山鳥重. 「わかる」とはどういうことか ――認識の脳科学 (ちくま新書) (p.20). 筑摩書房. Kindle 版.

「犬」と「猫」は区別できる。見た目や鳴き方が違う。猫は特に好きだ。 「JavaScript」と「TypeScript」が違うこともわかる。コード中にデータの型に関する情報が記述できる。JavaScriptでもJSDocとして記述できるが、TypeScriptだとコンパイル時に静的検査ができる。Language Serverの充実によってどちらもコーディング中にいいヒントをくれるのは同じだ。

区別ができるのならば、少なくとも「A」と「B」が違うことがわかっている。「A」と「B」がどう違うのか説明できるのならば、その説明の範囲で「A」の持つ特徴と「B」の持つ特徴を理解している。

説明できるというのは重要で、「X」というものの名前を知っているだけでは、「あ」という文字を知っているという事実とそこまで変わらない。

「X」という名前のものの存在を知っているところから、「X」って何だろうと気になるのが好奇心。別に気にならないのであればそれは興味がない分野なのだろう。全てを知る時間はないのだから好きなものから知るといいと思う。

わかる、とは自分のものにすることです。長々と文に表現されているものが自分の概念( 心像)としてひとつのイメージにまとめられることです。そうなると、今度はそのわかったこと を自分の言葉で表すことが出来ます。 山鳥重. 「わかる」とはどういうことか ――認識の脳科学 (ちくま新書) (p.148). 筑摩書房. Kindle 版.

小さい意味と大きな意味, 浅い理解と深い理解

どんな意味も、それぞれの水準で大きな意味と小さな意味を含んでいます。そのそれぞれの水準で、まず大きな意味を理解することが必要です。小さな意味が理解出来ても、大きな意味 が理解出来なければ、行動の役には立たないのです。 山鳥重. 「わかる」とはどういうことか ――認識の脳科学 (ちくま新書) (p.205). 筑摩書房. Kindle 版.

『ある「ライブラリ」にはこれこれこういう機能があって、他のライブラリと違ってこんな特徴があることを知ったんだ。どういうときに使うといいのかはわからないけどね!』

調べてみた段階。動かしてみてようやく知った段階。勉強会で面白く紹介した段階。満足できるタイミングは色んな段階であるけど、おそらくは実用まで持っていけると一番いいよね。

書籍中には「わかる」の種類や「わかる」体験の流れについても載っていて、例の説明が言葉遊びみたいで面白いなと思った。 疲れたので浅く締める。深く理解していきたいね。

TSConfig コンパイルターゲットの指定

TypeScript プロジェクトを作成するとき、 tsconfig.jsoncompilerOptions.target を指定することができる。

Next.js のプロジェクトを生成する create-next-app を使うとデフォルトで es5 が指定される。しかし ES5 がリリースされたのは2009年であり、フロントエンドの成長(ここでは言語機能やブラウザ機能の進歩)を考えるともはや古代。どう決めたらいいのか考えてみる。

tsconfigって何だっけ

TypeScript プロジェクトでは必ず設定してるけどこいつは何だ。

www.typescriptlang.org

次の2つの役割を持つ。

  • TypeScript プロジェクトのプロジェクトルートを示す
  • コンパイラオプションの指定

jsconfigとの違い

jsconfig.json は tsconfig.json から派生したもので、TypeScript を使用していないプロジェクトで tsconfig.json の役割を果たす。 tsconfig.jsonallowJstrue にしたものと同様。

code.visualstudio.com

Tip: jsconfig.json is a descendant of tsconfig.json, which is a configuration file for TypeScript. jsconfig.json is tsconfig.json with "allowJs" attribute set to true.

compilerOptions.targetのすること

target 属性が何をするものなのか整理する。

前提

  1. TypeScript はコンパイラによって JavaScriptコンパイルされる
  2. JavaScript の仕様である ECMAScript は複数のバージョンが存在する
  3. JavaScript 実行環境がコンパイルした ECMAScript のバージョンに対応している必要がある

targetの値

target の値は、前提1のコンパイル後の JavaScript が前提2の ECMAScript のどのバージョンに対応するかの指定に使われる。

エディタによる TypeScript コーディングのサポートを受けている場合は、target の値で対応している機能までで入力補完などが行われる。

targetでの動作を支えるlibとpolyfill

指定した target のECMAScript バージョンに使いたい機能がない場合でも、 compilerOptions.lib を指定することで、TypeScript でのエラーを回避できる。実行環境で動作させるためには compilerOptions.lib で指定した機能に対応するポリフィル(polyfill)を実装内に組み込む必要がある。

ポリフィルという名称の考案者による記事

What is a Polyfill?

ポリフィルの歴史についてまとめられた記事

polyfill を深堀りする - mizdra's blog

target, lib の指定とポリフィルの組み込みについて実験された記事

https://www.tohuandkonsome.site/entry/2019/10/10/215920

targetの決め方

実行環境ごとの target 指定の流れ

Node.js

使用する Node.js のバージョンで、十分に機能をサポートしている ECMAScript のバージョンを指定する。Node Green というサイトで、ECMAScript の機能と Node.js のサポート対応表が公開されているので参考になる。

node.green

ブラウザ

Internet Explorer のサポート終了から、フロントエンドで考慮するブラウザ機能のラインが数段階変わった。2022年初めの記事だが、OS・ブラウザのシェア率などからベースラインについて考察されている。

engineering.linecorp.com

  1. 標準仕様に関しては Safari はベースライン:自分たちが開発するサイトは少なくとも2年前のSafariで動作できないといけません。

ECMAScript の機能と各ブラウザの最新数バージョンでのサポート対応表も存在する。

kangax.github.io

自分たちが実装するサービスのターゲットと各ブラウザのシェアを見ながら、どこにラインを置くかを決めるとよさげ。

Prisma schemeから型を生成してNext.jsで使う

はじめに

Next.js でいわゆるフルスタックな開発をしようとしていたときに、Prisma scheme から型を生成したときのメモ

セットアップ

create-next-app を使って Next.js のプロジェクトを生成します。

npx create-next-app webapp --ts --tailwind --eslint --app --src-dir --use-npm
✔ Would you like to customize the default import alias? … No / Yes

Prisma のセットアップをします。データソースは何でもいいですが sqlite にしました。

cd webapp
npx prisma init --datasource-provider sqlite

prisma init によって prisma ディレクトリと scheme.prisma ファイルが生成されます。

生成されたファイルに generator zod とモデルを追加します。

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}

generator zod {
  provider = "zod-prisma-types"
}

model User {
  id Int @id @default(autoincrement())
  name String
}

Prisma ではジェネレーターによって、データモデルから何かしらを出力することができます。今回は zod-prisma-types を指定してデータモデルから、TypeScriptの型を出力させます。

次に、定義したスキーマからデータベースを生成します。

npm install -D zod-prisma-types
npx prisma migrate dev --name init

これで sqlite のデータベースと zod による型定義が出力されます。

prisma
├── dev.db
├── dev.db-journal
├── generated
│   └── zod
│       └── index.ts
├── migrations
│   ├── 20230515191627_init
│   │   └── migration.sql
│   └── migration_lock.toml
└── schema.prisma

型定義へのエイリアスを tsconfig に追加

paths@/prisma-types で参照先のエイリアスを追加します。

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "plugins": [
      {
        "name": "next"
      }
    ],
    "paths": {
      "@/*": ["./src/*"],
      "@/prisma-types": ["./prisma/generated/zod/index.ts"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
  "exclude": ["node_modules"]
}

これで生成した型定義を、Next.js 側の実装で楽に使える。

終わり

リンク

Next.js13のTurbopack

2022年10月の Next.js Conf で発表された内容のひとつに Turbopack というものがありました。

webpack と Vercel のメンバーによって作られているもので、2023年3月の時点ではアルファ版として試せる状態です。

turbo.build

ここ数年、フロントエンド周りのツールは 実行速度の面でパフォーマンスの高い Go や Rust などで実装されていることが多いです。Turbopack もまた Rust で実装されていて、webpack と比べて言語レベルで処理速度が上がります。

同じように JavaScript 以外の言語で実装された Vite との違いについても話がありました。

turbo.build

Vite は開発時のサーバー起動の時間を主眼に置き、開発しているソースコードはバンドルせず ES Modules を利用してブラウザ側で解決させます。(npm パッケージのライブラリは esbuild によって事前にバンドルが行われます。)

ja.vitejs.dev

Turbopack では開発規模が大きくなって必要なモジュールが増えたときに、ネットワークリクエストのパフォーマンスが落ちることを懸念して、バンドルの処理をいい感じにやることで解決しようとしています。

ロードマップでは、Next.js 以外にも Svelte などほかのフレームワークの対応も前向きなようで、フロントエンド開発全体の底上げに繋がりそうです。