Học React Native từ cơ bản đến nâng cao - Phần 11: Chia môi trường development, staging, production hoặc cách clone app thuận tiện nhất cho react native

source: https://hackernoon.com/drafts/ro2832a9.png

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:

  1. Chuẩn bị máy macos để build cho cả android và ios
  2. React native: 0.63.3
  3. Xcode: 12.1
  4. Android Studio: 4.1
  5. 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


All Rights Reserved