diff --git a/package.json b/package.json index d55952a..e4ab91f 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "@types/react-dom": "^19.2.3", "astro": "^5.17.1", "astro-expressive-code": "^0.41.5", + "dayjs": "^1.11.20", "react": "^19.2.4", "react-dom": "^19.2.4", "rehype-mermaid": "^3.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dfceffb..3140a30 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,6 +38,9 @@ astro-expressive-code: specifier: ^0.41.5 version: 0.41.5(astro@5.17.1(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(typescript@5.9.3)) + dayjs: + specifier: ^1.11.20 + version: 1.11.20 react: specifier: ^19.2.4 version: 19.2.4 @@ -1400,8 +1403,8 @@ daisyui@5.5.14: resolution: {integrity: sha512-L47rvw7I7hK68TA97VB8Ee0woHew+/ohR6Lx6Ah/krfISOqcG4My7poNpX5Mo5/ytMxiR40fEaz6njzDi7cuSg==} - dayjs@1.11.19: - resolution: {integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==} + dayjs@1.11.20: + resolution: {integrity: sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==} debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} @@ -4110,7 +4113,7 @@ daisyui@5.5.14: {} - dayjs@1.11.19: {} + dayjs@1.11.20: {} debug@4.4.3: dependencies: @@ -4847,7 +4850,7 @@ d3: 7.9.0 d3-sankey: 0.12.3 dagre-d3-es: 7.0.13 - dayjs: 1.11.19 + dayjs: 1.11.20 dompurify: 3.3.1 katex: 0.16.28 khroma: 2.1.0 diff --git a/src/components/ExampleWrapper.astro b/src/components/ExampleWrapper.astro new file mode 100644 index 0000000..79c7612 --- /dev/null +++ b/src/components/ExampleWrapper.astro @@ -0,0 +1,42 @@ +--- +--- + +
+ +
+ + diff --git a/src/components/example/CombinedExample.tsx b/src/components/example/CombinedExample.tsx new file mode 100644 index 0000000..1c63071 --- /dev/null +++ b/src/components/example/CombinedExample.tsx @@ -0,0 +1,54 @@ +import dayjs from "dayjs"; +import "dayjs/locale/ja"; +import { useState } from "react"; + +dayjs.locale("ja"); + +const initialTasks = [ + { id: 1, text: "朝のミーティング", done: false }, + { id: 2, text: "仕様書を読む", done: false }, + { id: 3, text: "コードレビュー", done: false }, +]; + +export default function CombinedExample() { + const [tasks, setTasks] = useState(initialTasks); + + const toggle = (id: number) => { + setTasks(tasks.map((t) => (t.id === id ? { ...t, done: !t.done } : t))); + }; + + const done = tasks.filter((t) => t.done).length; + + return ( +
+
+

+ {dayjs().format("YYYY年MM月DD日(ddd)")} +

+

今日のタスク

+

+ {done} / {tasks.length} 完了 +

+
+
+ {tasks.map((task) => ( +
+ +
+ ))} +
+
+ ); +} diff --git a/src/components/example/DayjsExample.tsx b/src/components/example/DayjsExample.tsx new file mode 100644 index 0000000..10031e7 --- /dev/null +++ b/src/components/example/DayjsExample.tsx @@ -0,0 +1,29 @@ +import dayjs from "dayjs"; +import "dayjs/locale/ja"; + +dayjs.locale("ja"); + +export default function DayjsExample() { + const now = dayjs(); + + return ( +
+
+ 標準表示: + {now.format("YYYY-MM-DD HH:mm:ss")} +
+
+ 日本語表示: + {now.format("YYYY年MM月DD日(ddd)HH時mm分")} +
+
+ 7日後: + {now.add(7, "day").format("YYYY年MM月DD日")} +
+
+ 先月の初日: + {now.subtract(1, "month").startOf("month").format("YYYY年MM月DD日")} +
+
+ ); +} diff --git a/src/components/example/ReactExample.tsx b/src/components/example/ReactExample.tsx new file mode 100644 index 0000000..ce63a3f --- /dev/null +++ b/src/components/example/ReactExample.tsx @@ -0,0 +1,29 @@ +import { useState } from "react"; + +export default function ReactExample() { + const [count, setCount] = useState(0); + + return ( +
+

+ クリック数: {count} +

+
+ + +
+
+ ); +} diff --git a/src/components/example/TailwindExample.tsx b/src/components/example/TailwindExample.tsx new file mode 100644 index 0000000..9502359 --- /dev/null +++ b/src/components/example/TailwindExample.tsx @@ -0,0 +1,25 @@ +export default function TailwindExample() { + return ( +
+
+ + + +
+
+
+

カードコンポーネント

+

+ Tailwind CSSのクラスを組み合わせるだけで、こうしたUIが作れます。 +

+
+
+
+ ); +} diff --git a/src/pages/nodejs/010-well-known-library.mdx b/src/pages/nodejs/010-well-known-library.mdx index 7f7debb..bf715bb 100644 --- a/src/pages/nodejs/010-well-known-library.mdx +++ b/src/pages/nodejs/010-well-known-library.mdx @@ -3,9 +3,201 @@ --- import Toc from "../../components/Toc.astro"; +import ExampleWrapper from "@/components/ExampleWrapper.astro"; +import TailwindExample from "@/components/example/TailwindExample"; +import ReactExample from "@/components/example/ReactExample"; +import DayjsExample from "@/components/example/DayjsExample"; +import CombinedExample from "@/components/example/CombinedExample"; export const title = "有名なライブラリ"; # {title} ## TOC + +npmには世界中の開発者が作ったライブラリが公開されており、その数は100万を超えています。 +ここでは特によく使われる代表的なライブラリを紹介します。 + +## UIを作る + +### React + +**React**はMeta(旧Facebook)が開発したUIライブラリです。 +ウェブページの画面を「コンポーネント」という部品に分けて管理できるようにしたもので、 +現在最もよく使われているフロントエンドライブラリのひとつです。 + +ボタンやフォームなどのUI部品を再利用しやすい形で作れるため、大規模なウェブアプリケーションの開発に特に力を発揮します。 +また、`useState`のような仕組みを使うことで、クリックや入力といった操作に応じて画面を自動で更新できます。 + +```tsx +import { useState } from "react"; + +export default function Counter() { + const [count, setCount] = useState(0); + + return ( +
+

