정보실

웹학교

정보실

javascript 웹과 React Native간에 TypeScript 코드 공유

본문

기존 웹 앱으로 하이브리드 모바일 앱을 구축하고 있습니다. 프론트 엔드에는 웹뷰가 없어지고 React Native에서 기기에서 실행되도록 백엔드를 조정합니다.


원본 : https://spin.atomicobject.com/2019/09/24/typescript-web-react-native/


우리가 겪은 문제 중 하나는 webpack으로 구축 된 기존 monorepoMetro와 번들로 제공되는 새로운 React Native 앱간에 코드를 공유하는 방법이었습니다.


모두 TypeScript이지만 이것은 간단하지 않았습니다. 이 게시물에서는 처리 방법을 설명하겠습니다.


계획 A 


기존 웹앱 web-monorepo와 새로운 React Native 앱을 offline-rn-app라고 불러 봅시다.


우리는 처음에 소스를 직접 참조하려고 시도하여 offline-rn-app에서 "web-monorepo/bar";에서 {foo}를 가져올 수 있습니다. 우리는 이 접근법에 많은 마찰을 겪었습니다. 예를 들면 다음과 같습니다.

  • React Native는 이제 기본적으로 TypeScript를 지원하지만 (993), Babel의 내장 TypeScript 처리를 사용하는데 알려진 제한이 있으며 기존 코드에서 일부 패턴을 처리 할 수 ​​없습니다 (😩).
  • 애플리케이션 코드는 특수 로더가 있는 .graphql 또는 .yml 파일 필요 및 require.context로 파일의 전체 디렉토리 가져 오기와 같은 소수의 웹팩 특정 기능을 사용합니다.

충분한 시간과 연구를 통해 이러한 문제를 해결할 수 있을지 모르지만 상류에서 수영하는 것처럼 느껴졌습니다. 우리는 웹팩 구성의 특정 문제로 어려움을 겪으면서“웹팩이 그 일을 하지 못하게 하고 출력을 소비하는 이유는 무엇입니까?”라고 생각했습니다.


계획 B 


웹 모노 레포 프로젝트에는 이미 두 개의 웹팩 진입점이 있었습니다. 하나는 React 프론트 엔드 용이고 다른 하나는 Express 백엔드 용입니다. 우리의 아이디어는 React Native 앱에서 사용할 수 있는 라이브러리를 생성하는 세 번째를 추가하는 것입니다.


이런 식으로 실제 TypeScript 컴파일러와 모든 웹팩 로더를 얻을 수 있으며 많은 데드 코드가 흔들릴 수 있습니다.


스포일러 : 효과가 있었습니다.


세부 


설정 한 구성의 중요한 부분은 다음과 같습니다.


package.json 


기존 Node 프로젝트에서 설치 가능한 라이브러리를 구축하기 위한 첫 번째 단계는 package.json에 몇 가지 추가 사항을 추가하는 것입니다.


// package.json "main": "lib/index.js", "types": "lib/entry/mobile-server.d.ts", "files": [ "lib/*" ], "scripts": { "build:library": "webpack --config ./webpack/library.config.js" } 


"main"및 "types"필드는 패키지 설치시 소비 앱에서 사용됩니다. “파일”글로브는 라이브러리를 설치할 때 소비하는 앱을 지정합니다. 마지막으로,“build : library”편의 스크립트는 새로운 웹팩 설정으로 이어집니다.


웹팩 및 tsconfig 


배포 할 파일을 선언했으면 빌드 할 차례입니다. 새로운 웹팩 구성은 다음과 같습니다.


// webpack/library.config.js const path = require("path"); module.exports = { mode: "development", entry: { "mobile-server": "./entry/mobile-server.ts" }, devtool: "source-map", output: { path: path.resolve(__dirname, "../lib"), filename: "index.js", library: "my-lib", libraryTarget: "umd" }, module: { rules: [ { test: /\.tsx?$/, use: [ { loader: "ts-loader", options: { configFile: "tsconfig.library.json" } } ] } ] }, resolve: { extensions: [".ts", ".tsx", ".js"], modules: [path.resolve(__dirname, "../modules"), "node_modules"] }, externals: ["cheerio", "config"] }; 


