JavaScript エコシステム完全ガイド 2024

JavaScript の現在地

JavaScriptは今やWeb開発の中心的存在であり、フロントエンドからバックエンド、モバイル、デスクトップアプリケーションまで、あらゆる場所で使用されています。

ランタイム環境

Node.js

依然として最も人気のあるサーバーサイドランタイム:

// Node.js 20の新機能
import { test } from 'node:test';
import assert from 'node:assert';

test('非同期テストの例', async (t) => {
  const result = await fetchData();
  assert.strictEqual(result.status, 200);
});

Deno

セキュリティファーストの設計:

// Denoでの実行例
// deno run --allow-net server.ts
import { serve } from "https://deno.land/std/http/server.ts";

serve((req) => new Response("Hello, Deno!"), { port: 8000 });

Bun

超高速な新世代ランタイム:

// Bunの高速サーバー
Bun.serve({
  port: 3000,
  fetch(request) {
    return new Response("Bunは速い!");
  },
});

フロントエンドフレームワーク

React 18+

並行レンダリングとサーバーコンポーネント:

// React Server Components
// app/page.tsx
async function Page() {
  const data = await fetch('https://api.example.com/data');
  const posts = await data.json();
  
  return (
    <div>
      {posts.map(post => (
        <article key={post.id}>
          <h2>{post.title}</h2>
          <p>{post.content}</p>
        </article>
      ))}
    </div>
  );
}

Vue 3

Composition APIとTypeScript統合:

<script setup lang="ts">
import { ref, computed } from 'vue'

interface Todo {
  id: number
  text: string
  done: boolean
}

const todos = ref<Todo[]>([])
const completedCount = computed(() => 
  todos.value.filter(todo => todo.done).length
)

function addTodo(text: string) {
  todos.value.push({
    id: Date.now(),
    text,
    done: false
  })
}
</script>

Svelte/SvelteKit

コンパイル時最適化:

<script>
  let count = 0;
  $: doubled = count * 2;
  
  function increment() {
    count += 1;
  }
</script>

<button on:click={increment}>
  カウント: {count}
</button>
<p>2倍: {doubled}</p>

ビルドツール

Vite

高速な開発体験:

// vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  optimizeDeps: {
    include: ['react', 'react-dom']
  },
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom']
        }
      }
    }
  }
})

esbuild

超高速バンドラー:

// build.js
import * as esbuild from 'esbuild'

await esbuild.build({
  entryPoints: ['app.js'],
  bundle: true,
  minify: true,
  sourcemap: true,
  target: ['es2020'],
  outfile: 'dist/app.js',
})

Turbopack

Next.jsの新しいバンドラー:

// next.config.js
module.exports = {
  experimental: {
    turbo: {
      rules: {
        '*.svg': {
          loaders: ['@svgr/webpack'],
          as: '*.js',
        },
      },
    },
  },
}

型システム

TypeScript 5

より強力な型推論:

// const型パラメータ
function createState<const T>(initial: T) {
  let state = initial;
  return {
    get: () => state,
    set: (value: T) => { state = value }
  }
}

const numberState = createState(42);
// numberStateの型は { get: () => 42, set: (value: 42) => void }

// satisfies演算子
type Colors = "red" | "green" | "blue";
type RGB = [number, number, number];

const palette = {
  red: [255, 0, 0],
  green: [0, 255, 0],
  blue: [0, 0, 255]
} satisfies Record<Colors, RGB>;

状態管理

Zustand

シンプルで軽量:

import { create } from 'zustand'

const useStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
  reset: () => set({ count: 0 })
}))

Jotai

原子的状態管理:

import { atom, useAtom } from 'jotai'

const countAtom = atom(0)
const doubledAtom = atom((get) => get(countAtom) * 2)

function Counter() {
  const [count, setCount] = useAtom(countAtom)
  const [doubled] = useAtom(doubledAtom)
  
  return (
    <div>
      <p>カウント: {count}, 2: {doubled}</p>
      <button onClick={() => setCount(c => c + 1)}>+</button>
    </div>
  )
}

テスティング

Vitest