クリック数: {count}

+ + +
+ ); +} +``` + + + +```bash +npm install react react-dom +``` + +### Tailwind CSS + +**Tailwind CSS**はCSSを効率よく書くためのライブラリです。 +通常のCSSはクラス名を自分で決めてスタイルを記述しますが、Tailwind CSSでは`text-lg`や`bg-blue-500`のような +あらかじめ用意されたクラスを組み合わせることで、CSSファイルをほとんど書かずにスタイルを整えられます。 + +Tailwind CSSを土台にして、ボタンやカードなどよく使うUIパーツをあらかじめ用意したライブラリもあります。 +このドキュメントサイトでは **daisyUI** というライブラリを使っており、`btn`や`card`といったクラスを使うだけで整ったUIが作れます。 + +```html + + + +
+
+

カードコンポーネント

+

Tailwind CSSのクラスを組み合わせるだけで作れます。

+
+
+``` + + + +```bash +npm install tailwindcss +``` + +## サーバーを作る + +### Express + +**Express**はNode.jsでWebサーバーを作るためのフレームワークです。 +Node.js単体でもWebサーバーは作れますが、Expressを使うことでURLごとの処理を簡潔に書けるようになります。 + +Node.jsでサーバーを作る場合、現在でも最もよく使われている定番のライブラリです。 + +```js +import express from "express"; + +const app = express(); + +// /hello にアクセスされたときの処理 +app.get("/hello", (req, res) => { + res.send("Hello, World!"); +}); + +app.listen(3000); +``` + +```bash +npm install express +``` + +## 便利ツール + +### Day.js + +**Day.js**は日付や時刻を扱うためのライブラリです。 +JavaScriptには標準で日付を扱う機能がありますが、「3日後の日付を求める」「日付を〇年〇月〇日の形式で表示する」 +といった処理を書くのが複雑です。Day.jsを使うとこういった処理をシンプルに書けます。 + +```js +import dayjs from "dayjs"; +import "dayjs/locale/ja"; + +dayjs.locale("ja"); + +const now = dayjs(); + +now.format("YYYY年MM月DD日(ddd)HH時mm分"); // 今日の日時 +now.add(7, "day").format("YYYY年MM月DD日"); // 7日後 +now.subtract(1, "month").startOf("month"); // 先月の初日 +``` + + + +```bash +npm install dayjs +``` + +--- + +これらはほんの一例です。npmには他にも無数のライブラリがあり、 +「やりたいことがあればまず探してみる」というのがNode.js開発の基本的なスタイルです。 + +いまモダンと言われるWeb開発の多くは、こういったライブラリを組み合わせて作られています。 + +## 組み合わせる + +これらのライブラリは、それぞれ単独で使うだけでなく組み合わせることで力を発揮します。 + +以下は **React**・**Tailwind CSS**・**Day.js** を組み合わせた例です。 +今日の日付(Day.js)を表示しながら、チェックボックスで状態が変わる(React)、見た目の整ったタスクリスト(Tailwind CSS)を作っています。 + +```tsx +import dayjs from "dayjs"; +import "dayjs/locale/ja"; +import { useState } from "react"; + +dayjs.locale("ja"); + +const initialTasks = [ + { id: 1, text: "朝のミーティング", done: false }, + { id: 2, text: "仕様書を読む", done: false }, + { id: 3, text: "コードレビュー", done: false }, +]; + +export default function TaskList() { + const [tasks, setTasks] = useState(initialTasks); + + const toggle = (id) => { + setTasks(tasks.map((t) => (t.id === id ? { ...t, done: !t.done } : t))); + }; + + const done = tasks.filter((t) => t.done).length; + + return ( +
+
+
+

+ {dayjs().format("YYYY年MM月DD日(ddd)")} +

+

今日のタスク

+

{done} / {tasks.length} 完了

+
+ +
+
+ ); +} +``` + +