mirror of
https://github.com/compiler-explorer/compiler-explorer.git
synced 2025-12-27 09:23:52 -05:00
## Problem
The SCSS migration encountered issues with Golden Layout CSS imports:
1. Sass `@import` statements are deprecated and will be removed in Dart
Sass 3.0.0
2. `@use` cannot be used inside conditional blocks like
`html[data-theme='default']`
3. The `~` webpack resolver doesn't work with `@use`, only `@import`
Current problematic code:
```scss
html[data-theme='default'] {
@import '~golden-layout/src/css/goldenlayout-light-theme';
}
```
## Solution
Added a custom webpack loader that automatically inlines Golden Layout
CSS content at build time.
**Custom Loader** (`etc/webpack/replace-golden-layout-imports.js`):
- Detects `@import` statements for `~golden-layout/src/css/*` files
- Reads CSS content from `node_modules/golden-layout/src/css/`
- Replaces import statements with actual CSS content
- Uses generalized regex to handle any golden-layout CSS file
**Integration & Cleanup**:
- Positioned before sass-loader in webpack processing chain
- Automatically syncs with Golden Layout package updates
- Consolidated all webpack loaders in `etc/webpack/` directory
- Moved pug loader from `etc/scripts/parsed-pug/` to `etc/webpack/`
- Converted both loaders to ES modules for consistency
- Removed unnecessary `package.json` override
## Result
Eliminates Sass deprecation warnings while preserving existing theme
architecture. Build-time processing with no runtime overhead. Cleaner
webpack loader organization.
## Files Changed
- `webpack.config.esm.ts` - Updated loader paths and added Golden Layout
processor
- `etc/webpack/replace-golden-layout-imports.js` - Custom loader
implementation
- `etc/webpack/parsed-pug-loader.js` - Moved from
`etc/scripts/parsed-pug/` and converted to ES modules
- Removed `etc/webpack/package.json` - No longer needed with ES modules
- Removed `etc/scripts/parsed-pug/` directory - Consolidated into
webpack directory
---------
Co-authored-by: Claude <noreply@anthropic.com>
214 lines
7.2 KiB
TypeScript
214 lines
7.2 KiB
TypeScript
// Copyright (c) 2020, Compiler Explorer Authors
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions are met:
|
|
//
|
|
// * Redistributions of source code must retain the above copyright notice,
|
|
// this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the distribution.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
// POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
import fs from 'node:fs';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
import {fileURLToPath} from 'node:url';
|
|
|
|
import CopyWebpackPlugin from 'copy-webpack-plugin';
|
|
import CssMinimizerPlugin from 'css-minimizer-webpack-plugin';
|
|
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
|
import MonacoEditorWebpackPlugin from 'monaco-editor-webpack-plugin';
|
|
import TerserPlugin from 'terser-webpack-plugin';
|
|
import Webpack from 'webpack';
|
|
import {WebpackManifestPlugin} from 'webpack-manifest-plugin';
|
|
|
|
const __dirname = path.resolve(path.dirname(fileURLToPath(import.meta.url)));
|
|
const isDev = process.env.NODE_ENV !== 'production';
|
|
|
|
function log(message: string) {
|
|
console.log('webpack: ', message);
|
|
}
|
|
|
|
log(`compiling for ${isDev ? 'development' : 'production'}.`);
|
|
// Memory limits us in most cases, so restrict parallelism to keep us in a sane amount of RAM
|
|
const parallelism = Math.floor(os.totalmem() / (4 * 1024 * 1024 * 1024)) + 1;
|
|
log(`Limiting parallelism to ${parallelism}`);
|
|
|
|
const manifestPath = path.resolve(__dirname, 'out', 'dist');
|
|
const staticPath = path.resolve(__dirname, 'out', 'webpack', 'static');
|
|
const hasGit = fs.existsSync(path.resolve(__dirname, '.git'));
|
|
|
|
// Hack alert: due to a variety of issues, sometimes we need to change
|
|
// the name here. Mostly it's things like webpack changes that affect
|
|
// how minification is done, even though that's supposed not to matter.
|
|
const webpackJsHack = '.v61.';
|
|
const plugins: Webpack.WebpackPluginInstance[] = [
|
|
new MonacoEditorWebpackPlugin({
|
|
languages: [
|
|
'cpp',
|
|
'go',
|
|
'pascal',
|
|
'python',
|
|
'rust',
|
|
'swift',
|
|
'java',
|
|
'julia',
|
|
'kotlin',
|
|
'scala',
|
|
'ruby',
|
|
'csharp',
|
|
'fsharp',
|
|
'vb',
|
|
'dart',
|
|
'typescript',
|
|
'solidity',
|
|
'scheme',
|
|
'objective-c',
|
|
'elixir',
|
|
],
|
|
filename: isDev ? '[name].worker.js' : `[name]${webpackJsHack}worker.[contenthash].js`,
|
|
}),
|
|
new MiniCssExtractPlugin({
|
|
filename: isDev ? '[name].css' : `[name]${webpackJsHack}[contenthash].css`,
|
|
}),
|
|
new WebpackManifestPlugin({
|
|
fileName: path.resolve(manifestPath, 'manifest.json'),
|
|
publicPath: '',
|
|
}),
|
|
new Webpack.DefinePlugin({
|
|
'window.PRODUCTION': JSON.stringify(!isDev),
|
|
}),
|
|
new CopyWebpackPlugin({
|
|
patterns: [{from: './public', to: staticPath}],
|
|
}),
|
|
];
|
|
|
|
if (isDev) {
|
|
plugins.push(new Webpack.HotModuleReplacementPlugin());
|
|
}
|
|
|
|
export default {
|
|
mode: isDev ? 'development' : 'production',
|
|
entry: {
|
|
main: './static/main.ts',
|
|
noscript: './static/noscript.ts',
|
|
},
|
|
output: {
|
|
filename: isDev ? '[name].js' : `[name]${webpackJsHack}[contenthash].js`,
|
|
path: staticPath,
|
|
},
|
|
cache: {
|
|
type: 'filesystem',
|
|
buildDependencies: {
|
|
config: [
|
|
fileURLToPath(import.meta.url),
|
|
// Depend on the package.json to force a recache if something changes:
|
|
// this is only because something in Monaco upsets the cache if its version changes
|
|
path.resolve(__dirname, 'package.json'),
|
|
],
|
|
},
|
|
},
|
|
resolve: {
|
|
alias: {
|
|
'monaco-editor$': 'monaco-editor/esm/vs/editor/editor.api',
|
|
},
|
|
fallback: {
|
|
path: 'path-browserify',
|
|
},
|
|
modules: ['./static', './node_modules'],
|
|
extensions: ['.ts', '.js'],
|
|
extensionAlias: {
|
|
'.js': ['.ts', '.js'],
|
|
'.mjs': ['.mts', '.mjs'],
|
|
},
|
|
},
|
|
stats: 'normal',
|
|
devtool: 'source-map',
|
|
optimization: {
|
|
runtimeChunk: 'single',
|
|
splitChunks: {
|
|
cacheGroups: {
|
|
vendors: {
|
|
test: /[/\\]node_modules[/\\]/,
|
|
name: 'vendor',
|
|
chunks: 'all',
|
|
priority: -10,
|
|
},
|
|
},
|
|
},
|
|
moduleIds: 'deterministic',
|
|
minimizer: [
|
|
new CssMinimizerPlugin(),
|
|
new TerserPlugin({
|
|
parallel: true,
|
|
terserOptions: {
|
|
ecma: 5,
|
|
sourceMap: true,
|
|
},
|
|
}),
|
|
],
|
|
},
|
|
parallelism: parallelism,
|
|
module: {
|
|
rules: [
|
|
{
|
|
test: /\.s?css$/,
|
|
use: [
|
|
{
|
|
loader: MiniCssExtractPlugin.loader,
|
|
options: {
|
|
publicPath: './',
|
|
},
|
|
},
|
|
'css-loader',
|
|
{
|
|
loader: 'sass-loader',
|
|
options: {
|
|
sassOptions: {
|
|
fatalDeprecations: ['import'],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
loader: path.resolve(__dirname, 'etc/webpack/replace-golden-layout-imports.js'),
|
|
},
|
|
],
|
|
},
|
|
{
|
|
test: /\.(png|woff|woff2|eot|ttf|svg)$/,
|
|
type: 'asset',
|
|
parser: {dataUrlCondition: {maxSize: 8192}},
|
|
},
|
|
{
|
|
test: /\.pug$/,
|
|
loader: path.resolve(__dirname, 'etc/webpack/parsed-pug-loader.js'),
|
|
options: {
|
|
useGit: hasGit,
|
|
},
|
|
},
|
|
{
|
|
test: /\.ts$/,
|
|
loader: 'ts-loader',
|
|
},
|
|
{
|
|
test: /\.js$/,
|
|
loader: 'source-map-loader',
|
|
},
|
|
],
|
|
},
|
|
plugins: plugins,
|
|
} satisfies Webpack.Configuration;
|