Expo 33.0 이상의 버전을 이용하면 React Native Web 이 built-in 되어 있어서 편하게 모바일과 웹 개발을 동시에 할 수 있지만, Expo 를 이용하게 되면 발생되는 Limitation 때문에 Yarn Workspace 를 이용하여 Mono Repo 를 구성하고자 합니다.
이 프로젝트에서는 react 16.12.0, react-native 0.61.5 를 사용합니다.
$ git clone https://github.com/wecanooo/react-native-web-mono-repo.git$ cd react-native-web-mono-repo$ yarn$ cd packages/mobile/ios$ pod install$ cd -$ yarn workspace web start$ yarn workspace common watch$ yarn workspace mobile start$ yarn workspace ios또는$ yarn workspace android
ios emulator, android emulator 설치에 대한 내용은 여기에서 다루지 않습니다.
아래 Step by Step 섹션은 이 프로젝트를 만들어가는 과정에 대해서 다른 내용입니다.
이 프로젝트에서는 다음과 같은 기술들이 사용됩니다.
-
Mono Repo 프로젝트 생성
- package.json 생성:
$ yarn init -y - tsconfig.json 생성:
$ tsc --init - tsconfig.base.json 생성
- react-native 및 typescript 의존성 설정
- package.json 에 workspaces, scripts 설정
- package.json 생성:
-
Package 구성
-
$ rm yarn.lock && rm -rf node_modules -
$ mkdir -p packages/common/src packages/mobile packages/web
-
-
-
$ gem install cocoapods -
$ npx react-native init mobile -
$ rm yarn.lock && rm -rf node_modules - Project Root 에서
$ yarn을 실행 - Packages 내의 프로젝트 내부에 있는 node_modules 에 패키지가 설치되는 것이 아니라 Project Root 의 node_modules 에 설치가 되는 것을 확인해야 합니다.
-
$ yarn add -D typescript @types/jest @types/react @types/react-native @types/react-test-renderer
-
-
Mono Repo 구성을 위한 React Native 프로젝트 튜닝 (for iOS)
- 찾기 & 변경 기능을 통해
../../node_modules/react-native/라고 되어 있는 값들을 모두../../../../node_modules/react-native/로 변경 -
metro.config.js파일을 다음과 같이 변경
const path = require("path"); module.exports = { projectRoot: path.resolve(__dirname, "../../"), transformer: { getTransformOptions: async () => ({ transform: { experimentalImportSupport: false, inlineRequires: false } }) } };
-
$ open packages/mobile/ios/mobile.xcodeproj/수행 후AppDelegate.m파일의jsBundleURLForBundleRoot:@"index"파일의index부분을packages/mobile/index로 변경 - XCode 의
Build Phases > Bundle React Native code and Images설정에 다음의 값으로 변경
export NODE_BINARY=node export EXTRA_PACKAGER_ARGS="--entry-file packages/mobile/index.js" ../../../node_modules/react-native/scripts/react-native-xcode.sh
- Podfile 에서
require_relative항목의 경로를 수정한 뒤pod install수행 -
$ yarn workspace mobile start와$ yarn ios를 통해 모바일에서 실행이 되는지 확인
- 찾기 & 변경 기능을 통해
-
Mono Repo 구성을 위한 React Native 프로젝트 튜닝 (for Android)
-
packages/mobile/android/app/src/main/java/com/myprojectname/MainApplication.java파일의getJSMainModuleName함수의 내용을return "index";에서return "packages/mobile/index";로 변경 -
packages/mobile/android/app/build.gradle파일 내의project.ext.react =부분을 다음의 코드로 변경하고apply from:부분의 경로를 Project Root 로 설정
project.ext.react = [ entryFile: "packages/mobile/index.js", root: "../../../../" ]-
settings.gradle파일의apply from:항목의 경로를../../../node_modules/~로 변경 -
$ yarn android로 실행이 되는지 확인 (Android Studio 다운로드 및 AVD Manager 설정에 대한 설명은 다루지 않습니다.)
-
-
Common Packages 와 코드 공유
- 필요한 패키지 설치
$ yarn add react react-native,$ yarn add -D typescript @types/react @types/react-native rimraf - package.json 생성:
$ yarn init -y
{ "name": "@cosmos/common", "version": "0.0.1", "main": "dist/index.js", "license": "MIT", "scripts": { "postinstall": "npm run build", "build": "rimraf dist && tsc", "watch": "tsc --watch" }, "dependencies": { "react": "^16.12.0", "react-native": "^0.61.5" }, "devDependencies": { "@types/react": "^16.9.19", "@types/react-native": "^0.61.15", "rimraf": "^3.0.2", "typescript": "^3.7.5" } }- tsconfig.json 생성:
$ tsc --init
{ "extends": "../../tsconfig.base.json", "compilerOptions": { "composite": true, "declaration": true, // "emitDeclarationOnly": true, "isolatedModules": false, "module": "commonjs", "outDir": "dist", "rootDir": "src", "experimentalDecorators": true, "jsx": "react", "typeRoots": ["@types", "../../node_modules/@types"] }, "include": ["src/**/*"], "exclude": ["node_modules"] } - 필요한 패키지 설치
-
React Native Web 프로젝트 생성
- CRA 로 React Project 생성
$ cd packages && npx create-react-app web - React Native Web 관련 패키지 설치
$ yarn add react-native-web react-art - Typescript 패키지 설치
$ yarn add -D typescript @types/react-native @types/react @types/react-dom - tsconfig.json 설정
$ tsc --init
{ "extends": "../../tsconfig.base.json", "compilerOptions": { "forceConsistentCasingInFileNames": true, "noEmit": true, "typeRoots": ["@types", "../../node_modules/@types"] }, "include": ["src"], "references": [ { "path": "../components" } ] }- package.json 에 common 패키지 추가
{ "dependencies": { ... "@cosmos/common": "0.0.1", ... } }- src 폴더 재설치
$ rm -rf src,packages/web/src/index.tsx파일 생성
import { AppRegistry } from "react-native"; import { App } from "@cosmos/common"; AppRegistry.registerComponent("cosmos", () => App); AppRegistry.runApplication("cosmos", { rootTag: document.getElementById("root") });
-
$ yarn start실행하면 웹화면을 확인할 수 있음
- CRA 로 React Project 생성
-
Mobx 로 state 관리
React Hook 을 이용하기 위해 mobx-react-lite 를 설치합니다.
- mobx, mobx-react-lite 패키지 설치
$ yarn add mobx mobx-react-lite - useContext 와 mobx-react-lite 를 연동하여 store 관리
- experimentalDecorators 적용을 위한 설정
- observable, observer, action 연동
- mobx, mobx-react-lite 패키지 설치
-
React Navigation 추가
- Bottom Tab Navigation 연동
- Stack Navigation 연동
-
API 연동
-
UI Template 제작

