Повторное использование кода в Node, Web и Mobile
В этом руководстве я покажу вам, как настроить монорепозиторий JavaScript с api (Express), веб-приложением (React), мобильным приложением (React Native) и общей папкой для повторно используемого кода. Но сначала…
Краткое введение
Я разработчик программного обеспечения и большую часть времени трачу на создание REST API и приложений React. Мое путешествие с монорепозиториями началось сначала как любопытство. А потом все стало еще серьезнее, когда несколько месяцев назад я начал создавать собственное приложение. Когда я начал создавать это приложение, у меня были некоторые основные принципы, которым я хотел следовать как можно больше:
- Используйте JavaScript для всего стека
- Избегайте дублирования бизнес-логики между серверной частью и интерфейсом
- Простая установка и обслуживание
Основными частями стека были: сервер API (GraphQL / Node), веб-приложение (React) и мобильное приложение (React Native).
Основное внимание в этой статье уделяется второму пункту выше. Наличие всего стека как монорепозитория позволило мне обмениваться кодом между моим сервером api, веб-приложением и собственным приложением. Далее следует несколько открытий, которые я сделал на этом пути, и то, как я создал свой проект. Я надеюсь, тебе это нравится.
Метод проб и ошибок
В своем стремлении к настройке монорепозитория я попробовал несколько методов и инструментов, в том числе:
- Лерна
- Webpack (с использованием псевдонима и параметров разрешения)
- Алльный метод.
- Рабочие места пряжи
У всех есть свои плюсы и минусы. Такие инструменты, как Lerna, создают символические ссылки для соединения папок в монорепозитории, и это было одной из проблем при запуске собственного приложения. В конце концов, я решил проблему символических ссылок с помощью Haul. Но опять же, было так больно склеивать все вместе. Симулятор часто выдавал мне ошибки о рассинхронизации пакета JavaScript и других проблемах. И я был не в восторге от того, что тратил столько времени на настройку, а не на разработку.
Webpack также был вариантом. Я настроил конфигурацию, которая позволила мне импортировать модули из корневой папки монорепозитория. Но это заставило меня везде использовать webpack, и это казалось ненужным.
По поводу метода Алле. Я не мог заставить его работать с React Native.
Затем, в счастливый день, я услышал о рабочих пространствах Yarn, а затем я нашел этот отличный учебник от Дарио Хавьера Краверо о том, как использовать рабочие пространства Yarn с приложением React и приложением React Native. То, что он описывает в статье, было самым быстрым, простым и надежным методом, который я нашел до сих пор, чтобы получить монорепозиторий, который работает для React и React Native.
Обсуждение дешево. Покажи мне код.
Линус Торвальдс
Давай перейдем к делу. В этом руководстве мы создадим следующую структуру папок:
/jsrepo /api /native /shared /web
Общая папка будет содержать код, который можно повторно использовать в серверной части и во внешнем интерфейсе (веб / собственный). Эта папка может содержать такие вещи, как константы, вспомогательные функции и бизнес-логику.
Для других папок мы создадим очень простые приложения, чтобы продемонстрировать, что вся установка работает.
Предварительные условия
Я предполагаю, что у вас есть:
- установлена последняя версия Node JS
- Пакеты NPM установлены глобально: create-react-app и create-react-native-app
Фундамент
Создадим основной проект. Я назову его jsrepo
и положу в свою домашнюю папку ~/jsrepo
. Измените имя и местоположение по своему желанию.
mkdir jsrepo cd jsrepo npm init
Все следующие команды cli взяты из ~/jsrepo
Общий пакет
1. Создайте общую папку.
mkdir shared cd shared npm init
2. Давайте добавим контент в общую папку.
touch index.js mkdir packages cd packages touch colors.js
3. Добавить в ~/jsrepo/shared/packages/colors.js
const GREEN = '#24ad34'; module.exports = { GREEN };
4. И в ~/jsrepo/shared/index.js
const Colors = require('./packages/colors'); module.exports = { Colors };
Убедитесь, что основное поле package.json
файла общей папки указывает на ~/jsrepo/shared/index.js
. Это очень важно для правильной работы.
API
Теперь давайте создадим простой экспресс-сервер для использования нашего общего пакета.
1. Создайте папку api
cd ~/jsrepo mkdir api cd api npm init
2. Добавьте общую папку и выразите как зависимость
npm install ../shared express --save
Зависимости в файле package.json для api будут следующими:
"dependencies": { "express": "^4.16.3", "shared": "file:../shared" }
3. Давайте создадим простой экспресс-сервер и воспользуемся общим пакетом.
touch server.js
4. Вставьте это в файл ~/jsrepo/api/server.js
:
const express = require('express'); const { Colors } = require('shared'); const app = express(); app.get( '/', (req, res) => res.send(`Colors: ${JSON.stringify(Colors)}`) ); app.listen(3001, () => console.log('App listening on port 3001!'));
5. Запустите сервер api npm run start
и перейдите по адресу http: // localhost: 3001. Вы увидите это:
Интернет
- Давайте воспользуемся приложением create-react-app, чтобы создать простое веб-приложение.
cd ~/jsrepo create-react-app web cd web rm -r node_modules
2. Добавьте общую папку.
npm install ../shared --save
3. Импортируйте общий код в App.js
import React, { Component } from 'react'; import logo from './logo.svg'; import './App.css'; // 1. add this line import { Colors } from 'shared'; class App extends Component { render() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <h1 className="App-title">Welcome to React</h1> </header> <p className="App-intro"> To get started, edit <code>src/App.js</code> and save to reload. </p> {/* 2. add the following line */} <p>Colors are {JSON.stringify(Colors)}</p> </div> ); } } export default App;
4. Установите зависимости с npm install
5. Запустите приложение с npm run start
и перейдите по адресу http: // localhost: 3000. Вы должны увидеть это:
Родной
- Давайте использовать
create-react-native-app
для создания нового проекта
cd ~/jsrepo
create-react-native-app native
2. Установите общий пакет.
npm install ../shared --save
3. Измените App.js
, чтобы использовать общий пакет.
import React from 'react'; import { StyleSheet, Text, View } from 'react-native'; // 1. add this import { Colors } from 'shared'; export default class App extends React.Component { render() { return ( <View style={styles.container}> <Text>Open up App.js to start working on your app!</Text> <Text>Changes you make will automatically reload.</Text> <Text>Shake your phone to open the developer menu.</Text> {/* 2. Add this line */} <Text>{JSON.stringify(Colors)}</Text> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, });
4. Установите зависимости:
npm install
5. Запустите приложение с помощью Expo или другого понравившегося вам инструмента. Если вы используете Expo, перейдите в Expo IDE и откройте проект. Убедитесь, что ваш компьютер и мобильный телефон находятся в одной сети Wi-Fi.
6. Вы должны это увидеть
И это все. У нас есть монорепозиторий с API, веб-проект и собственный проект, которые могут повторно использовать код из общей папки.
Что, скорее всего, произойдет, если вы пойдете по этому пути:
- Одна из проблем, которые я обнаружил до сих пор, и я не могу это подчеркнуть, - это проблема смешивания модулей ES6 и модулей Commons JS. Как вы заметили, общая папка использует только Commons JS, и это потому, что мы хотим повторно использовать общие пакеты в api, который работает на Node. А Node по умолчанию не поддерживает модули ES6. Итак, если вы попытаетесь использовать модули ES6 в общей папке, вам придется проделать дополнительную работу. Вероятно, вы могли бы транспилировать общий код и экспортировать его в разные системы модулей, тогда Node и веб-приложение смогут его использовать.
- Несколько раз, работая с общей папкой, мне приходилось использовать стороннюю библиотеку, и, как всегда, я сделал:
const lib = require('some-lib')
. Но ничего не вышло. Пока не пойму, что в некоторых случаях приходилось делатьconst lib = require('some-lib').default
. Просто хорошо иметь в виду. - Работа с модулями Commons JS и ES6 в монорепозитории была настоящим кошмаром. В какой-то момент я решил везде использовать только Commons JS. Я имею в виду везде. Это была большая работа, но она разрешила множество конфликтов, когда модули не разрешались и не импортировались должным образом. Если вы хотите прервать описанную выше настройку, просто замените любой экспорт в общей папке с Commons JS на модули ES6.
Следующая часть
- Повторное использование компонентов React между веб-платформами и нативными платформами
Подпишитесь на мою рассылку!
Если вам понравился этот контент, подпишитесь на мою ежемесячную новостную рассылку. Я пишу о
Developer Experience (DX), Frontend-разработке и архитектуре программного обеспечения. Обещаю, без спама. И вы можете отказаться от подписки в любой момент. Зарегистрируйтесь на rafaelrozon.com.
Ресурсы
- Как использовать рабочие области пряжи с Create React App и Create React Native App (Expo) для совместного использования общего кода
- Настройка монорепозитория JavaScript
- Создание крупномасштабных приложений на реакцию в монорепозитории
- Кроссплатформенное приложение с React в монорепозитории
- Рабочие места для пряжи
Спасибо и удачного взлома!