Skip to content

Commit

Permalink
feat(core): allow directly using plugin manifest
Browse files Browse the repository at this point in the history
  • Loading branch information
Blake Holifield authored Sep 9, 2024
1 parent 226a748 commit 9eede15
Show file tree
Hide file tree
Showing 11 changed files with 219 additions and 63 deletions.
57 changes: 34 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,13 +290,23 @@ const moduleFederationPlugin = new ModuleFederationPlugin({
name: 'host',
filename: 'host.[contenthash].js',
shared: [
{'@openshift/dynamic-plugin-sdk': { singleton: true, requiredVersion: '*'} },
{ '@scalprum/react-core': { singleton: true, requiredVersion: '*'} },
{
'@openshift/dynamic-plugin-sdk': {
singleton: true,
requiredVersion: '*',
},
},
{
'@scalprum/react-core': {
singleton: true,
requiredVersion: '*',
},
},
{ react: { singleton: true, requiredVersion: '*' } },
{ 'react-dom': { singleton: true, requiredVersion: '*' } },
{ 'react-dom': { singleton: true, requiredVersion: '*'} },
// any other packages you wish to share
]
})
],
});
```

Note that for demo purposes, the `requiredVersion` for dependencies in this example is set to `*`, but you can update this to a version that suits your requirements.
Expand Down Expand Up @@ -329,23 +339,24 @@ This is a known issue that is being actively worked on.
const { DynamicRemotePlugin } = require('@openshift/dynamic-plugin-sdk-webpack');

const sharedModules = {
'@openshift/dynamic-plugin-sdk':( singleton: true},
'@scalprum/react-core':( singleton: true},
react: { singleton: true),
'react-dom': ( singleton: true },
'@openshift/dynamic-plugin-sdk': { singleton: true },
'@scalprum/react-core': { singleton: true },
react: { singleton: true },
'react-dom': { singleton: true },
};

const dynamicPlugin = new DynamicRemotePlugin({
extensions: [],
sharedModules,
entryScriptfilename: 'remoteModule.[contenthash].js',
pluginMetadata: {
name: 'remoteModule',
version: '1.0.0',
exposedModules: {
RemoteModuleComponent: './remoteModule/src/RemoteModuleComponent.tsx',
},
extensions: [],
sharedModules,
entryScriptfilename:'remoteModule.(contenthash].js',
pluginMetadata: {
name: "remoteModule",
version: "1.0.0",
exposedModules: {
RemoteModuleComponent": "./remoteModule/src/RemoteModuleComponent.tsx"
},
extensions: []
}
},
});

```
Expand Down Expand Up @@ -441,10 +452,10 @@ const moduleFederationPlugin = new ModuleFederationPlugin({
filename: 'host.[contenthash].js',
shared: [{
// These packages has to be shared and has to be marked as singleton!
{ '@openshift/dynamic-plugin-sdk', { singleton: true, eager: true}}
{ '@scalprum/react-core': { singleton: true, eager: true} },
{ react: { singleton: true, eager: true } },
{ 'react-dom': { singleton: true, eager: true } },
{ '@openshift/dynamic-plugin-sdk', { singleton: true, }}
{ '@scalprum/react-core': { singleton: true, } },
{ react: { singleton: true, } },
{ 'react-dom': { singleton: true } },
// any other packages you wish to share
}]
})
Expand Down
17 changes: 16 additions & 1 deletion examples/test-app-e2e/cypress.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset';
import { defineConfig } from 'cypress';

const nxe2eConfig = nxE2EPreset(__filename, { cypressDir: 'src' });

// Adds logging to terminal for debugging
// https://docs.cypress.io/api/commands/task#Usage
// Usage: `cy.task('log', 'my message');
export default defineConfig({
e2e: nxE2EPreset(__filename, { cypressDir: 'src' }),
e2e: {
...nxe2eConfig,
setupNodeEvents(on) {
on('task', {
log(message) {
console.log(message);
return null;
},
});
},
},
});
13 changes: 12 additions & 1 deletion examples/test-app-e2e/src/e2e/test-app/sdk-plugin-loading.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,18 @@ describe('SDK module loading', () => {
});
it('should show data from prefetch', () => {
cy.visit('http://localhost:4200/sdk');

cy.get('div#sdk-module-item').contains('SDK Inbox').should('exist');
});

it('should render a slider from the pluginManifest', () => {
cy.intercept('GET', '/full-manifest.js?cacheBuster=*').as('manifestRequest');
cy.visit('http://localhost:4200/sdk');

cy.wait('@manifestRequest').then((interception) => {
expect(interception.response.statusCode).to.eq(200);
expect(interception.response.headers['content-type']).to.include('application/javascript');
});
cy.get(`[aria-label="Checked"]`).should('exist');
cy.get('#plugin-manifest').should('exist');
});
});
12 changes: 12 additions & 0 deletions examples/test-app/src/entry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ const config: AppsConfig<{ assetsHost?: string }> = {
assetsHost: 'http://127.0.0.1:8001',
manifestLocation: 'http://127.0.0.1:8001/plugin-manifest.json',
},
'full-manifest': {
name: 'full-manifest',
assetsHost: 'http://127.0.0.1:8001',
pluginManifest: {
name: 'full-manifest',
version: '1.0.0',
extensions: [],
registrationMethod: 'callback',
baseURL: 'auto',
loadScripts: ['full-manifest.js'],
},
},
};

