😀

【自己学習】とにかくまとめ

に公開

npxとnpmの違い

npm (Node Package Manager)

  • パッケージ管理ツール
  • パッケージのインストール、アンインストール、依存関係の管理を行う
  • package.jsonの管理
  • スクリプトの実行(npm run)

npx (Node Package eXecute)

  • パッケージ実行ツール
  • パッケージをインストールせずに一時的に実行
  • グローバルインストールを避けて最新版を使用
  • ローカルにインストールされたパッケージの実行

vscodeのショートカット

コマンド 機能
Ctrl+Shift+X 拡張機能画面を開く

ES7とは

JavaScriptの言語仕様であるECMAScript 2016の通称。

便利なパッケージ

@mui/material

  • 機能: Material-UI(現MUI)のコアコンポーネント
  • 特徴: Googleのマテリアルデザインを実装、豊富なコンポーネント

@emotion/react, @emotion/styled

機能: CSS-in-JS ライブラリ、MUIの依存関係
特徴: 動的スタイリング、テーマ対応

lucide-react

機能: 軽量なアイコンライブラリ
特徴: モダンなアイコンセット、TypeScript対応
ユーティリティ

numeral

機能: 数値フォーマットライブラリ
特徴: 通貨、パーセント、ファイルサイズ等の表示

date-fns

機能: 日付操作ライブラリ(軽量なMoment.js代替)
特徴: 関数型、Tree-shaking対応、国際化

axios

機能: HTTP クライアントライブラリ
特徴: Promise ベース、リクエスト/レスポンス インターセプター

recharts

機能: React用チャートライブラリ
特徴: 宣言的、レスポンシブ、カスタマイズ可能

react-dnd, react-dnd-html5-backend

機能: ドラッグ&ドロップ機能
特徴: 柔軟なAPI、HTML5ドラッグ&ドロップAPI使用
専用コンポーネント

gantt-task-react

  • 機能: ガントチャート専用コンポーネント
  • 特徴: プロジェクト管理に特化、タスク管理、スケジュール表示
  • 注意: react18までしかサポートしていないため、--legacy-peer-depsオプションが必要

@mui/x-data-grid

機能: 高機能データグリッド(MUI X)
特徴: 仮想化、ソート、フィルタ、ページング、編集機能

npmコマンド

npm uninstall

パッケージをアンインストールする

Turbopackとは

Turbopackは、VercelがRustで開発したNext.js向けの高速バンドラーです。

基本概要

  • 開発者: Vercel(Next.jsの開発元)
  • 言語: Rust
  • 目的: Webpackの後継として、ビルド速度の大幅向上
  • 対象: Next.js 13以降で実験的機能として導入

主な特徴

1. 圧倒的な高速化

開発時ビルド: Webpackより最大10倍高速
増分コンパイル: 変更部分のみを再ビルド
並列処理: Rustの並行処理能力を活用

2. Next.js 16での位置づけ

Next.js 16.0.3を使用しており、Turbopackはデフォルトで有効化される予定です。

Google Fontsの動作メカニズム

アプリ起動→fonts.gstatic.comにアクセス→woff2ファイルをダウンロード→表示

Next.js 16ではTurbopackが自動的にシステムフォントを最適化しようとして、内部的にGoogle Fontsサーバーにアクセスしている。

システムフォントとは

ユーザのOSに標準でインストールされているフォントのこと。
Next.js16ではpage.tsx上にデフォルトでfont-sansを記述しており、実際にはシステムフォントを指定している。

page.tsx
export default function Home() {
  return (
    <div className="flex min-h-screen items-center justify-center bg-zinc-50 font-sans dark:bg-black">
      <main className="flex min-h-screen w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
        hello world!
      </main>
    </div>
  );
}

font-sansの指定場所

font-sansを記述すると、システムフォントが指定されるということなので、具体的な指定の流れを次にまとめた。

特徴1. パフォーマンス

  • ダウンロード不要: 既にローカルに存在
  • 表示速度: 即座に表示される
  • ネットワーク負荷: 0バイト

特徴2. 一貫性

  • OS統一: そのOSの標準的な見た目
  • アクセシビリティ: ユーザーが慣れ親しんだフォント
  • 読みやすさ: OS最適化済み

特徴3. 信頼性

  • オフライン対応: インターネット不要
  • 証明書問題なし: 外部サーバーアクセスなし

