我们有一个在React中开发的前端应用程序。 现在,我们还想制作一个本机应用程序,但是要尽可能多地从当前应用程序中重用。
我已经看到,在这些情况下,经常使用react-native-web,但是,我们已经开发了仅带有react的应用,而将所有当前组件替换为react-native-web组件将花费太多时间(因为我们正在使用antd组件库)。
我的想法是将所有渲染方法移至另一个npm包(以及其他一些需要重写才能使用react-native的部分),然后从主包中导入它们。
我想象这样的文件夹结构:
通过这种方式,Web和本机软件包将分别具有其npm启动和构建脚本。 如何在核心程序包中并基于平台(在这种情况下为Web或本机)基于正确的程序包导入渲染部分?
我认为我可以使用lerna库来分离包和commonjs或requirejs之类的东西,然后动态导入正确的render元素。
您能推荐一些其他有用的工具吗? 还是整个方法都是错误的,还有另一种方法可以实现?
换句话说,我们如何实现从Web程序包到核心程序包的依赖注入?
想象一下,我们在核心包中有一个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
}
..
}
答案 0 :(得分:0)
发布的程序包应该按照常规方式构建到ES5,可以选择通过ES6导出和导入(ESM构建)来在模块化环境中更有效地使用它。
ES6的进出口是静态的。它们至少在构建工具中没有模块篡改的情况下无法交换。动态import()
是a proposal,而不是ES6的一部分。这将防止有效的摇树,这将导致web
和native
都包含在捆绑包中,即使其中一个未使用也是如此。
DI的某些变体应用于使core
渲染器不可知。
其中一种方法是允许core
中使用某种插件系统:
import { configureRenderer } from '@foo/core';
import * as renderers from '@foo/web';
configureRenderer(renderers);
这在某些情况下可能会起作用,但是对于组件来说效果不佳,因为这会阻止renderers
摇晃树并限制core
使用native
或在这种情况下,网络. This results in
网络package bundled entirely, even if only small portion is used. The restriction to
本机or web
可能会起作用,因为平台是互斥的,但通常这不是一个好的设计解决方案。
一个更好的方法是以相反的方式来实现。 core
没有依赖关系,包含通用抽象,而web
和native
是具体的实现。这可以通过使用具有类组件的OOP继承来解决,并且有很多方法可以用功能方法来实现DI,适合这种情况的一种方法是render prop(因此得名):
// @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
});