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 21, 2024
1 parent 3d2f4c7 commit 7635dfb
Show file tree
Hide file tree
Showing 14 changed files with 769 additions and 461 deletions.
56 changes: 56 additions & 0 deletions different-react-versions-16-17/app1/fallback.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react';
import ReactDOM from 'react-dom';

class Component extends React.Component {
render() {
const { hostV, remoteV, containerRef } = this.props;
console.log({ hostV, remoteV });
return (
<div>
<p style={{ color: 'red' }}>
In RUNTIME PLUGIN WRAPPER <br />
Host React: {hostV} Remote React: {remoteV}
</p>
<div ref={containerRef}/>
</div>
);
}
}

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

componentDidMount() {
this.mountOriginalComponent();
}

componentDidUpdate() {
this.mountOriginalComponent();
}

componentWillUnmount() {
if (this.containerRef.current) {
ReactDOM.unmountComponentAtNode(this.containerRef.current);
}
}

mountOriginalComponent() {
const element = <Original {...this.props} />;
ReactDOM.render(element, this.containerRef.current);
}

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

return <WrappedComponent/>;
};

export default withVersions;
6 changes: 3 additions & 3 deletions different-react-versions-16-17/app1/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
"webpack": "^5.91.0",
"webpack-cli": "4.10.0",
"webpack-dev-server": "4.15.1",
"@rspack/core": "^0.5.6",
"@rspack/cli": "^0.5.6",
"@rspack/dev-server": "^0.5.6"
"@rspack/core": "^0.6.2",
"@rspack/cli": "^0.6.2",
"@rspack/dev-server": "^0.6.2"
},
"scripts": {
"start": "rspack serve",
Expand Down
1 change: 0 additions & 1 deletion different-react-versions-16-17/app1/public/index.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<html>
<head>
<script src="<%= htmlWebpackPlugin.options.app2RemoteEntry %>"></script>
</head>
<body>
<div id="root"></div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

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;
},
async onLoad(args) {
console.log('onLoad: ', args);
const hostVersion = args.origin.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
const res = (await import('./fallback.js')).default

if(remoteVersion && hostVersion && remoteVersion !== hostVersion) {
return ()=>()=>res(args.exposeModuleFactory().default, remoteVersion, hostVersion)
}
return args
},
async loadShare(args) {
console.log('loadShare:', args);
},
async beforeLoadShare(args) {
console.log('beforeloadShare:', args);
return args;
},
};
};
export default runtimePlugin;
2 changes: 2 additions & 0 deletions different-react-versions-16-17/app1/rspack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const webpackConfig = {
remotes: {
app2: 'app2',
},
runtimePlugins: [require.resolve('./react-adapter-runtime-plugin.ts')],
shared: {
...deps,
'react-dom': {
Expand All @@ -58,6 +59,7 @@ const webpackConfig = {
new HtmlWebpackPlugin({
template: './public/index.html',
app2RemoteEntry: getRemoteEntryUrl(3002),
excludeChunks: ['app1']
}),
],
};
Expand Down
20 changes: 10 additions & 10 deletions different-react-versions-16-17/app1/src/components/App.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import ReactAdapterConsumer from './ReactAdapterConsumer';

console.log('RESOLVE', import('app2/Button'))
const RemoteButton = React.lazy(() => import('app2/Button'));

// const ModernComponent = React.lazy(() => import("app2/ModernComponent"));
Expand All @@ -26,15 +26,15 @@ 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' }}>*/}
{/* <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>*/}

{/*This will Fail*/}
{/*<HookComponent/>*/}
Expand Down
5 changes: 2 additions & 3 deletions different-react-versions-16-17/app1/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ const webpackConfig = {
plugins: [
new ModuleFederationPlugin({
name: 'app1',
library: { type: 'var', name: 'app1' },
remotes: {
app2: 'app2',
app2: `app2@${getRemoteEntryUrl(3002)}`,
},
runtimePlugins: [require.resolve('./react-adapter-runtime-plugin.ts')],
shared: {
...deps,
'react-dom': {
Expand All @@ -56,7 +56,6 @@ const webpackConfig = {
}),
new HtmlWebpackPlugin({
template: './public/index.html',
app2RemoteEntry: getRemoteEntryUrl(3002),
}),
],
};
Expand Down
56 changes: 56 additions & 0 deletions different-react-versions-16-17/app2/fallback.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react';
import ReactDOM from 'react-dom';

class Component extends React.Component {
render() {
const { hostV, remoteV, containerRef } = this.props;
console.log({ hostV, remoteV });
return (
<div>
<p style={{ color: 'red' }}>
In RUNTIME PLUGIN WRAPPER <br />
Host React: {hostV} Remote React: {remoteV}
</p>
<div ref={containerRef}/>
</div>
);
}
}

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

componentDidMount() {
this.mountOriginalComponent();
}

componentDidUpdate() {
this.mountOriginalComponent();
}

componentWillUnmount() {
if (this.containerRef.current) {
ReactDOM.unmountComponentAtNode(this.containerRef.current);
}
}

mountOriginalComponent() {
const element = <Original {...this.props} />;
ReactDOM.render(element, this.containerRef.current);
}

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

return <WrappedComponent/>;
};

export default withVersions;
6 changes: 3 additions & 3 deletions different-react-versions-16-17/app2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
"webpack": "^5.91.0",
"webpack-cli": "4.10.0",
"webpack-dev-server": "4.15.1",
"@rspack/core": "^0.5.6",
"@rspack/cli": "^0.5.6",
"@rspack/dev-server": "^0.5.6"
"@rspack/core": "^0.6.2",
"@rspack/cli": "^0.6.2",
"@rspack/dev-server": "^0.6.2"
},
"scripts": {
"start": "rspack serve",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

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;
},
async onLoad(args) {
console.log('onLoad: ', args);
const hostVersion = args.origin.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
const res = (await import('./fallback.js')).default

if(remoteVersion && hostVersion && remoteVersion !== hostVersion) {
return ()=>()=>res(args.exposeModuleFactory().default, remoteVersion, hostVersion)
}
return args
},
async loadShare(args) {
console.log('loadShare:', args);
},
async beforeLoadShare(args) {
console.log('beforeloadShare:', args);
return args;
},
};
};
export default runtimePlugin;
1 change: 1 addition & 0 deletions different-react-versions-16-17/app2/rspack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ const webpackConfig = {
name: 'app2',
library: { type: 'var', name: 'app2' },
filename: 'remoteEntry.js',
runtimePlugins: [require.resolve('./react-adapter-runtime-plugin.ts')],
exposes: {
'./Button': './src/components/Button',
'./ModernComponent': './src/components/ModernReactComponent',
Expand Down
1 change: 1 addition & 0 deletions different-react-versions-16-17/app2/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const webpackConfig = {
name: 'app2',
library: { type: 'var', name: 'app2' },
filename: 'remoteEntry.js',
runtimePlugins: [require.resolve('./react-adapter-runtime-plugin.ts')],
exposes: {
'./Button': './src/components/Button',
'./ModernComponent': './src/components/ModernReactComponent',
Expand Down

0 comments on commit 7635dfb

Please sign in to comment.