プロジェクト全体の構築
フロントエンド開発ツールチェーン概要
現代のフロントエンド開発では、複雑なプロジェクト要件に対応するための様々なツールが存在します。
主要ツールカテゴリ
- 静的型チェック: TypeScript, Flow
- コード品質検査: ESLint
- パッケージ管理: npm, Yarn
- トランスパイラ: Babel
- 開発サーバー: ホットリロード、HMR対応
- バンドラー: Webpack, Rollup, Parcel
- タスクランナー: Gulp, npm scripts
- スキャフォールディング: Vue CLI, Vite, Create React App
ビルドツール比較: Vue CLI vs Vite
Viteは従来のVue CLIに比べて10〜100倍高速な開発サーバーを提供します。
Vue CLIの特徴
- Webpackベースのビルドシステム
- 統合的なプロジェクトスキャフォールド
- プラグインエコシステム
- GUIインターフェース
Viteの特徴
- ブラウザのネイティブESモジュールを活用
- Rollupベースのビルド
- 高速な開発サーバー
- シンプルな構成
コード品質管理
ESLintの設定と活用
コードの一貫性を保つためにESLintを活用します。
// ESLint設定例
module.exports = {
extends: [
'eslint:recommended',
'@vue/typescript/recommended'
],
rules: {
'no-console': 'warn',
'no-unused-vars': 'error'
}
};
Prettierとの連携
コードフォーマットを自動化するためにPrettierを導入します。
// .prettierrc
{
"semi": true,
"singleQuote": true,
"tabWidth": 2
}
プロジェクト構造の設計
推奨ディレクトリ構造
src/
├── components/ # 共通コンポーネント
├── views/ # ページコンポーネント
├── store/ # 状態管理
├── router/ # ルーティング
├── hooks/ # カスタムフック
├── utils/ # ユーティリティ関数
└── types/ # TypeScript型定義
Gitワークフロー
Git Flowの基本構造
- master: 本番環境用ブランチ
- develop: 開発ベースブランチ
- feature/*: 機能開発ブランチ
- release/*: リリース準備ブランチ
- hotfix/*: 緊急修正ブランチ
UIコンポーネントライブラリ
Ant Design Vueの導入
// main.ts
import { createApp } from 'vue';
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/reset.css';
const application = createApp(App);
application.use(Antd);
application.mount('#app');
状態管理の実装
Vuex Storeの基本構造
// store/index.ts
import { createStore } from 'vuex';
interface AppState {
user: User | null;
settings: AppSettings;
}
export default createStore<AppState>({
state: {
user: null,
settings: {}
},
mutations: {
setUser(state, userData) {
state.user = userData;
}
},
actions: {
async fetchUser({ commit }, userId) {
const user = await api.getUser(userId);
commit('setUser', user);
}
}
});
ユーティリティライブラリの活用
UUIDの生成
import { v4 as generateId } from 'uuid';
const uniqueId = generateId();
console.log(uniqueId);
Lodashユーティリティ関数
import { pick, mapValues, without } from 'lodash-es';
const sampleData = { id: 1, name: 'Test', value: 100 };
const selectedProps = pick(sampleData, ['id', 'name']);
const transformedData = mapValues(sampleData, (value) => ({
type: typeof value,
value
}));
const numbers = [1, 2, 3, 4, 5];
const filteredNumbers = without(numbers, 3, 4);
TypeScriptユーティリティ型
Readonly型の使用
interface UserProfile {
username: string;
email: string;
}
const profile: Readonly<UserProfile> = {
username: 'developer',
email: 'dev@example.com'
};
PartialとRequiredの活用
interface ConfigOptions {
timeout?: number;
retries?: number;
}
// すべてのプロパティを必須にする
const requiredConfig: Required<ConfigOptions> = {
timeout: 5000,
retries: 3
};
// すべてのプロパティをオプションにする
const partialConfig: Partial<ConfigOptions> = {};
テスト戦略と実装
Jestテストフレームワーク
基本的なアサーション
describe('基本的なテスト', () => {
test('数値計算', () => {
expect(2 + 2).toBe(4);
expect(5).toBeGreaterThan(3);
});
test('オブジェクト比較', () => {
expect({ name: 'test' }).toEqual({ name: 'test' });
});
});
非同期処理のテスト
const fetchData = () => Promise.resolve('data');
test('非同期処理', async () => {
const result = await fetchData();
expect(result).toBe('data');
});
Vueコンポーネントテスト
コンポーネントのマウントとテスト
import { mount } from '@vue/test-utils';
import ButtonComponent from './Button.vue';
describe('Buttonコンポーネント', () => {
test('クリックイベントの発火', async () => {
const wrapper = mount(ButtonComponent, {
props: { label: 'Click Me' }
});
await wrapper.trigger('click');
expect(wrapper.emitted('click')).toBeTruthy();
});
});
TDD開発アプローチ
テスト駆動開発のサイクル
- テストケースの作成(失敗)
- 実装コードの記述(成功)
- リファクタリング(改善)
ColorPickerコンポーネントのTDD例
describe('ColorPicker', () => {
test('カラープレビューの表示', () => {
const wrapper = mount(ColorPicker, {
props: { value: '#ff0000' }
});
expect(wrapper.find('.color-preview').exists()).toBe(true);
});
test('カラー変更イベントの発火', async () => {
const wrapper = mount(ColorPicker);
await wrapper.find('.color-option').trigger('click');
expect(wrapper.emitted('update:value')).toHaveLength(1);
});
});
テスト環境の設定
Vue Test Utilsの設定
// jest.config.js
module.exports = {
preset: '@vue/cli-plugin-unit-jest',
testMatch: [
'**/__tests__/**/*.[jt]s?(x)',
'**/?(*.)+(spec|test).[jt]s?(x)'
]
};
モックの活用
API呼び出しのモック
jest.mock('axios', () => ({
get: jest.fn(() => Promise.resolve({
data: { id: 1, name: 'Mock User' }
}))
}));
タイマーのモック
jest.useFakeTimers();
test('タイマー処理', () => {
const callback = jest.fn();
setTimeout(callback, 1000);
jest.runAllTimers();
expect(callback).toHaveBeenCalled();
});