У нас есть интерфейсное приложение, разработанное на React. Теперь мы также хотели бы создать приложение, ориентированное на реакцию, но с максимально возможным повторным использованием из текущего приложения.
Я видел, что в этих случаях часто используется response-native-web, однако мы уже разработали наше приложение, просто реагируя, и замена всех наших текущих компонентов на компоненты react-native-web займет слишком много времени (также потому, что мы используя библиотеку компонентов antd).
Моя идея состояла в том, чтобы переместить все методы рендеринга в другой пакет npm (и некоторые другие части, которые потребуют переписывания для использования response-native) и импортировать их из основного пакета.
Я представляю себе структуру папок примерно так:
Таким образом, веб-пакеты и собственные пакеты будут иметь свои сценарии запуска и сборки npm. Как я могу в основном пакете и в зависимости от платформы (в данном случае веб или нативной) импортировать часть рендеринга из правильного пакета?
Я думал, что могу использовать библиотеку lerna для разделения пакетов и что-то вроде commonjs или requirejs, чтобы затем динамически импортировать правильный элемент рендеринга.
Можете ли вы порекомендовать другие инструменты, которые могут быть полезны? Или весь подход неверен и есть другой способ добиться этого?
Другими словами, как мы можем добиться внедрения зависимостей из веб-пакета в основной пакет?
Представьте, у нас есть компонент Home в базовом пакете:
class Home extends Component {
..
render() {
// somehow import required 'view'
// example: import('path_to_web_package_from_some_global_variable' + '/HomeRender.js');
// There would be a HomeRender.js in 'web' package and another one in 'native' package
}
..
}
@estus Что вы имеете в виду, говоря о неиспользуемой платформе? Я хочу импортировать только код, специфичный для «Интернета» или «нативного». Я добавил небольшой пример того, как это может выглядеть
Почему бы просто не переместить компоненты в папку, доступную для обоих web/native, и импортировать их из них?
import() является асинхронным, и он заставляет компонент быть асинхронным, что не очень хорошо. Постараюсь дать ответ, исходя из моего понимания того, как выглядят ваши пакеты.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Предполагается, что опубликованный пакет будет построен для ES5 традиционным способом, опционально с использованием экспорта и импорта ES6 (сборка ESM) для более эффективного использования в модульных средах.
Импорт и экспорт ES6 статичны. Их нельзя поменять местами, по крайней мере, без изменения модуля в инструменте сборки. В то время как динамический import() - это предложение, а не часть ES6. Это предотвратило бы эффективное встряхивание дерева, это привело бы к включению как web, так и native в комплект, даже если один из них не используется.
Чтобы сделать core независимым от рендерера, следует использовать некоторые вариации DI.
Один из способов - разрешить какую-то систему плагинов в core:
import { configureRenderer } from '@foo/core';
import * as renderers from '@foo/web';
configureRenderer(renderers);
Это может работать в некоторых случаях, но это не очень хорошо работает с компонентами, потому что это предотвращает раскачку дерева renderers и ограничивает использование core. В этом случае может работать native или web. This results inwebpackage bundled entirely, even if only small portion is used. The restriction tonativeor web, поскольку платформы являются взаимоисключающими, но это не так. В целом не удачное дизайнерское решение.
Лучше всего реализовать это наоборот. core не имеет зависимостей и содержит общие абстракции, в то время как web и native являются конкретными реализациями. Это может быть решено с помощью наследования ООП с компонентами класса, и есть много возможностей реализовать DI с функциональным подходом, тот, который подходит для этого случая, - визуализировать опору (отсюда и название):
// @foo/core
export class Home extends Component {
...
render() {
const {render, ...props} = this.props;
return render(props);
}
}
// @foo/web
import { Home as HomeWithoutRenderer } from '@foo/core';
const rendererHOC = (Comp, renderer) => props => <Comp render = {renderer} ...props />;
export const Home = rendererHOC(HomeWithoutRenderer, props => {
// platform-specific view
});
Спасибо! Это действительно очень помогает :) Теперь он работает, единственное, что нужно было изменить, это новый экспорт Home: вместо 'export const Home = rendererHoc (..)' должен быть 'export const Home = () => rendererHoc ( ..) '
Рад, что это сработало. Произошла опечатка, rendererHOC был задуман как HOC, поэтому ему можно было передать другие реквизиты. Я его обновил.
core, а не наоборот. Рассмотрите возможность предоставления краткого примера, что это за пакеты и как они работают вместе.