I. Dùng khi nào ?
Mục đích của bài viết này sẽ giúp:
1. Để clone ra nhiều app trên cùng 1 project
Okay có tình huống tương đối phổ biến như sau:
Bạn có 1 project ngon lành về đọc tin tức nhưng giờ bạn muốn tạo các app khác nhau để bán cho khách hàng như App thể thao, App tin tức học đường, App tin tức chính trị, ... và bạn thấy tất cả những app đó đều có thể dùng chung 1 project. Việc duy nhất ở đây chỉ là đổi biến môi trường, thay icon hay style cho app là xong .
Vậy đây chính là giải pháp của bạn để dễ dàng đóng gói 1 app mới cho khách hàng 1 cách nhanh chóng và thuận tiện cho việc maintain (nếu như không có sự sai khác về business )
2. Để thuận tiện cho việc phát triển, testing và đưa lên production
Tình huống thứ 2 như sau:
Bạn làm app cho ngân hàng nhưng bạn không thể dùng server thật để chạy thử các chức năng trừ/cộng tiền cho khách hàng được; bạn cần 1 server mock để tiện cho việc coding và test hoàn thiện nhất rồi mới đưa cho khách hàng sử dụng.
Câu hỏi trong đầu của bạn sẽ là "Làm cách nào để đổi giữa các môi trường dễ dàng nhất ?"
Còn rất nhiều tình huống khác nữa bạn sẽ gặp phải nhưng tạm thời tôi chỉ nêu như vậy để các bạn có thể dễ dàng hình dung trước khi đi vào sử dụng
Do bài viết khá dài nên tôi sẽ giải thích ngắn gọn nhưng thay vào đó tôi chèn nhiều hình ảnh để các bạn dễ làm theo
Okay bắt đầu thôi !
II. Demo
Đầu tiên tôi sẽ demo trên Xcode và Android Studio trước để các bạn dễ hình dung và mường tượng được kết quả của bài viết chia môi trường này
Đây là repo tôi đã làm để các bạn có thể xem được kết quả https://github.com/oTranThanhNghia/SimpleAppReactNative1.
Chú ý bên ios do tôi không thể chia sẻ certificate cho các bạn được nên các bạn phải làm theo hướng dẫn để chạy app nhé
1. Android
Chọn 1 loại trong danh sách dưới đây
Kết quả trên điện thoại
2. iOS
Trên Xcode sẽ có 3 môi trường để chọn
Còn đây là kết quả trên điện thoại
III. Hướng dẫn cài đặt
Trong bài viết tôi sẽ hướng dẫn tạo ra 3 môi trường là development, staging và production. Còn việc tại sao lại có 3 môi trường này thì mình đưa ra 1 bài viết khác để tóm tắt ngắn gọn nhất cho bạn là:
Difference Between Development, Stage, And Production
Góc ủng hộ
Bài viết này mình dựa trên https://github.com/maxkomarychev/react-native-ultimate-config và chạy thấy khá ổn định cho các dự án react native mà mình đã làm trong thời gian qua.
Vậy nên các bạn hãy vào ủng hộ 1 star để ủng hộ mấy anh em dev phát triển thư viện này nhé. Mình xin cảm ơn !
1. Các bước chuẩn bị
Để tiện theo dõi bài viết tôi cần thống nhất những thứ sau:
- Chuẩn bị máy macos để build cho cả android và ios
- React native: 0.63.3
- Xcode: 12.1
- Android Studio: 4.1
- Node: 14.7.0
Bên phía khác gồm:
- Chuẩn bị backend cho các môi trường development, staging và production
- Tạo tài khoản firebase với các môi trường development, staging và production
Ví dụ tôi đã tạo sẵn như dưới đây
- Tạo môi trường development, staging và production tương ứng cùng với các dịch vụ bên thứ 3 khác như Facebook, Twitter, ...
Chú ý: Bạn phải chuẩn bị máy mac thật khoẻ để build nhé. Vì khi dự án càng lớn thì build app sẽ càng lâu. Nhất là đối với ios, build ra được 1 file ipa chắc bạn có thể ngủ được 1 giấc kha khá
2. Về project React Native
$ yarn add react-native-ultimate-config
$ cd ios
$ pod install
Dựa theo tài liệu https://github.com/maxkomarychev/react-native-ultimate-config/blob/master/docs/quickstart.md
Tạo 3 môi trường dev, stag và prod
file .env
ENV=init
- file .env.dev.yaml
ENV: dev
BASE_URL: https://newsapi.org
API_KEY: 2761498486644b8e8bd7af2861768628
- file .env.prod.yaml
ENV: prod
BASE_URL: https://newsapi.org
API_KEY: 2761498486644b8e8bd7af2861768628
- file .env.stag.yaml
ENV: stag
BASE_URL: https://newsapi.org
API_KEY: 2761498486644b8e8bd7af2861768628
cập nhật .gitignore
# react-native-ultimate-config
rnuc.xcconfig
Chạy script sau để sinh các file cho native
$ yarn rnuc .env
Tạo file config để sử dụng trong javascript
3. Về Android
Tham khảo https://developer.android.com/studio/build/build-variants
thêm đoạn script sau
flavorDimensions "root"
productFlavors {
dev {
applicationId "com.ngh.simpleappreactnative1.dev"
dimension 'root'
signingConfig signingConfigs.debug
}
stag {
applicationId "com.ngh.simpleappreactnative1.stag"
dimension 'root'
signingConfig signingConfigs.debug
}
prod {
applicationId "com.ngh.simpleappreactnative1"
dimension 'root'
signingConfig signingConfigs.release
}
}
thêm signingConfigs cho release
Chú ý: Các bản phải tạo keystore riêng cho production nhé. Còn trong bài viết này tôi sẽ sử dụng lại debug keystore để demo
vào app/build.gradle
okay giờ các bạn thêm script sau để nhận các file .env đã được tạo ở trên ( docs: https://github.com/maxkomarychev/react-native-ultimate-config/blob/master/docs/cookbook.md#using-multiple-flavors-android)
trong file android/app/build.gradle
Trong file MainApplication.java thêm đoạn sau
// import module
import com.reactnativeultimateconfig.UltimateConfigModule;
...
@Override
public void onCreate() {
super.onCreate();
...
UltimateConfigModule.setBuildConfig(BuildConfig.class); // expose
}
Tạo config cho mỗi product flavor
về file google-services.json
cho mỗi loại thì các bạn tải ở đây
Khi đã tạo xong thì sẽ được kết quả như sau trên Android Studio
4. Về iOS
a) Chuẩn bị tài khoản apple developer (mất phí) và tạo Bundle Identifier
Bundle ID này sẽ là cho môi trường production com.ngh.simpleapp.reactnative3
Tương tự với 2 môi trường Development và Staging còn lại tôi sẽ tạo được kết quả như sau
Lưu ý: Bạn vào keychain access rồi export ra AppleDistributionCertificates.p12 và AppleDevelopmentCertificates.p12 để người khác sử dụng nữa nhé
b) Tạo certificate
Bạn có thể bỏ qua bước này nếu đã có certificate rồi.
tạo file request
tạo certificate
Các bạn sẽ phải tạo 2 certificate (Development và Distribution) các bước thì y hệt giống nhau
còn bạn nào bị báo đỏ thì kiểm tra mình có thể dùng lại certificate đã có (vì bạn đã tạo đến giới hạn apple cho phép)
Chọn file request bạn đã có ở trên
Ấn download
Khi tải về bạn sẽ nhận được 1 file
Sau đó bạn click đúp để cài certificate đó vào máy.
Bạn mở app Keychain Access trên máy mac sẽ thấy
và thời gian expires giống với trên trang developer apple ở trên
Tương tự đối với certificate cho distribution thì sẽ có kết quả như sau
c) Tạo profile
Development
Các bạn cần tạo ít nhất 3 môi trường (Development, Ad Hoc và App Store ) cho app ios
tiếp tục demo với development
Chọn certificate
Chọn các device cho phép chạy app
Đặt tên cho provisioning profile
Ad Hoc và App Store
Tương tự như development bạn sẽ chọn app ID, certificate và các devices
Khi tạo xong tất cả thì bạn upload lên đâu đó để team bạn dùng chung nhé
Ví dụ để lên google drive chẳng hạn
d) Cấu hình trên xcode
Sau khi cài đặtreact-native-ultimate-config
và chạy lệnh
$ yarn rnuc .env
thì sẽ có 1 file rnuc.xcconfig
xuất hiện trong folder ios/
của bạn
Lúc này bạn kéo file rnuc.xcconfig
vào xcode như sau
sau đó chọn target bạn muốn
b.1. Tạo Configuration mới
Trong setting của project xcode -> chọn phần project, tab Info, tìm phần Configurations, sau đó ấn nút + để thực hiện Duplicate Debug Configuration để tạo ra DebugDev, DebugStag và đổi tên Debug -> DebugProd, tương tự Duplicate Release Configuration để tạo ra ReleaseDev, ReleaseStag và đổi tên Release -> ReleaseProd
Kết quả sẽ như sau
Đổi based on configuration file về rnuc
b.2. Tạo scheme mới
Ấn vào biểu tượng app góc trên bên trái xcode -> Chọn Manage scheme
Ấn nút + để tạo thêm 2 scheme mới là SimpleAppReactNative1_Dev, SimpleAppReactNative1_Stag
Sau đó sửa tên scheme cũ thành SimpleAppReactNative1_Prod
Bạn phải chắc chắn chọn target SimpleAppReactNative1 là app như hình ảnh dưới đây
Kết quả tạo xong scheme như sau
và ở xcode sẽ xuất hiện 3 scheme
b.3. Thiết lập config build cho Scheme
Edit 3 schemes mới với config : Run, Test, Analyze chọn build configuration Debug<config tương ứng> , Profile và Archive chọn build configuration Release<config tương ứng>
- Scheme: SimpleAppReactNative1_Dev
Vào Build-> pre-actions để tạo script
chọn target cho provide build setting from
Thêm script theo tài liệu https://github.com/maxkomarychev/react-native-ultimate-config/blob/master/docs/cookbook.md#using-multiple-schemes-ios
if [ -d "$HOME/.nvm" ]; then
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
fi
RN_ROOT_DIR=$(dirname "$PROJECT_DIR")
cd "$RN_ROOT_DIR"
yarn run rnuc ".env.dev.yaml"
- Scheme: SimpleAppReactNative1_Stag
Với Build-> pre-actions cũng tương tự như Dev
- Scheme: SimpleAppReactNative1_Prod
Với Build-> pre-actions cũng tương tự như trên
Bạn mở file Podfile thêm những config sau (dựa theo config project của cocoapods )
Rồi chạy lại lệnh
$ pod install
b.4. Thiết lập Info.plist theo Scheme
Clone file Info.plist, để cùng thư mục và sửa tên thành Info-Prod.plist, Info-Stag.plist, Info-Dev.plist và add vào project. Mỗi 1 scheme sẽ có 1 .plist riêng để tiện cấu hình
Kết quả sẽ như sau
Sửa lại path tương ứng
b.5. Thiết lập Bundle Identifier tương ứng với scheme
Như đã tạo các Bundle Identifier trên developer apple
thì các bạn sẽ sửa tương ứng như sau
b.6 Thiết lập Firebase config theo Scheme tương ứng
Tạo 1 thư mục mới tên là AppConfig bên trong chia ra như sau
Mỗi file GoogleService-Info.plist sẽ được tải về từ đây
Vào Build Phase thêm script như sau: https://stackoverflow.com/a/48789232
# Type a script or drag a script file from your workspace to insert its path.
PATH_TO_GOOGLE_PLISTS="${PROJECT_DIR}/SimpleAppReactNative1/AppConfig"
case "${CONFIGURATION}" in
"DebugDev" | "ReleaseDev" )
cp -r "$PATH_TO_GOOGLE_PLISTS/Dev/GoogleService-Info.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist" ;;
"DebugStag" | "ReleaseStag" )
cp -r "$PATH_TO_GOOGLE_PLISTS/Stag/GoogleService-Info.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist" ;;
"DebugProd" | "ReleaseProd" )
cp -r "$PATH_TO_GOOGLE_PLISTS/Prod/GoogleService-Info.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist" ;;
*)
;;
esac
Lưu ý trong Target -> Build Phases -> Copy Bundle Resources Chỉ nên để 1 file GoogleSerivce-Info.plist. Nếu nhiều hơn thì sẽ build lỗi
Okay vậy đến đây là xong. Nếu có bất kỳ vấn đề nào khi đang làm, bạn có thể comment ở dưới để mình hỗ trợ nhé
IV. Tài liệu tham khảo
https://github.com/maxkomarychev/react-native-ultimate-config