diff --git a/.gitattributes b/.gitattributes index d207b1802b2..0d6d68cde01 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,6 @@ -*.go text eol=lf +*.go text eol=lf +*.ts text eol=lf +*.tsx text eol=lf +*.js text eol=lf +*.jsx text eol=lf +*.json text eol=lf diff --git a/frontend/rsbuild.config.ts b/frontend/rsbuild.config.ts index a93b2770be4..b208535edf8 100644 --- a/frontend/rsbuild.config.ts +++ b/frontend/rsbuild.config.ts @@ -1,15 +1,34 @@ +/* + * Copyright 2025 The Kubernetes Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { defineConfig } from '@rsbuild/core'; +import { pluginNodePolyfill } from '@rsbuild/plugin-node-polyfill'; import { pluginReact } from '@rsbuild/plugin-react'; import { pluginSvgr } from '@rsbuild/plugin-svgr'; -import { pluginNodePolyfill } from '@rsbuild/plugin-node-polyfill'; // Dynamically inject REACT_APP_ environment variables const reactAppEnvVars = Object.entries(process.env) .filter(([key, value]) => key.startsWith('REACT_APP_') && value !== undefined) - .reduce((env, [key, value]) => { - env[`import.meta.env.${key}`] = JSON.stringify(value); - return env; - }, { 'import.meta.env': '{}' }); + .reduce( + (env, [key, value]) => { + env[`import.meta.env.${key}`] = JSON.stringify(value); + return env; + }, + { 'import.meta.env': '{}' } + ); // Use environment variable for backend port, defaulting to 4466 const backendPort = process.env.HEADLAMP_PORT || '4466'; @@ -44,7 +63,7 @@ export default defineConfig({ '/clusters', '/plugins', '/config', - '/auth', + '/auth/', '/oidc', '/oidc-callback', '/externalproxy', @@ -138,7 +157,7 @@ export default defineConfig({ pluginReact({ swcReactOptions: { throwIfNamespace: false, - } + }, }), pluginSvgr({ svgrOptions: { diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index ad879207039..5a4b647d137 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -1,158 +1,158 @@ -/* - * Copyright 2025 The Kubernetes Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import react from '@vitejs/plugin-react'; -import { defineConfig } from 'vite'; -import { nodePolyfills } from 'vite-plugin-node-polyfills'; -import svgr from 'vite-plugin-svgr'; -import { viteStaticCopy } from "vite-plugin-static-copy"; - +/* + * Copyright 2025 The Kubernetes Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vite'; +import { nodePolyfills } from 'vite-plugin-node-polyfills'; +import { viteStaticCopy } from "vite-plugin-static-copy"; +import svgr from 'vite-plugin-svgr'; + // Use environment variable for backend port, defaulting to 4466 const backendPort = process.env.HEADLAMP_PORT || '4466'; const backendTarget = `http://localhost:${backendPort}`; const underTest = process.env.UNDER_TEST === 'true' || process.env.VITEST === 'true'; - -export default defineConfig({ + +export default defineConfig({ define: { global: 'globalThis', 'import.meta.env.UNDER_TEST': JSON.stringify(underTest), }, - envPrefix: 'REACT_APP_', - base: process.env.PUBLIC_URL, - server: { - port: 3000, - proxy: { - '/api': { - target: backendTarget, - changeOrigin: true, - }, - '/clusters': { - target: backendTarget, - changeOrigin: true, - }, - '/plugins': { - target: backendTarget, - changeOrigin: true, - }, - '/config': { - target: backendTarget, - changeOrigin: true, - }, - '/auth': { - target: backendTarget, - changeOrigin: true, - }, - '/oidc': { - target: backendTarget, - changeOrigin: true, - }, - '/oidc-callback': { - target: backendTarget, - changeOrigin: true, - }, - '/wsMultiplexer': { - target: backendTarget, - changeOrigin: true, - ws: true, - }, - '/externalproxy': { - target: backendTarget, - changeOrigin: true, - }, - '/drain-node': { - target: backendTarget, - changeOrigin: true, - }, - '/drain-node-status': { - target: backendTarget, - changeOrigin: true, - }, - '/parseKubeConfig': { - target: backendTarget, - changeOrigin: true, - }, - '/cluster': { - target: backendTarget, - changeOrigin: true, - }, - '/metrics': { - target: backendTarget, - changeOrigin: true, - }, - }, - cors: true, - }, - plugins: [ - svgr({ - svgrOptions: { - prettier: false, - svgo: false, - svgoConfig: { - plugins: [{ removeViewBox: false }], - }, - titleProp: true, - ref: true, - }, - }), - react(), - nodePolyfills({ - include: ['process', 'buffer', 'stream'], - }), - // Make sure we copy the minified monaco-editor source into the static folder - // since it's loaded dynamically and not bundled via ESM. We do it this way - // to support setting the localization language - viteStaticCopy({ - targets: [ - { - src: "node_modules/monaco-editor/min/vs", - dest: "assets", // copies to assets/vs - }, - ], - }), - ], - build: { - outDir: 'build', - commonjsOptions: { - transformMixedEsModules: true, - }, - rollupOptions: { - // Exclude @axe-core from production bundle - external: ['@axe-core/react'], - output: { - manualChunks(id: string) { - // Build smaller chunks for @mui, lodash, xterm, recharts - if (id.includes('node_modules')) { - if (id.includes('lodash')) { - return 'vendor-lodash'; - } - - if (id.includes('@mui/material')) { - return 'vendor-mui'; - } - - if (id.includes('xterm')) { - return 'vendor-xterm'; - } - - if (id.includes('recharts')) { - return 'vendor-recharts'; - } - } - }, - }, - }, - }, -}); + envPrefix: 'REACT_APP_', + base: process.env.PUBLIC_URL, + server: { + port: 3000, + proxy: { + '/api': { + target: backendTarget, + changeOrigin: true, + }, + '/clusters': { + target: backendTarget, + changeOrigin: true, + }, + '/plugins': { + target: backendTarget, + changeOrigin: true, + }, + '/config': { + target: backendTarget, + changeOrigin: true, + }, + '/auth/': { + target: backendTarget, + changeOrigin: true, + }, + '/oidc': { + target: backendTarget, + changeOrigin: true, + }, + '/oidc-callback': { + target: backendTarget, + changeOrigin: true, + }, + '/wsMultiplexer': { + target: backendTarget, + changeOrigin: true, + ws: true, + }, + '/externalproxy': { + target: backendTarget, + changeOrigin: true, + }, + '/drain-node': { + target: backendTarget, + changeOrigin: true, + }, + '/drain-node-status': { + target: backendTarget, + changeOrigin: true, + }, + '/parseKubeConfig': { + target: backendTarget, + changeOrigin: true, + }, + '/cluster': { + target: backendTarget, + changeOrigin: true, + }, + '/metrics': { + target: backendTarget, + changeOrigin: true, + }, + }, + cors: true, + }, + plugins: [ + svgr({ + svgrOptions: { + prettier: false, + svgo: false, + svgoConfig: { + plugins: [{ removeViewBox: false }], + }, + titleProp: true, + ref: true, + }, + }), + react(), + nodePolyfills({ + include: ['process', 'buffer', 'stream'], + }), + // Make sure we copy the minified monaco-editor source into the static folder + // since it's loaded dynamically and not bundled via ESM. We do it this way + // to support setting the localization language + viteStaticCopy({ + targets: [ + { + src: 'node_modules/monaco-editor/min/vs', + dest: 'assets', // copies to assets/vs + }, + ], + }), + ], + build: { + outDir: 'build', + commonjsOptions: { + transformMixedEsModules: true, + }, + rollupOptions: { + // Exclude @axe-core from production bundle + external: ['@axe-core/react'], + output: { + manualChunks(id: string) { + // Build smaller chunks for @mui, lodash, xterm, recharts + if (id.includes('node_modules')) { + if (id.includes('lodash')) { + return 'vendor-lodash'; + } + + if (id.includes('@mui/material')) { + return 'vendor-mui'; + } + + if (id.includes('xterm')) { + return 'vendor-xterm'; + } + + if (id.includes('recharts')) { + return 'vendor-recharts'; + } + } + }, + }, + }, + }, +});