const Entry = () => {
Expand Down
13 changes: 13 additions & 0 deletions examples/test-app/src/modules/SDKComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,16 @@ import Divider from '@mui/material/Divider';
import Slider from '@mui/material/Slider';
import InboxIcon from '@mui/icons-material/Inbox';
import DraftsIcon from '@mui/icons-material/Drafts';
import Checkbox from '@mui/material/Checkbox';

function valuetext(value: number) {
return `${value}°C`;
}

interface namedProps {
name: string;
}

export const NamedSDKComponent = () => {
return (
<Box sx={{ width: 300 }}>
Expand All @@ -23,6 +28,14 @@ export const NamedSDKComponent = () => {
);
};

export const PluginSDKComponent = (props: namedProps = { name: 'named' }) => {
return (
<Box sx={{ width: 300 }}>
<Checkbox aria-label="Checked" id={props.name} defaultChecked />
</Box>
);
};

const SDKComponent = () => {
return (
<Box sx={{ width: '100%', maxWidth: 360, bgcolor: 'background.paper' }}>
Expand Down
6 changes: 6 additions & 0 deletions examples/test-app/src/routes/SDKModules.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { ScalprumComponent } from '@scalprum/react-core';
import { Grid } from '@mui/material';

const SDKModules = () => {
const props = {
name: 'plugin-manifest',
};
return (
<Grid container spacing={4}>
<Grid xs={12} md={6} item>
Expand All @@ -11,6 +14,9 @@ const SDKModules = () => {
<Grid xs={12} md={6} item>
<ScalprumComponent scope="sdk-plugin" module="./SDKComponent" importName="NamedSDKComponent" />
</Grid>
<Grid xs={12} md={6} item>
<ScalprumComponent scope="full-manifest" module="./SDKComponent" importName="PluginSDKComponent" {...props} />
</Grid>
</Grid>
);
};
Expand Down
13 changes: 13 additions & 0 deletions federation-cdn-mock/src/modules/SDKComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,14 @@ import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
import Divider from '@mui/material/Divider';
import Slider from '@mui/material/Slider';
import Checkbox from '@mui/material/Checkbox';
import InboxIcon from '@mui/icons-material/Inbox';
import DraftsIcon from '@mui/icons-material/Drafts';

interface namedProps {
name: string;
}

function valuetext(value: number) {
return `${value}°C`;
}
Expand All @@ -23,6 +28,14 @@ export const NamedSDKComponent = () => {
);
};

export const PluginSDKComponent = (props: namedProps = { name: 'named' }) => {
return (
<Box sx={{ width: 300 }}>
<Checkbox aria-label="Checked" id={props.name} defaultChecked />
</Box>
);
};

const SDKComponent = () => {
return (
<Box sx={{ width: '100%', maxWidth: 360, bgcolor: 'background.paper' }}>
Expand Down
31 changes: 26 additions & 5 deletions federation-cdn-mock/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const { resolve } = require('path');
const { ModuleFederationPlugin, ContainerPlugin } = require('@module-federation/enhanced');
const { DynamicRemotePlugin } = require('@openshift/dynamic-plugin-sdk-webpack');

console.log("Entry tests:", resolve(__dirname, './src/modules/moduleOne.tsx'))
console.log('Entry tests:', resolve(__dirname, './src/modules/moduleOne.tsx'));

const sharedModules = {
react: {
Expand All @@ -25,7 +25,7 @@ const sharedModules = {
},
};

const TestSDKPLugin = new DynamicRemotePlugin({
const TestSDKPlugin = new DynamicRemotePlugin({
extensions: [],
sharedModules,
entryScriptFilename: 'sdk-plugin.[contenthash].js',
Expand All @@ -34,7 +34,7 @@ const TestSDKPLugin = new DynamicRemotePlugin({
pluginOverride: {
ModuleFederationPlugin,
ContainerPlugin,
}
},
},
pluginMetadata: {
name: 'sdk-plugin',
Expand All @@ -53,18 +53,39 @@ const TestSDKPLugin = new DynamicRemotePlugin({
},
});

const FullManifest = new DynamicRemotePlugin({
extensions: [],
sharedModules,
pluginManifestFilename: 'full-manifest.json',
entryScriptFilename: 'full-manifest.js',
moduleFederationSettings: {
// Use non native webpack plugins
pluginOverride: {
ModuleFederationPlugin,
ContainerPlugin,
},
},
pluginMetadata: {
name: 'full-manifest',
version: '1.0.0',
exposedModules: {
'./SDKComponent': resolve(__dirname, './src/modules/SDKComponent.tsx'),
},
},
});

function init() {
/** @type { import("webpack").Configuration } */
const config = {
entry: {
mock: resolve(__dirname, './src/index.tsx'),
},
cache: { type: 'filesystem', cacheDirectory: resolve(__dirname, '.cdn-cache')},
cache: { type: 'filesystem', cacheDirectory: resolve(__dirname, '.cdn-cache') },
output: {
publicPath: 'auto',
},
mode: 'development',
plugins: [TestSDKPLugin],
plugins: [TestSDKPlugin, FullManifest],
module: {
rules: [
{
Expand Down
Loading

0 comments on commit 9eede15

Please sign in to comment.