global.cssで@applyと記述するとUnknown at rule @applyエラー

バージョン16のNext.jsにはTailwind.config.tsが無い

Tailwind.config.ts(tailwindcssの設定ファイル)がなくなっている。そこで、postcss.config.mjsファイルを変更すること。

postcss.config.mjsとは

postCSSとは

cssをJavaScriptプラグインで変換するツール。つまり、postcss.config.mjsはJavaScriptプラグインによるcss変換の際の設定を管理するファイル。

NEXT.js 16のpostcss.config.mjsのデフォルト状態

postcss.config.mjs
const config = {
  plugins: {
    "@tailwindcss/postcss": {},
  },
};
export default config;

mjsファイルとは

ES Modules (ECMAScript Modules) を明示的に使用するJavaScriptファイルのこと。
mjsファイル以外だと、
-js = CommonJS または ES Modules(設定による)
-cjs = CommonJS を明示的に使用するJavaScriptファイル

mjsファイルの利点

package.jsonの"type": "module"なしで使用できる!.mjsファイルは自動的にES Modulesとして解釈される

vscodeでprettierを入れたのにオートフォーマットされない。

原因

plugins名のタイポと該当パッケージが入っていなかった

タイポがある.prettierrc
{
    // 正:"plugins": ["prettier-plugin-tailwindcss"],
	"plugins": ["prettier-plugin-talwindcss"],
	"semi": true,
	"singleQuote": false,
	"jsxSingleQuote": false,
	"tabWidth": 2,
	"useTabs": false,
	"trailingComma": "es5",
	"bracketSpacing": true,
	"jsxBracketSameLine": false,
	"printWidth": 80,
	"endOfLine": "lf"
}

あとはnpm iしてなかったので以下を実行。

npm i prettier-plugin-tailwindcss

調査方法

