@namphuongtechnologi/react-feature-flags
v1.1.4
Published
A simple and flexible React toolkit for managing feature flags with a custom fetcher.
Maintainers
Readme
@namphuongtechnologi/react-feature-flags
Thư viện React đơn giản và linh hoạt để quản lý feature flags với khả năng tùy biến fetcher.
📦 Cài đặt
npm install @namphuongtechnologi/react-feature-flags⚙️ Yêu cầu hệ thống
Thư viện này yêu cầu:
- React >= 17.0.0
- React DOM >= 17.0.0
- Axios >= 1.13.2 (tùy chọn, chỉ cần khi sử dụng
createFetcher)
🚀 Hướng dẫn nhanh
1. Tạo hàm fetcher
Hàm này có nhiệm vụ lấy dữ liệu flag từ API và trả về một object có dạng Record<string, boolean>.
Bạn có thể sử dụng hàm createFetcher để tạo fetcher một cách nhanh chóng, hoặc tự tạo một hàm fetcher tùy chỉnh.
Ví dụ 1: Sử dụng createFetcher (khuyến nghị)
// /flagFetcher.ts
import { createFetcher } from '@namphuongtechnologi/react-feature-flags';
import { myAxios } from '../config/axios'; // Giả sử bạn đã có một instance axios
const currentEnv = import.meta.env.VITE_APP_ENV; // Lấy môi trường hiện tại
// Tạo fetcher với các tùy chọn nâng cao
export const myAppFetcher = createFetcher({
apiUrl: `/feature-flags`,
currentEnv: currentEnv,
axiosInstance: myAxios,
envToKeyMap: {
staging: 'is_active_on_staging', // Ánh xạ môi trường 'staging' với key 'is_active_on_staging'
},
transformResponse: (response) => response.data.results, // Lấy dữ liệu từ cấu trúc trả về khác
});apiUrl: Endpoint API để lấy danh sách các flag.currentEnv: Tên môi trường hiện tại của ứng dụng (development,staging,production,...).axiosInstance(Tùy chọn): Tái sử dụng một instance axios đã có sẵn trong dự án của bạn.envToKeyMap(Tùy chọn): Ghi đè hoặc bổ sung ánh xạ giữa tên môi trường và tên thuộc tính trong dữ liệu API.transformResponse(Tùy chọn): Một hàm để chỉ chofetchercách trích xuất đúng mảng dữ liệu từ response của API.
2. Bọc ứng dụng trong FeatureFlagProvider
Trong file main.tsx (hoặc file gốc của ứng dụng), hãy bọc component App của bạn.
import { FeatureFlagProvider } from '@namphuongtechnologi/react-feature-flags';
import { myAppFetcher } from './flagFetcher';
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<FeatureFlagProvider
fetcher={myAppFetcher}
loadingComponent={<h1>Đang tải cấu hình...</h1>}
>
<App />
</FeatureFlagProvider>
</React.StrictMode>,
);3. Sử dụng flag trong Component
Sử dụng hook useFeatureFlags để truy cập vào trạng thái của các flag hoặc dùng component <FeatureComponent> để render UI có điều kiện.
Cách 1: Dùng hook useFeatureFlags
import { useFeatureFlags } from '@namphuongtechnologi/react-feature-flags';
function Dashboard() {
const { flags, isLoading, error } = useFeatureFlags();
if (isLoading) {
return <p>Đang tải trạng thái tính năng...</p>;
}
if (error) {
return <p>Đã xảy ra lỗi khi tải feature flags</p>;
}
return (
<div>
{flags['enableNewLayout'] && <h2>Giao diện mới đã được bật!</h2>}
{flags['showAnalytics'] && <AnalyticsDashboard />}
</div>
);
}Cách 2: Dùng component <FeatureComponent>
import { FeatureComponent } from '@namphuongtechnologi/react-feature-flags';
function MyComponent() {
return (
<FeatureComponent name='showNewWidget' fallback={<OldWidget />}>
<NewWidget />
</FeatureComponent>
);
}📚 API chi tiết
FeatureFlagProvider
Component gốc cung cấp context cho toàn bộ ứng dụng.
| Prop | Kiểu | Bắt buộc | Mô tả |
| :----------------- | :--------------------------------------- | :------- | :------------------------------------------------ |
| fetcher | () => Promise<Record<string, boolean>> | Có | Hàm async trả về một object chứa các flag. |
| children | React.ReactNode | Có | Các component con của ứng dụng. |
| loadingComponent | React.ReactNode | Không | Component hiển thị trong khi fetcher đang chạy. |
useFeatureFlags()
Hook để truy cập vào trạng thái của các flag.
Giá trị trả về:
flags: Record<string, boolean>: Object chứa các cặp key-value của flag.isLoading: boolean:truekhifetcherđang chạy.error: unknown: Chứa lỗi nếufetcherthất bại.
<FeatureComponent> Component
Một cách khai báo để render UI có điều kiện dựa trên flag.
| Prop | Kiểu | Bắt buộc | Mô tả |
| :--------- | :---------------- | :------- | :-------------------------------------- |
| name | string | Có | Tên của flag cần kiểm tra. |
| children | React.ReactNode | Có | Nội dung sẽ render nếu flag là true. |
| fallback | React.ReactNode | Không | Nội dung sẽ render nếu flag là false. |
filterByFeature()
Hàm tiện ích để lọc một mảng (ví dụ: menu, tabs) dựa trên các flag. Mỗi item trong mảng cần có thuộc tính featureFlag: string. Những item không có thuộc tính này sẽ luôn được giữ lại.
Hàm này hỗ trợ lọc đệ quy cho các item có children (menu đa cấp).
import {
useFeatureFlags,
filterByFeature,
} from '@namphuongtechnologi/react-feature-flags';
interface MenuItem {
key: string;
label: string;
featureFlag?: string;
children?: MenuItem[];
}
const allMenuItems: MenuItem[] = [
{ key: '/dashboard', label: 'Dashboard' },
{
key: '/analytics',
label: 'Analytics',
featureFlag: 'enableAnalyticsPage',
},
{
key: '/settings',
label: 'Settings',
featureFlag: 'enableSettingsV2',
children: [
{ key: '/settings/profile', label: 'Profile' },
{
key: '/settings/advanced',
label: 'Advanced',
featureFlag: 'enableAdvancedSettings',
},
],
},
];
function MainMenu() {
const { flags } = useFeatureFlags();
const visibleMenuItems = filterByFeature(allMenuItems, flags);
// Render menu với các item đã được lọc (bao gồm cả children)
return <Menu items={visibleMenuItems} />;
}createFetcher(options)
Hàm factory để nhanh chóng tạo fetcher cho API. Hàm này sẽ tự động fetch dữ liệu từ API và chuyển đổi thành format Record<string, boolean>.
| Option | Kiểu | Bắt buộc | Mô tả |
| :------------------ | :---------------------------- | :------- | :----------------------------------------------------------------------------------------- |
| apiUrl | string | Có | URL endpoint để fetch danh sách các flag. |
| axiosInstance | AxiosInstance | Không | Một instance axios đã được cấu hình sẵn. Nếu không cung cấp, sẽ tạo một instance mặc định. |
| transformResponse | (res: any) => GenericFlag[] | Không | Hàm để trích xuất mảng dữ liệu từ response. Mặc định: (response) => response.data.data |
| activeKey | string | Không | Tên thuộc tính trong object flag để kiểm tra trạng thái active. Mặc định: "isActive" |
Lưu ý:
- Mỗi flag trong mảng cần có thuộc tính
code: stringđể làm key trong object kết quả. - Thuộc tính được chỉ định bởi
activeKeyphải là kiểuboolean.
🔧 TypeScript
Thư viện được viết hoàn toàn bằng TypeScript và export các types sau:
import type {
Flags,
FlagFetcher,
FeatureFlagContextType,
FeatureFlagProviderProps,
FetcherOptions,
} from '@namphuongtechnologi/react-feature-flags';📝 Ví dụ đầy đủ
Xem thêm các ví dụ chi tiết trong phần Hướng dẫn nhanh phía trên.
🧪 Testing và Publishing
Kiểm tra build local
Trước khi publish, bạn nên test build và kiểm tra package local:
# Build thư viện
npm run build
# Tạo file .tgz để test local
npm run test:localFile .tgz sẽ được tạo trong thư mục gốc. Bạn có thể test package này trong một dự án khác:
# Trong dự án test
npm install /path/to/namphuongtechnologi-react-feature-flags-1.1.2.tgzKiểm tra nội dung package
Kiểm tra xem những file nào sẽ được đưa lên npm:
# Xem danh sách files sẽ được publish
npm pack --dry-runPublish lên npm
1. Đăng nhập vào npm
# Đăng nhập vào npm (lần đầu tiên)
npm login
# Kiểm tra tài khoản hiện tại
npm whoami2. Kiểm tra thông tin package
Đảm bảo các thông tin trong package.json đã chính xác:
name: Tên package (phải match với scope trên npm)version: Version hiện tạidescription: Mô tả packageauthor: Tác giảlicense: Giấy phéprepository: Link repository (nếu có)
3. Tăng version và build
Bạn có thể sử dụng các script có sẵn để tăng version tự động:
# Tăng patch version (1.1.2 -> 1.1.3)
npm run release:patch
# Tăng minor version (1.1.2 -> 1.2.0)
npm run release:minor
# Tăng major version (1.1.2 -> 2.0.0)
npm run release:majorHoặc tăng version thủ công:
# Tăng version (sẽ tự động update package.json)
npm version patch # hoặc minor, major
# Build lại sau khi tăng version
npm run build4. Publish lên npm
# Publish lên npm registry
npm publish --access publicLưu ý: Với scoped package (@namphuongtechnologi/react-feature-flags), bạn cần thêm flag --access public để publish công khai.
5. Xác nhận publish thành công
Kiểm tra package đã được publish:
# Xem thông tin package trên npm
npm view @namphuongtechnologi/react-feature-flags
# Hoặc truy cập trực tiếp
# https://www.npmjs.com/package/@namphuongtechnologi/react-feature-flagsWorkflow đầy đủ
# 1. Đảm bảo code đã được commit
git status
# 2. Chạy test (nếu có)
# npm test
# 3. Tăng version và build
npm run release:patch # hoặc minor, major
# 4. Test package local (tùy chọn)
npm run test:local
# 5. Publish lên npm
npm publish --access public
# 6. Commit và push version mới
git add package.json package-lock.json
git commit -m "chore: bump version to x.x.x"
git push
# 7. Tạo git tag (nếu cần)
git tag v1.1.3
git push origin v1.1.3Troubleshooting
Lỗi: "You do not have permission to publish"
- Đảm bảo bạn đã đăng nhập đúng tài khoản có quyền publish
- Kiểm tra xem package name đã được sử dụng bởi người khác chưa
- Với scoped package, đảm bảo bạn là owner của organization
@namphuongtechnologi
Lỗi: "Package version already exists"
- Tăng version mới trước khi publish
- Kiểm tra version hiện tại:
npm view @namphuongtechnologi/react-feature-flags version
Lỗi: "Invalid package name"
- Đảm bảo package name tuân theo quy tắc đặt tên của npm
- Scoped package phải có format:
@scope/package-name
🤝 Đóng góp
Mọi đóng góp đều được chào đón! Vui lòng mở issue hoặc pull request trên GitHub.
📄 License
MIT
