Skip to content

Commit b9fdade

Browse files
committed
fix(ui): restore webpack 5 production build and dependency resolution
- replace webpack 4-only production plugins with webpack 5 equivalents - restore extracted CSS, asset-manifest generation, and service-worker output - remove the legacy peer dependency install workaround from the UI build script - align ui package dependencies and regenerate the lockfile to install cleanly - replace the outdated ts-jest preprocessor shim with a local TypeScript Jest transform - revert dist/npm inquirer and find-process to CommonJS-safe versions - tighten configToYAML typing and align CustomNavLink active state with NavLink semantics - fix TerminalCache typing so the UI build passes lint and type checks
1 parent 3785612 commit b9fdade

11 files changed

Lines changed: 3437 additions & 2490 deletions

File tree

assets/assets.go

Lines changed: 11 additions & 9 deletions
Large diffs are not rendered by default.

dist/npm/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
},
2020
"dependencies": {
2121
"cli-spinner": "^0.2.10",
22-
"find-process": "^2.1.1",
23-
"inquirer": "^13.3.2",
22+
"find-process": "^1.4.7",
23+
"inquirer": "^7.0.5",
2424
"node-fetch": "^2.6.7"
2525
},
2626
"license": "Apache-2.0"
27-
}
27+
}

hack/build-ui.bash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ set -e
55
DEVSPACE_ROOT=$(git rev-parse --show-toplevel)
66

77
# Install dependencies
8-
cd ui && npm install --legacy-peer-deps && npm run build
8+
cd ui && npm install && npm run build
99

1010
# Pack ui
1111
echo "Packing ui"

ui/config/jest/typescriptTransform.js

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,25 @@
22

33
'use strict';
44

5-
const tsJestPreprocessor = require('ts-jest/preprocessor');
5+
const path = require('path');
6+
const typescript = require('typescript');
67

7-
module.exports = tsJestPreprocessor;
8+
const configPath = path.resolve(__dirname, '../../tsconfig.test.json');
9+
const { config } = typescript.readConfigFile(configPath, typescript.sys.readFile);
10+
const parsedConfig = typescript.parseJsonConfigFileContent(config, typescript.sys, path.dirname(configPath));
11+
12+
module.exports = {
13+
process(src, filename) {
14+
const result = typescript.transpileModule(src, {
15+
compilerOptions: {
16+
...parsedConfig.options,
17+
sourceMap: false,
18+
},
19+
fileName: filename,
20+
});
21+
22+
return {
23+
code: result.outputText,
24+
};
25+
},
26+
};

ui/config/webpack.config.dev.js

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -233,20 +233,18 @@ module.exports = {
233233
},
234234
],
235235
},
236-
// "file" loader makes sure those assets get served by WebpackDevServer.
236+
// Webpack 5 asset modules emit files directly without file-loader.
237237
// When you `import` an asset, you get its (virtual) filename.
238238
// In production, they would get copied to the `build` folder.
239-
// This loader doesn't use a "test" so it will catch all modules
240-
// that fall through the other loaders.
241239
{
242240
// Exclude `js` files to keep "css" loader working as it injects
243-
// its runtime that would otherwise processed through "file" loader.
241+
// its runtime that would otherwise be processed through the asset rule.
244242
// Also exclude `html` and `json` extensions so they get processed
245-
// by webpacks internal loaders.
243+
// by webpack's internal loaders.
246244
exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
247-
loader: require.resolve('file-loader'),
248-
options: {
249-
name: 'static/media/[name].[hash:8].[ext]',
245+
type: 'asset/resource',
246+
generator: {
247+
filename: 'static/media/[name].[hash:8][ext]',
250248
},
251249
},
252250
],

ui/config/webpack.config.prod.js

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ const autoprefixer = require('autoprefixer');
44
const path = require('path');
55
const webpack = require('webpack');
66
const HtmlWebpackPlugin = require('html-webpack-plugin');
7+
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
8+
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
9+
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
710
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
811
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
912
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
@@ -43,6 +46,13 @@ if (env.stringified['process.env'].NODE_ENV !== '"production"') {
4346
throw new Error('Production builds must have NODE_ENV=production.');
4447
}
4548