`Ctrl + Shift + U'で「Prettier」を指定するとログが出てくるのでここを確認する

オートコンプリートをclassName=""に変更する

className=''のようにシングルクオテーションでオートコンプリートされるのをダブルクオテーションに変更したい場合、settings.jsonファイルに以下の設定を追加する。

  1. Ctrl + Shift + Pでコマンドパレットを開きます。
  2. Preferences: Open User Settings (JSON) を検索して選択します。
  3. 開いたsettings.json ファイルに以下のコードを追加します。
settings.json
{
  // ...他の設定...
  "typescript.preferences.quoteStyle": "double",
  "javascript.preferences.quoteStyle": "double"
}

設定の説明

"typescript.preferences.quoteStyle": "double"

TypeScriptファイル(.ts, .tsx)で、自動補完やリファクタリング時に使用される引用符をダブルクォート(")に統一します。

"javascript.preferences.quoteStyle": "double"

JavaScriptファイル(.js, .jsx)でも同様にダブルクォートを使用するようにします。
この設定を追加して保存すると、classNameなどを入力した際の自動補完が <div className=""></div> のようにダブルクォートで生成されるようになります。

importにtypeをつけるメリット

デメリットは無し!

ビルド時の最適化

TypeScriptからJavaScriptにコンパイルされる際、型情報はすべて削除されます。import typeでインポートされたものは、コンパイラが「これは型だから、最終的なJavaScriptファイルには含めなくて良い」と即座に判断できます。これにより、不要なコードがバンドルに含まれるのを防ぎ、ビルドプロセスが高速になることがあります。

コードの意図が明確になる

typeと書かれていることで、コードを読む人は「ああ、これは型として使われているだけで、実際のロジックやUIには影響しないんだな」と一目で理解できます。コードの可読性が向上します。

循環参照の回避

これが最も重要なメリットの一つです。ファイルAがファイルBの値をインポートし、ファイルBがファイルAの型をインポートするような複雑な依存関係がある場合、通常のimportだと循環参照エラーが発生することがあります。import typeを使うと、型インポートはコンパイル時に消えるため、実行時の循環参照を安全に回避できます。

循環参照とは

循環参照(Circular Dependency)とは、2つ以上のファイル(モジュール)が、お互いを直接的または間接的にインポートし合っている状態のことです。
プログラムが読み込まれる際に、どちらを先に解決すればよいか分からなくなり、無限ループのような状態に陥ってしまいます。

簡単な例

  • a.ts が b.ts の中身を使おうとしてインポートする。
  • b.ts が a.ts の中身を使おうとしてインポートする。

なぜ問題?

JavaScript(やTypeScript)のモジュールシステムは、ファイルがインポートされる際に一度だけ実行・初期化されます。
循環参照が起きると、以下のような問題が発生します。

  1. a.ts の読み込みが開始される。
  2. a.ts は b.ts をインポートしているので、b.ts の読み込みに移る。
  3. b.ts は a.ts をインポートしているが、a.ts はまだ読み込みの途中。
  4. この時点で、a.ts からエクスポートされるはずの値(関数やクラスなど)がまだ準備できていないため、b.ts は undefined を受け取ってしまう。
  5. 結果として、プログラムがクラッシュしたり、予期せぬ動作をしたりします。

import type はなぜ循環参照を解決できるのか?

  • 通常の import: 実行時に必要な値(関数、クラス、変数など)を読み込みます。
  • import type: コンパイル時にのみ必要な型情報を読み込みます。

TypeScriptがコードをJavaScriptにコンパイルする際、すべての型情報は削除されます。import typeで読み込んだものも、最終的なJavaScriptファイルには残りません。

解決の仕組み

ファイルAがファイルBの値をインポートし、ファイルBがファイルAの型をインポートするケースを考えます。

a.ts
import type { B_Type } from './b'; // 型だけをインポート
export const a_value = "Hello from A";
export function doSomething(param: B_Type) {
  // ...
}
b.ts
import { a_value } from './a'; // 値をインポート
export type B_Type = {
  id: number;
};
console.log(a_value); // "Hello from A"

このコードがJavaScriptにコンパイルされると、a.tsのimport type { B_Type } from './b'; は完全に消え去ります。

a.js(コンパイル後)
// import typeは消える!
export const a_value = "Hello from A";
export function doSomething(param) {
  // ...
}
b.js (コンパイル後)
import { a_value } from './a.js';
console.log(a_value);

結果として、JavaScriptレベルでは b.js が a.js を一方的にインポートするだけの単純な依存関係になり、循環参照が解消されます。このように、import typeは値の依存関係と型の依存関係を分離することで、安全にコードを記述できるようにしてくれる強力な機能です。

ローカルPostgreSQLのデータベースURL

postgresql://<ユーザー名>:<パスワード>@<ホスト>:<ポート>/<データベース名>?schma=<スキーマ名>

npm auditレポート

プロジェクトが依存しているパッケージ(ライブラリ)にセキュリティ上の脆弱性(ぜいじゃくせい)が見つかったというnpmからの警告レポートです。
簡単に言うと、「あなたのプロジェクトで使っているパッケージに、セキュリティ上の問題が見つかりましたよ」というお知らせです。

npx prisma initを使ったらエラーになった話

エラー内容

Error: request to https://binaries.prisma.sh/all_commits/f09f2815f091dbba658cdcd2264306d88bb5bda6/windows/schema-engine.exe.gz.sha256 failed, reason: unable to verify the first certificate; if the root CA is installed locally, try running Node.js with --use-system-ca

エラーの原因

自分のPCとPrismaのサーバーとの通信に**「中間者」**(会社のセキュリティソフトなど)が割り込み、Node.jsが「この通信相手は本当に安全か信用できない」と判断したため。

解決策の役割

「Node.js標準の信用リストではなく、Windowsが信用しているリストを使って相手を判断して」とNode.jsに指示した。

なぜうまくいったか

Windowsの信用リストには、その「中間者」の身元を保証する情報が含まれていたため、Node.jsは通信相手を信用できると判断し、通信を許可したから。

  1. エラーの原因:「身分証明書が確認できません」問題
    このエラーを理解するために、インターネット通信を「身分証明書の確認」に例えてみましょう。

① 正常な通信(HTTPSの仕組み)
あなた(Node.js): Prismaのサーバーに「エンジンファイルをください」とリクエストします。
Prismaサーバー: 「はい、どうぞ。これが私の身分証明書(SSL証明書)です。私は本物のPrismaサーバーですよ」と証明書を提示します。
あなた(Node.js): 持っている「信頼できる証明書発行機関リスト」と照合します。「うん、この証明書は信頼できる機関が発行したものだ。本物だね」と確認し、安全な通信を開始します。
② 今回のエラーが発生した通信
ここでおそらく、あなたのPCとインターネットの間に**「中間者」**が存在します。これは多くの場合、会社のセキュリティポリシーを守るためのものです。

中間者の例:
企業のファイアウォール
プロキシサーバー
ウイルス対策ソフト
この中間者が、通信内容をチェックするために以下のような動きをします。

あなた(Node.js): Prismaのサーバーにリクエストします。
中間者: そのリクエストを横取りします。
中間者: あなたの代わりにPrismaサーバーと通信し、本物のSSL証明書を受け取ります。
中間者: 自分自身で新しいSSL証明書を作成し、それを「これがPrismaサーバーの証明書だよ」と偽ってあなたに渡します。
あなた(Node.js): その偽の証明書を受け取り、自分の「信頼できる証明書発行機関リスト」と照合します。「待てよ、この証明書を発行した『(例)My Company Security Inc.』なんて機関は知らないぞ。この証明書は信用できない!」と判断します。
結果: 安全が確認できないため、通信を拒否します。これが unable to verify the first certificate エラーの正体です。
Node.jsは、セキュリティのために未知の証明書をブロックするという、正しい動作をしていたわけです。

  1. 解決策の役割:set NODE_OPTIONS=--use-system-ca
    このコマンドが何をしたのかを解説します。

set NODE_OPTIONS=...: Node.jsが起動する際のオプションを設定するコマンドです。
--use-system-ca: このオプションが核心です。ca は Certificate Authority(証明書発行機関)の略です。
デフォルトの動作: Node.jsは、自身に組み込まれている比較的小さな「信頼できる証明書発行機関リスト」を使います。
--use-system-ca を付けた場合: Node.jsは、自身のものではなく、**OS(Windows)が管理している、より大きな「信頼できる証明書発行機関リスト」**を使うようになります。
3. なぜ、それでうまくいったのか
会社のネットワーク環境では、PCをセットアップする際に「中間者(ファイアウォールなど)が発行する証明書は信頼できるものですよ」という情報を、OS(Windows)の証明書ストアに自動的に登録している場合がほとんどです。

つまり、

Node.jsのリスト: 「中間者」の情報を知らない。
Windowsのリスト: 「中間者」の情報を知っている(信頼済み)。
--use-system-ca を使ったことで、Node.jsは判断基準を「知らないリスト」から「知っているリスト」に切り替えました。

あなた(Node.js): 中間者から偽の証明書を受け取ります。
あなた(Node.js): 判断基準を**Windowsの「信頼できる証明書発行機関リスト」**に切り替えます。
あなた(Node.js): リストと照合します。「ああ、この『My Company Security Inc.』は、Windowsさんが信頼できると言っている機関だ。じゃあ大丈夫だね」と判断します。
結果: 通信が許可され、無事にPrismaのエンジンをダウンロードできました。
このように、エラーの原因を正しく理解し、適切なオプションを指定することで、セキュリティを維持しつつ問題を解決できたのです。

ESLintのno-unused-vars警告を除外する方法

Viteを使っている場合はtsconfig.app.json"noUnusedParameters"falseにすればよい

tsconfig.app.json
{
  "compilerOptions": {
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
    "target": "ES2022",
    "useDefineForClassFields": true,
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "types": ["vite/client"],
    "skipLibCheck": true,

    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "verbatimModuleSyntax": true,
    "moduleDetection": "force",
    "noEmit": true,
    "jsx": "react-jsx",

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
+    "noUnusedParameters": false,
-    "noUnusedParameters": true,
    "erasableSyntaxOnly": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedSideEffectImports": true
  },
  "include": ["src"]
}

上記以外の一般的なやり方

npm install --save-dev @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-config-prettier eslint-plugin-import

上記プラグインより ESLint デフォルトのルールだけでは実現できない以下の機能が追加されます。

  • ESLint v9 と Prettier の併用のサポート
  • TypeScript のサポート
  • import/export 構文の検証

npm init @eslint/config@latestを実行する。

What do you want to lint?(eslintの設定ファイルを
→ javascript

How would you like to use ESLint?
→To check syntax and find problems(構文エラーに加えて、バグの原因になりそうな問題やベストプラクティス違反も検出します)

What type of modules does your project use?
→JavaScript modules (import/export)

Which framework does your project use?
→React

Does your project use TypeScript?
→Yes

Where does your code run?(どの環境(プラットフォーム)であなたのコードを実行しますか?)
→Browser

Which language do you want your configuration file be written in?
→jypeScript(設定ファイルが.eslintrc.jsになる)

The config that you've selected requires the following dependencies:
eslint, @eslint/js, globals, typescript-eslint, eslint-plugin-react
Would you like to install them now?
→Yes

Which package manager do you want to use?
→npm

eslint.config.js
import js from "@eslint/js";
import globals from "globals";
import tseslint from "typescript-eslint";
import pluginReact from "eslint-plugin-react";
import { defineConfig } from "eslint/config";

export default defineConfig([
  {
    files: ["**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
    plugins: { js },
    extends: ["js/recommended"],
    languageOptions: { globals: globals.browser },
+    rules: {
+      "no-unused-vars": "off",
+    },
  },
  tseslint.configs.recommended,
  pluginReact.configs.flat.recommended,
]);

tsconfig.jsonとは

TypeScriptのコンパイラオプションなどを記述したファイルで、tscやエディタなどが参照する設定ファイル。
tsc --initコマンドによって作成されるが、Viteなどが勝手に用意してくれるケースもある

erasableSyntaxOnly

erasableSyntaxOnly を有効にするメリットと目的は、
**「型情報だけを利用し、実際のJavaScriptコード(クラスや関数など)は出力しない」**ことです。

主な目的・メリット
型だけを使いたい場合に最適

ライブラリや型定義ファイル(.d.ts)など、型情報だけを提供したいときに便利です。
バンドルサイズの削減

実際のJavaScriptコードを生成しないため、最終的なバンドルサイズが小さくなります。
型安全なAPI設計

実装は別にして、型だけを公開したい場合に使えます。
型消去(erasable)による最適化

型チェックだけ行い、実行時には型に関するコードを一切残さないことで、パフォーマンスやセキュリティ面で有利になることがあります。
まとめ
型だけを使いたい場合や、型定義だけを公開したい場合に有効
実装(クラスや関数など)は出力されないので、型情報のみを利用したい用途に向いている
そのため、アプリ本体や実装が必要な場合には通常は使いません。

サーバーコンポーネントの特徴

  • tsxファイルの先頭に'use client'が無い。

useEffect()とマウントされるタイミングってどっちが先?

マウントされるタイミングが先。
マウント = 初回レンダリング。

  • コンポーネントがマウントされる(初回レンダリングされる)ここで初めてDOMに描画されます。
  • その後、useEffect(() => { setState(...) }, []) のような副作用が実行される
  • setState(setVisible(true) など)はマウント後に実行されます。

reactの再レンダリングとcssトランジションの発火タイミング

モーダルを非表示にする際に300ミリ秒かけてスライドアウトさせる場合は、以下のようにする。

const timeoutRef = useRef<number | null>(null);
const [visible, setVisible] = useState(false);

useEffect(() => {
  setVisible(true);
}, []);

const handleClose = () => {
  setVisible(false);
  timeoutRef.current = setTimeout(() => {
    // 別のところで定義しているモーダルをクローズするメソッド
    closeUpdateModal();
  },300);
}

useEffect(() => {
  return () => {
    if (timeoutRef.current) clearTimeout(timeoutRef.current);
  }
},[]);


      <div
        //マウント直後は visible が false なので、サイドメニューは translate-x-full(画面外)で非表示。
        className={`
          fixed right-0 top-0 h-full w-96 bg-white shadow-lg z-10
          transition-transform duration-300
          ${visible ? "translate-x-0" : "translate-x-full"}
        `}
        onClick={(e) => e.stopPropagation()}
      ></div>

アンマウント時にclearTimeoutをしている理由

今回はhandleClose()を実行して、300ミリ秒後にcloseUpdateModal()が実行するようにしている。もし仮に、handleClose()が実行してから300ミリ秒経過する前に、何かしらの理由(ルーティングや親コンポーネントの状態変化)などで、このコンポーネント自体が消えたとする。
その場合、このコンポーネントが消えているにも関わらずcloseUpdateModal()が実行される、という事態になる。
そうなった場合にどのような挙動になるかわからないため、安全策としてアンマウント時にclearTimeoutをしている。

Discussion