Skip to content

Commit

Permalink
feat: runtime plugin to mound multi react version app
Browse files Browse the repository at this point in the history
  • Loading branch information
ScriptedAlchemy committed Apr 22, 2024
1 parent a9a812d commit f4c2146
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 171 deletions.
22 changes: 12 additions & 10 deletions different-react-versions-16-17/app1/fallback.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import React from 'react';
class Component extends React.Component {
render() {
const { hostV, remoteV, containerRef } = this.props;
console.log({ hostV, remoteV });
return (
<div>
<p style={{ color: 'red' }}>
Expand All @@ -17,17 +16,17 @@ class Component extends React.Component {
}

// This is the higher-order component that takes the Original component and additional props
const withVersions = (Original, hostVersion, remoteVersion,remoteReactVersion) => {
const ReactDOM = remoteReactVersion();
console.log(ReactDOM)
const withVersions = (Original, remoteVersion, hostVersion,remoteReactDOMVersion, remoteReactVersion) => {
const ReactDOM = remoteReactDOMVersion();
const React = remoteReactVersion();
class WrappedComponent extends React.Component {
constructor(props) {
super(props);
this.containerRef = React.createRef();
}

componentDidMount() {
this.mountOriginalComponent();
this.mountOriginalComponent(true);
}

componentDidUpdate() {
Expand All @@ -40,18 +39,21 @@ const withVersions = (Original, hostVersion, remoteVersion,remoteReactVersion) =
}
}

mountOriginalComponent() {
const element = <Original {...this.props} />;
ReactDOM.render(element, this.containerRef.current);
mountOriginalComponent(shouldRender) {
const element = React.createElement(Original, this.props);
const fGunc = shouldRender ? ReactDOM.render : ReactDOM.hydrate
fGunc(element, this.containerRef.current);
}

render() {
console.log(Original, hostVersion, remoteVersion, remoteReactVersion);
return <Component hostV={hostVersion} remoteV={remoteVersion} containerRef={this.containerRef} />;
}
}

return <WrappedComponent/>;


return (props) => <WrappedComponent {...props}/>

};

export default withVersions;
69 changes: 45 additions & 24 deletions different-react-versions-16-17/app1/react-adapter-runtime-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,59 +3,80 @@ const runtimePlugin = function () {
return {
name: 'my-runtime-plugin',
beforeInit(args) {
console.log('beforeInit: ', args);
return args;
},
init(args) {
console.log('init: ', args);
return args;
},
loadRemote(args) {
console.log('beforeRequest: ', args);
return args;
},
afterResolve(args) {
console.log('afterResolve', args);

const hostVersion = args.options.shared.react[0].version;
const remoteInstance = __FEDERATION__.__INSTANCES__.find(instance=>{
return instance.name === args.pkgNameOrAlias
})
const remoteVersion = remoteInstance ? remoteInstance.options.shared.react[0].version : false

if(remoteVersion && hostVersion && remoteVersion !== hostVersion) {
console.log(remoteVersion, hostVersion)
}

return args;
},
// resolveShare(args) {
// const { shareScopeMap, scope, pkgName, version, GlobalFederation } = args;
//
// console.log('resolveShare:', args);
// if (pkgName !== 'react') {
// return args;
// }
//
// return args
//
// // set lib
// args.resolver = function () {
// shareScopeMap[scope][pkgName][version] = {
// lib: ()=>window.React,
// loaded:true,
// loading: Promise.resolve(()=>window.React)
// }; // Manually replace the local share scope with the desired module
// return shareScopeMap[scope][pkgName][version];
// };
//
// // set get
// args.resolver = function () {
// shareScopeMap[scope][pkgName][version] = {
// get: async ()=>()=>window.React,
// }; // Manually replace the local share scope with the desired module
// return shareScopeMap[scope][pkgName][version];
// };
// return args;
// },
async onLoad(args) {
console.log('onLoad: ', args);
// console.log('onLoad: ', args);
const hostVersion = args.origin.options.shared['react-dom'][0].version;
const remoteInstance = __FEDERATION__.__INSTANCES__.find(instance=>{
return instance.name === args.pkgNameOrAlias
})
const remoteVersion = remoteInstance ? remoteInstance.options.shared['react-dom'][0].version : false
const res = (await import('./fallback.js')).default

if(remoteVersion && hostVersion && remoteVersion !== hostVersion) {
const remoteReactVersion = await args.origin.loadShare('react-dom', {
const remoteReactDOMVersion = await remoteInstance.loadShare('react-dom', {
resolver: (sharedOptions) => {
console.log('sharedOptions',sharedOptions)
return (
sharedOptions.find((i) => i.version === remoteVersion) ?? sharedOptions[0]
);
},
})
return ()=>()=>res(args.exposeModuleFactory().default, remoteVersion, hostVersion,remoteReactVersion)


const remoteReactVersion = await remoteInstance.loadShare('react', {
resolver: (sharedOptions) => {
return (
sharedOptions.find((i) => i.version === remoteVersion) ?? sharedOptions[0]
);
},
})
const res = (await import('./fallback.js')).default

return ()=>(props)=>{
return res(args.exposeModuleFactory().default, remoteVersion, hostVersion,remoteReactDOMVersion,remoteReactVersion)(props)
}
}
return args
},
async loadShare(args) {
console.log('loadShare:', args);
},
async beforeLoadShare(args) {
console.log('beforeloadShare:', args);
return args;
},
};
Expand Down
26 changes: 14 additions & 12 deletions different-react-versions-16-17/app1/src/components/App.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React from 'react';
import ReactAdapterConsumer from './ReactAdapterConsumer';
console.log('RESOLVE', import('app2/Button'))
const ModernComponent = React.lazy(() => import("app2/ModernComponent"));

const RemoteButton = React.lazy(() => import('app2/Button'));

// const ModernComponent = React.lazy(() => import("app2/ModernComponent"));
// Hooks not suppoorted, uncomment to verify this is a pre-hooks react version being used.
// import HookComponent from './ComponentWithHook'

Expand All @@ -26,15 +25,18 @@ class App extends React.Component {
<h2>App 1, Uses react version not compatible with hooks</h2>
<input onChange={this.setValue} placeholder="Type something into this input" />

{/*<div style={{ border: '1px red solid', padding: '10px', margin: '20px 0' }}>*/}
{/* <ReactAdapterConsumer*/}
{/* // any other props, passed to ModernComponent*/}
{/* {...this.state}*/}
{/* importer={() => import('app2/ModernComponent')}*/}
{/* >*/}
{/* <h3>And these are children passed into it from the legacy app</h3>*/}
{/* </ReactAdapterConsumer>*/}
{/*</div>*/}
<div style={{border: '1px red solid', padding: '10px', margin: '20px 0'}}>
<React.Suspense fallback="Loading Modern Com">

<ModernComponent
// any other props, passed to ModernComponent
{...this.state}
>
<h3>And these are children passed into it from the legacy app</h3>
</ModernComponent>
</React.Suspense>

</div>

{/*This will Fail*/}
{/*<HookComponent/>*/}
Expand Down

This file was deleted.

10 changes: 6 additions & 4 deletions different-react-versions-16-17/app1/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ const webpackConfig = {
shared: {
...deps,
'react-dom': {
import: 'react-dom', // the "react" package will be used a provided and fallback module
shareKey: 'react-dom', // under this name the shared module will be placed in the share scope
shareScope: 'legacy', // share scope with this name will be used
singleton: true, // only a single version of the shared module is allowed
strictVersion: true,
// singleton: true, // only a single version of the shared module is allowed
},
'react': {
strictVersion: true,
// singleton: true, // only a single version of the shared module is allowed
},
},
}),
Expand Down
22 changes: 12 additions & 10 deletions different-react-versions-16-17/app2/fallback.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import React from 'react';
class Component extends React.Component {
render() {
const { hostV, remoteV, containerRef } = this.props;
console.log({ hostV, remoteV });
return (
<div>
<p style={{ color: 'red' }}>
Expand All @@ -17,17 +16,17 @@ class Component extends React.Component {
}

// This is the higher-order component that takes the Original component and additional props
const withVersions = (Original, hostVersion, remoteVersion,remoteReactVersion) => {
const ReactDOM = remoteReactVersion();
console.log(ReactDOM)
const withVersions = (Original, remoteVersion, hostVersion,remoteReactDOMVersion, remoteReactVersion) => {
const ReactDOM = remoteReactDOMVersion();
const React = remoteReactVersion();
class WrappedComponent extends React.Component {
constructor(props) {
super(props);
this.containerRef = React.createRef();
}

componentDidMount() {
this.mountOriginalComponent();
this.mountOriginalComponent(true);
}

componentDidUpdate() {
Expand All @@ -40,18 +39,21 @@ const withVersions = (Original, hostVersion, remoteVersion,remoteReactVersion) =
}
}

mountOriginalComponent() {
const element = <Original {...this.props} />;
ReactDOM.render(element, this.containerRef.current);
mountOriginalComponent(shouldRender) {
const element = React.createElement(Original, this.props);
const fGunc = shouldRender ? ReactDOM.render : ReactDOM.hydrate
fGunc(element, this.containerRef.current);
}

render() {
console.log(Original, hostVersion, remoteVersion, remoteReactVersion);
return <Component hostV={hostVersion} remoteV={remoteVersion} containerRef={this.containerRef} />;
}
}

return <WrappedComponent/>;


return (props) => <WrappedComponent {...props}/>

};

export default withVersions;

0 comments on commit f4c2146

Please sign in to comment.