49+
const cssFilename = 'static/css/[name].[contenthash:8].css';
50+
const cssPublicPath = shouldUseRelativeAssetPaths ? Array(cssFilename.split('/').length).join('../') : undefined;
51+
const getExtractLoader = () => ({
52+
loader: MiniCssExtractPlugin.loader,
53+
options: cssPublicPath ? { publicPath: cssPublicPath } : {},
54+
});
55+
4656
// This is the production configuration.
4757
// It compiles slowly and is focused on producing a fast and minimal bundle.
4858
// The development configuration is different and lives in a separate file.
@@ -159,43 +169,47 @@ module.exports = {
159169
{
160170
test: /\.module\.s(a|c)ss$/,
161171
use: [
162-
require.resolve('style-loader'),
163-
// isDevelopment ? 'style-loader' : MiniCssExtractPlugin.loader,
172+
getExtractLoader(),
164173
{
165174
loader: require.resolve('css-loader'),
166175
options: {
167176
importLoaders: 1,
168177
modules: {
169178
localIdentName: '[hash:base64]',
170179
},
180+
sourceMap: shouldUseSourceMap,
171181
},
172182
},
173183
{
174-
...getSassLoader(),
184+
...getSassLoader({
185+
sourceMap: shouldUseSourceMap,
186+
}),
175187
},
176188
],
177189
},
178190
// SCSS: https://github.com/webpack-contrib/sass-loader
179191
{
180192
test: /\.scss$/,
181193
use: [
182-
'style-loader', // creates style nodes from JS strings
183-
'css-loader', // translates CSS into CommonJS
184-
getSassLoader(), // compiles Sass to CSS
194+
getExtractLoader(),
195+
{
196+
loader: require.resolve('css-loader'),
197+
options: {
198+
sourceMap: shouldUseSourceMap,
199+
},
200+
},
201+
getSassLoader({
202+
sourceMap: shouldUseSourceMap,
203+
}),
185204
],
186205
},
187206
// "postcss" loader applies autoprefixer to our CSS.
188207
// "css" loader resolves paths in CSS and adds assets as dependencies.
189-
// "style" loader turns CSS into JS modules that inject <style> tags.
208+
// "mini-css-extract-plugin" extracts the final CSS into a production asset.
190209
{
191210
test: /\.css$/,
192211
use: [
193-
{
194-
loader: require.resolve('style-loader'),
195-
options: {
196-
hmr: false,
197-
},
198-
},
212+
getExtractLoader(),
199213
{
200214
loader: require.resolve('css-loader'),
201215
options: {
@@ -226,19 +240,17 @@ module.exports = {
226240
],
227241
},
228242

229-
// "file" loader makes sure assets end up in the `build` folder.
243+
// Webpack 5 asset modules emit files directly without file-loader.
230244
// When you `import` an asset, you get its filename.
231-
// This loader doesn't use a "test" so it will catch all modules
232-
// that fall through the other loaders.
233245
{
234-
loader: require.resolve('file-loader'),
235246
// Exclude `js` files to keep "css" loader working as it injects
236-
// it's runtime that would otherwise processed through "file" loader.
247+
// its runtime that would otherwise be processed through the asset rule.
237248
// Also exclude `html` and `json` extensions so they get processed
238-
// by webpacks internal loaders.
249+
// by webpack's internal loaders.
239250
exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
240-
options: {
241-
name: 'static/media/[name].[hash:8].[ext]',
251+
type: 'asset/resource',
252+
generator: {
253+
filename: 'static/media/[name].[hash:8][ext]',
242254
},
243255
},
244256
// ** STOP ** Are you adding a new loader?
@@ -313,6 +325,20 @@ module.exports = {
313325
// Default number of concurrent runs: os.cpus().length - 1
314326
parallel: true,
315327
}),
328+
new MiniCssExtractPlugin({
329+
filename: cssFilename,
330+
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
331+
}),
332+
new WebpackManifestPlugin({
333+
fileName: 'asset-manifest.json',
334+
}),
335+
new WorkboxWebpackPlugin.GenerateSW({
336+
dontCacheBustURLsMatching: /\.\w{8}\./,
337+
swDest: 'service-worker.js',
338+
navigateFallback: publicUrl + '/index.html',
339+
navigateFallbackDenylist: [/^\/__/],
340+
exclude: [/\.map$/, /asset-manifest\.json$/],
341+
}),
316342
// Moment.js is an extremely popular library that bundles large locale files
317343
// by default due to how Webpack interprets its code. This is a practical
318344
// solution that requires the user to opt into importing specific locales.

0 commit comments

Comments
 (0)