현재 진행하고 있는 프로젝트에서 CRA + ReactNative Monorepo 초기세팅 작업을 진행했던 경험을 바탕으로 개발환경을 구축하는 방법을 공유하고자 작성하는 글입니다.
관련된 자료가 많이 없어서 방법을 찾고 에러를 해결하는 과정에 많은 소요가 들었기에 이 과정을 공유해서 많은 분들이 참고해서 더 빠르고 편하게 환경설정을 돕고자 작성하는 글입니다.
버전 및 목적별로 조금씩 설정하는 방법이 다르기에 제가 사용한 방법이 최적의 효율을 내는 방법이 아닐수도 있고, 사용하는 패키지들의 버전이 바뀌면 조금씩 상이한 부분이 존재해서 수정해야 하는 부분이 존재할 수 있습니다.
mkdir <project-name>
cd <project-name>
yarn init -y -p
npx lerna init
[lerna.json]
{
"packages": ["packages/*"],
"npmClient": "yarn",
"useWorkspaces": "true",
"version": "0.0.0"
}
[package.json]
{
"name": "<Project-name>",
"version": "1.0.0",
"main": "index.js",
"repository": "<Repository-url>",
"private": true,
"devDependencies": {
"lerna": "^3.22.1"
},
"workspaces": {
"packages": ["packages/*"]
}
}
touch .gitignore
[.gitignore]
.DS_Store
node_modules/
yarn-error.log
cd packages
npx react-native init <rn-project-name> --template react-native-template-typescript
cd <rn-project-name>
rm yarn.lock && rm -rf node_modules && rm -rf .git
{
"name": <project-name>,
"version": "1.0.0",
"main": "index.js",
"repository": <your-repository-url>,
"private": true,
"devDependencies": {
"lerna": "^3.22.1"
},
"workspaces": {
"packages": [
"packages/*"
],
"nohoist": [
"**/<rn-project-name>",
"**/<rn-project-name>/**"
]
}
const path = require("path");
module.exports = {
projectRoot: path.resolve(__dirname, "../../"),
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: false,
},
}),
},
};
(in Root directory) open packages/<rn-project-name>/ios/<rn-project-name>.xcodeproj/
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"packages/<rn-project-name>/index" fallbackResource:nil];
#else
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}
export NODE_BINARY=node
export EXTRA_PACKAGER_ARGS="--entry-file packages/<rn-project-name>/index.js --reset-cache"
../node_modules/react-native/scripts/react-native-xcode.sh
(in project root directory)yarn workspace <rn-project-name> ios
@Override
protected String getJSMainModuleName() {
return "packages/<rn-project-name>/index";
}
packages/<rn-project-name>/android/디렉토리에도 존재하고, packages/<rn-project-name>/android/app/디렉토리에도 존재하기에 두 파일을 헷갈리지 않도록 주의하시길 바랍니다.project.ext.react = [
(enableHermes: false), // clean and rebuild if changing
(cliPath: "../../node_modules/react-native/local-cli/cli.js"),
(entryFile: "packages/<rn-project-name>/index.js"),
];
(in project root directory)yarn workspace <rn-project-name> android
adb kill-server
adb start-server
스크립트를 실행 후 다시 yarn workspace <rn-project-name> android스크립트를 실행해보기 바랍니다.
cd packages
npx create-react-app web --template typescript
cd web
rm yarn.lock && rm -rf .git
(in Root Packages) yarn lerna clean && yarn install
yarn workspace <cra-project-name> start를 했을때 정상적으로 로컬호스트에 cra프로젝트가 실행되면 성공입니다.
yarn workspace <cra-project-name> start 실행한 후 dependecy 버전 오류메세지가 출력된다면 해당하는 버전의 패키지를 개별적으로 cra project에 추가해주면 됩니다.yarn workspace <project-name> add <package-name> 스크립트를 실행하면 됩니다.yarn workspace <cra-project-name> add bable-jest eslint -D 스크립트를 통해서 추가할 수 있습니다.yarn workspace <project-name> add <package-name>{
"name": "@mono/lib",
"version": "1.0.0",
"main": "index.js",
"repository": "<Repository-url>",
"private": true,
}
yarn workspace <your-project-name> add @mono/lib@1.0.0 기본적으로 yarn workspace를 사용 시 yarn workspace
예를 들어 web이란 프로젝트에 build라는 스크립트가 설정되어 있고, 그걸 root directory에서 실행하고 싶다면 yarn workspace web build를 터미널에서 실행시키면 됩니다.
처음에 lerna를 설치했었습니다. lerna에서 제공하는 여러가지 모노레포를 관리하기 위한 기능들이 있는데 그 중에서 저는 주로 lerna clean 이라는 스크립트만 사용하고 있습니다.
yarn lerna clean 스크립트를 실행하면 packages/ 디렉토리 하위의 모든 프로젝트들의 node_modules를 일괄적으로 삭제할 수 있습니다.
root directory에서 yarn install 스크립트를 실행하면 하위의 모든 프로젝트들의 dependecy들이 설치됩니다.
dependecy들이 꼬였거나, 기타 이유로 인해 node_modules를 삭제 후 재설치해야 할 필요가 있다고 판단되면 yarn lerna clean && yarn install을 통해서 실행할 수 있습니다.
또한 저의 경우에는 매번 yarn workspace를 치는 것이 번거로워서 alias적인 개념으로 root pakcage.json에 script를 추가해놨습니다.
{
"name": <your-project-name>,
"version": "1.0.0",
"main": "index.js",
"repository": <your-repostiory-url>
"private": true,
"devDependencies": {
"lerna": "^3.22.1"
},
"workspaces": {
"packages": [
"packages/*"
],
"nohoist": [
"**/<rn-project-name>",
"**/<rn-project-name>/**"
]
},
"scripts": {
"web": "yarn workspace web",
"mobile": "yarn workspace mobile",
"server": "yarn workspace server",
"lib": "yarn workspace @mono/lib",
"theme": "yarn workspace @mono/theme"
}
}
👍