현재 진행하고 있는 프로젝트에서 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"
}
}
👍