entry / mobile-server.ts의 입력으로부터 package.json의 메인이 기대하는 lib / index.js와 소스 맵이 생성됩니다.


대부분의 타사 코드가 번들로 제공되는 반면 소비 앱이 제공 할 패키지의 외부 코드를 추가 할 수 있습니다. (나중에 더 자세히 설명합니다.)


또한 사용자 정의 tsconfig를 제공했습니다.


// tsconfig.library.json { "extends": "./tsconfig", "compilerOptions": { "module": "es6", "target": "es5", "allowJs": false, "noEmit": false, "declaration": true, "declarationMap": true, "lib": [], "outDir": "lib", "resolveJsonModule": true }, "include": ["entry/mobile-server.ts"], "exclude": ["node_modules", "dist", "lib"] } 


비어있는 lib 목록을 제외하고는 브라우저 DOM 또는 Node.js 파일 시스템 액세스와 같은 React Native에서 사용할 수 없는 API를 사용하여 라이브러리 빌드를 실수로 막는 것을 제외하고는 여기서 흥미로운 점이 없습니다.


이것들을 가지고, lib/를 생성하기 위해 build : library를 실을 수 있습니다.


포장 


새 라이브러리를 패키지 리포지토리에 게시 할 계획이 없으므로 파일 경로 또는 GitHub 리포지토리와 같이 추가 할 수 있는 다른 패턴 중 하나를 통해 라이브러리를 참조해야 합니다. 


약간의 실험 후, 우리는 실 팩으로 타르볼을 생산하기로 결정했습니다. 이를 통해 CircleCI 워크 플로우에서 작업 간에 공유 할 수 있는 멋진 단일 아티팩트가 있습니다.


Consuming the library 


offline-rn-app에서 다음과 같이 tarball을 참조합니다.


// package.json "my-lib": "../web-monorepo/my-lib-1.0.0.tgz" 


React Native 측에서는 다른 타사 라이브러리를 사용하는 것과 같은 느낌이 듭니다.


위의 웹팩 구성에 지정된 "외부"를 기억하십니까? 우리가 공유하는 일부 코드는 React Native와 호환되지 않는 라이브러리에 따라 다릅니다. 우리는 결국 그것들로부터 벗어날 수도 있지만, 지금은 괜찮은 해결책이 있습니다.


라이브러리 측에서는 문제가 있는 모듈을 외부화 하여 소비 앱이 처리하도록 합니다.


React Native 앱에서는 대체 구현으로 교체하여 처리합니다. 이를 위해 babel-plugin-module-resolver를 추가하여 모듈의 별칭을 임의로 지정할 수 있습니다.


// babel.config.js module.exports = { presets: [ "module:metro-react-native-babel-preset", "@babel/preset-typescript" ], plugins: [ [ require.resolve("babel-plugin-module-resolver"), { alias: { cheerio: "react-native-cheerio", config: "./src/mobile-config.ts" } } ] ] }; 


그리고 짜잔! React Native에서 실행되는 Express 서버의 코드가 있습니다.


향후 개선 : 편집자 경험 


장래에 매끄럽게 만들고자 하는 하나의 거친 패치는 monorepo에서 작업 할 때의 에디터 경험입니다. VS 코드는 tsconfig 중 하나만 알고 있습니다. 따라서 foo.ts를 편집 할 때 빌드 대상 중 하나에 따라 오류가 발생하지만 다음에 명령 줄에서 다른 대상을 컴파일 할 때까지 표시되지 않는 오류가 발생할 수 있습니다.


플랜 B로 전환하면서 또 다른 단점은 더 이상 오프라인 애플리케이션의 소스에서 웹 모노 레포로 F12를 할 수 없다는 것입니다. 대신 경계를 넘어 정의로 이동하면 라이브러리의 유형 정의에 도달하게 됩니다. 이것으로 소스 맵을 향상 시킬 수 있습니까?


결론 


우리의 솔루션에는 몇 가지 타협과 상당한 복잡성이 포함되어 있지만 전반적으로 이 접근법은 잘 작동합니다.



  • 트위터로 보내기
  • 페이스북으로 보내기
  • 구글플러스로 보내기
  • 카카오톡으로 보내기

페이지 정보

조회 28회 ]  작성일19-10-02 11:58

웹학교