iT邦幫忙

2024 iThome 鐵人賽

DAY 28
0
Modern Web

React 學得動嗎系列 第 28

[Day 28] Gym Pro:提升系統擴展性與可維護性

  • 分享至 

  • xImage
  •  

今天,我們要來為系統加入一些功能。這些功能可能不會直接被使用者看到,但它們對於系統的長期健康發展有關。

1. 實現插件系統

首先,我們來實現一個簡單的插件系統,讓 Gym Pro 能夠更容易地擴展功能。

建立插件接口

src/types/Plugin.ts 中:

export interface Plugin {
  name: string;
  version: string;
  init: () => void;
  destroy: () => void;
}

建立插件管理器

src/services/pluginManager.ts 中:

import { Plugin } from '../types/Plugin';

class PluginManager {
  private plugins: Plugin[] = [];

  registerPlugin(plugin: Plugin) {
    this.plugins.push(plugin);
    plugin.init();
    console.log(`Plugin ${plugin.name} v${plugin.version} has been registered.`);
  }

  unregisterPlugin(pluginName: string) {
    const index = this.plugins.findIndex(p => p.name === pluginName);
    if (index !== -1) {
      const plugin = this.plugins[index];
      plugin.destroy();
      this.plugins.splice(index, 1);
      console.log(`Plugin ${plugin.name} has been unregistered.`);
    }
  }

  getPlugin(pluginName: string): Plugin | undefined {
    return this.plugins.find(p => p.name === pluginName);
  }
}

export const pluginManager = new PluginManager();

建立範例插件

src/plugins/customReportPlugin.ts 中:

import { Plugin } from '../types/Plugin';

const customReportPlugin: Plugin = {
  name: 'Custom Report Plugin',
  version: '1.0.0',
  init: () => {
    console.log('Custom Report Plugin initialized');
    // 這裡可以增加自定義報表的邏輯
  },
  destroy: () => {
    console.log('Custom Report Plugin destroyed');
    // 這裡可以清理插件資源
  }
};

export default customReportPlugin;

在應用中使用插件

src/App.tsx 中:

import React, { useEffect } from 'react';
import { pluginManager } from './services/pluginManager';
import customReportPlugin from './plugins/customReportPlugin';

function App() {
  useEffect(() => {
    pluginManager.registerPlugin(customReportPlugin);
    return () => {
      pluginManager.unregisterPlugin(customReportPlugin.name);
    };
  }, []);

  // ... 其他程式
}

2. 改進日誌記錄

接下來,我們來改進系統的日誌記錄功能,使用 winston 來實現更好的日誌管理。

安裝必要的套件

npm install winston

建立日誌服務

src/services/logger.ts 中:

import winston from 'winston';

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' }),
  ],
});

if (process.env.NODE_ENV !== 'production') {
  logger.add(new winston.transports.Console({
    format: winston.format.simple(),
  }));
}

export default logger;

在應用中使用日誌服務

現在,我們可以在整個應用中使用這個日誌服務:

import logger from './services/logger';

// 在需要記錄日誌的地方
logger.info('這是一條信息日誌');
logger.error('這是一條錯誤日誌', { error: new Error('發生錯誤') });

3. 優化打包和部署流程

為了讓 Gym Pro 更容易部署和維護,我們來優化打包和部署流程。我們使用 GitHub Actions 來實現自動化部署,我們也可以使用Vercel來做到自動化部屬。

建立 GitHub Actions 工作流

在專案根目錄建立 .github/workflows/deploy.yml 檔案:

name: Deploy

on:
  push:
    branches:
      - main

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Use Node.js
      uses: actions/setup-node@v2
      with:
        node-version: '14'
    - name: Install dependencies
      run: npm ci
    - name: Build
      run: npm run build
    - name: Deploy to GitHub Pages
      uses: peaceiris/actions-gh-pages@v3
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        publish_dir: ./build

這個工作流程會在每次推送到 main 分支時自動構建並部署應用到 GitHub Pages。

4. 國際化

最後,我們來為 Gym Pro 增加支援國際化,使其能夠支援多種語言。我們將使用 react-i18next 來實現這個功能。

安裝必要的套件

npm install react-i18next i18next

設置 i18next

src/i18n.ts 中:

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';

import enTranslations from './locales/en.json';
import zhTranslations from './locales/zh.json';

i18n
  .use(initReactI18next)
  .init({
    resources: {
      en: { translation: enTranslations },
      zh: { translation: zhTranslations },
    },
    lng: 'zh', // 預設語言
    fallbackLng: 'en',
    interpolation: {
      escapeValue: false,
    },
  });

export default i18n;

建立翻譯文件

src/locales/zh.json 中:

{
  "welcome": "歡迎使用 Gym Pro",
  "members": "會員",
  "classes": "課程",
  "reports": "報表"
}

src/locales/en.json 中:

{
  "welcome": "Welcome to Gym Pro",
  "members": "Members",
  "classes": "Classes",
  "reports": "Reports"
}

在應用中使用國際化

src/index.tsx 中:

import React from 'react';
import ReactDOM from 'react-dom';
import './i18n';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

在組件中使用翻譯:

import React from 'react';
import { useTranslation } from 'react-i18next';

const Welcome: React.FC = () => {
  const { t } = useTranslation();

  return <h1>{t('welcome')}</h1>;
};

export default Welcome;

小結

今天我們為 Gym Pro 系統增加了一些功能:

  1. 實現了插件系統,讓系統更容易擴展。
  2. 改進了日誌記錄功能,使用 winston 進行更強大的日誌管理。
  3. 優化了打包和部署流程,使用 GitHub Actions 實現自動化部署。
  4. 實現了國際化,讓系統支援多種語言。

上一篇
[Day 27] Gym Pro:優化用戶體驗與增加實用功能
下一篇
[Day 29] Gym Pro:系統收尾與最後優化
系列文
React 學得動嗎30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言