Skip to content

Commit

Permalink
frontend: use nextjs with module federation
Browse files Browse the repository at this point in the history
  • Loading branch information
malinskibeniamin committed Jan 5, 2024
1 parent 46f3bbe commit fbdd1ca
Show file tree
Hide file tree
Showing 25 changed files with 2,392 additions and 413 deletions.
6 changes: 5 additions & 1 deletion frontend/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"react-app",
"plugin:react/recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:react-hooks/recommended"
"plugin:react-hooks/recommended",
"next/core-web-vitals"
],
"parserOptions": {
"ecmaVersion": 2018,
Expand Down Expand Up @@ -56,6 +57,9 @@
],
"eqeqeq": [
"off"
],
"@next/next/no-img-element": [ // TODO: Remove once we are ready to use Image component
"off"
]
}
}
2 changes: 1 addition & 1 deletion frontend/.nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v18
v18.19.0
22 changes: 0 additions & 22 deletions frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,6 @@
<!-- Unused for now -->
<!-- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@500;600;700&display=swap" rel="stylesheet"> -->
<!-- <link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap" rel="stylesheet"> -->

<script>
{
let basePath = window["BASE_URL"] = "__BASE_PATH_REPLACE_MARKER__";
window["ENABLED_FEATURES"] = "__FEATURES_REPLACE_MARKER__";

window.__getLocation = function () {
return window.location;
};
let l = window.__getLocation();
let base = document.createElement('base');
if (!basePath.startsWith('__BASE')) {
base.href = l.protocol + '//' + l.hostname + (l.port ? (':' + l.port) : '') + basePath;
} else {
base.href = l.protocol + '//' + l.hostname + (l.port ? (':' + l.port) : '') + '/';
}
document.head.appendChild(base);
}
</script>

<!-- <link rel="icon" type="image/x-icon" href="./favicon.ico" /> -->
<link rel="icon" type="image/png" sizes="384x384" href="/favicon-32.png" />
</head>

<body>
Expand Down
2 changes: 1 addition & 1 deletion frontend/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const esModules = [
module.exports = {
roots: ['<rootDir>/src'],
collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}', '!src/**/*.d.ts'],
setupFiles: ['react-app-polyfill/jsdom'],
setupFiles: ['./jest.polyfills.js', 'react-app-polyfill/jsdom'],
setupFilesAfterEnv: ['<rootDir>/src/setupTests.ts'],
testMatch: [
'<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}',
Expand Down
17 changes: 17 additions & 0 deletions frontend/jest.polyfills.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// jest.polyfills.js
/**
* @note The block below contains polyfills for Node.js globals
* required for Jest to function when running JSDOM tests.
* These HAVE to be require's and HAVE to be in this exact
* order, since "undici" depends on the "TextEncoder" global API.
*
* Consider migrating to a more modern test runner if
* you don't want to deal with this.
*/

const { TextDecoder, TextEncoder } = require('node:util')

Object.defineProperties(globalThis, {
TextDecoder: { value: TextDecoder },
TextEncoder: { value: TextEncoder },
})
5 changes: 5 additions & 0 deletions frontend/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
83 changes: 83 additions & 0 deletions frontend/next.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { NextFederationPlugin } from '@module-federation/nextjs-mf';

/** @type {import('next').NextConfig} */
const nextConfig = {
// Optionally, add any other Next.js config below
reactStrictMode: true,
swcMinify: true,
output: 'export',
images: { // Required to properly export HTML files
unoptimized: true
},
experimental: {
// Optimize how packages get loaded in dev mode
optimizePackageImports: [
'@redpanda-data/ui',
'react-bootstrap',
'react-icons',
'lodash',
'@chakra-ui/react',
'@chakra-ui/form-control',
'@chakra-ui/icon',
'@chakra-ui/layout',
'@chakra-ui/media-query',
'@chakra-ui/menu',
'@chakra-ui/spinner',
'@chakra-ui/styled-system',
'@chakra-ui/system',
'@mui/material',
'date-fns',
'antd',
],
},
webpack: (config) => {
config.plugins.push(
/**
* Module Federation for NextJS only works well in Pages Router
* https://github.com/module-federation/module-federation-examples/issues/3151#issuecomment-1720250040
*/
new NextFederationPlugin({
name: 'rp_console',
filename: 'static/chunks/embedded.js',
exposes: {
// specify exposed pages and components
'./EmbeddedApp': './src/EmbeddedApp',
'./injectApp': './src/injectApp',
'./config': './src/config.ts',
},
})
);

/**
* Allow the .js extension in import paths when importing TypeScript files.
* It is the standard for ECMAScript modules, but not all bundlers have
* caught up yet.
* Alternatively, add the plugin option `import_extension=none` in buf.gen.yaml.
* Required for App
*/
config.resolve = {
...config.resolve,
extensionAlias: {
'.js': ['.ts', '.js'],
},
};

/**
* Required because we use pages router, which does not allow importing CSS directly from our @redpanda-data/ui library.
* https://github.com/vercel/next.js/discussions/27953#discussioncomment-3616403
*/
config.module?.rules
.find((rule) => rule.oneOf)
.oneOf.forEach((rule) => {
if (rule.issuer?.and?.[0]?.toString().includes("_app")) {
const and = rule.issuer.and
rule.issuer.or = [/[\\/]node_modules[\\/]@redpanda-data[\\/]/, { and }]
delete rule.issuer.and
}
})

return config;
},
};

export default nextConfig;
Loading

0 comments on commit fbdd1ca

Please sign in to comment.