Vite対応のテストランナー:

// math.test.js
import { expect, test, describe } from 'vitest'
import { add, multiply } from './math'

describe('数学関数', () => {
  test('加算', () => {
    expect(add(2, 3)).toBe(5)
  })
  
  test('乗算', () => {
    expect(multiply(3, 4)).toBe(12)
  })
})

Playwright

E2Eテストの新標準:

// e2e.spec.js
import { test, expect } from '@playwright/test'

test('ホームページのテスト', async ({ page }) => {
  await page.goto('https://example.com')
  
  // タイトルの確認
  await expect(page).toHaveTitle(/Example/)
  
  // ボタンクリック
  await page.click('button[type="submit"]')
  
  // 結果の確認
  await expect(page.locator('.success')).toBeVisible()
})

パッケージマネージャー

pnpm

効率的なディスク使用:

# ワークスペースの設定
pnpm init
pnpm add -D typescript
pnpm add --filter @myapp/web react

Yarn Berry

プラグアンドプレイ:

# .yarnrc.yml
nodeLinker: pnp
enableGlobalCache: true

plugins:
  - path: .yarn/plugins/@yarnpkg/plugin-typescript.cjs
    spec: "@yarnpkg/plugin-typescript"

モノレポツール

Turborepo

高速なビルドパイプライン:

// turbo.json
{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    },
    "test": {
      "dependsOn": ["build"],
      "inputs": ["src/**/*.tsx", "src/**/*.ts"]
    }
  }
}

Nx

エンタープライズ向けツール:

// nx.json
{
  "tasksRunnerOptions": {
    "default": {
      "runner": "@nrwl/nx-cloud",
      "options": {
        "cacheableOperations": ["build", "test", "lint"],
        "parallel": 3
      }
    }
  }
}

APIレイヤー

tRPC

型安全なAPI:

// server/routers/user.ts
import { z } from 'zod'
import { router, publicProcedure } from '../trpc'

export const userRouter = router({
  getUser: publicProcedure
    .input(z.object({ id: z.string() }))
    .query(async ({ input }) => {
      return await db.user.findUnique({
        where: { id: input.id }
      })
    }),
})

// client/app.tsx
import { trpc } from './utils/trpc'

function UserProfile({ userId }) {
  const { data } = trpc.user.getUser.useQuery({ id: userId })
  return <div>{data?.name}</div>
}

GraphQL

柔軟なデータフェッチング:

// スキーマ定義
const typeDefs = `
  type Query {
    posts(limit: Int): [Post]
  }
  
  type Post {
    id: ID!
    title: String!
    content: String!
    author: User!
  }
  
  type User {
    id: ID!
    name: String!
    email: String!
  }
`

// リゾルバー
const resolvers = {
  Query: {
    posts: (_, { limit }) => db.posts.findMany({ take: limit })
  },
  Post: {
    author: (post) => db.users.findUnique({ where: { id: post.authorId } })
  }
}

新しいWeb API

Web Components

class TodoList extends HTMLElement {
  constructor() {
    super()
    this.attachShadow({ mode: 'open' })
    this.todos = []
  }
  
  connectedCallback() {
    this.render()
  }
  
  render() {
    this.shadowRoot.innerHTML = `
      <style>
        ul { list-style: none; padding: 0; }
        li { padding: 0.5rem; border-bottom: 1px solid #eee; }
      </style>
      <ul>
        ${this.todos.map(todo => `
          <li>${todo.text}</li>
        `).join('')}
      </ul>
    `
  }
}

customElements.define('todo-list', TodoList)

まとめ

2024年のJavaScriptエコシステムは、より成熟し、開発者体験の向上に焦点を当てています。重要なトレンドは:

  1. パフォーマンス: Bun、esbuild、Turbopackなど高速ツールの台頭
  2. 型安全性: TypeScriptの普及とtRPCなどの型安全ツール
  3. 開発者体験: Vite、Vitestなどの高速な開発ツール
  4. エッジコンピューティング: エッジランタイムの成熟

適切なツールを選択し、プロジェクトの要件に合わせて使用することが成功の鍵です。