cli: Integrate CSS bundling as a Rollup plugin
Instead of having a separate post-build step for CSS entry points, the CSS bundling is now integrated directly into the Rollup build as a plugin. This is cleaner and will enable better watch mode support in the future. Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -37,7 +37,7 @@ import {
|
||||
OutputPlugin,
|
||||
} from 'rollup';
|
||||
|
||||
import { forwardFileImports } from './plugins';
|
||||
import { forwardFileImports, cssEntryPoints } from './plugins';
|
||||
import { BuildOptions, Output } from './types';
|
||||
import { paths } from '../../../../lib/paths';
|
||||
import { BackstagePackageJson } from '@backstage/cli-node';
|
||||
@@ -275,6 +275,7 @@ export async function makeRollupConfigs(
|
||||
target: 'ES2023',
|
||||
minify: options.minify,
|
||||
}),
|
||||
cssEntryPoints({ entryPoints, targetDir }),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage 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 fs from 'fs-extra';
|
||||
import postcss from 'postcss';
|
||||
// @ts-expect-error - no types available
|
||||
import postcssImport from 'postcss-import';
|
||||
import { resolve as resolvePath, dirname } from 'node:path';
|
||||
import { EntryPoint } from '../../../../lib/entryPoints';
|
||||
|
||||
/**
|
||||
* Bundles a CSS entry point, resolving @import statements.
|
||||
*/
|
||||
export async function buildCSSEntryPoint(
|
||||
entryPoint: EntryPoint,
|
||||
targetDir: string,
|
||||
): Promise<void> {
|
||||
const sourcePath = resolvePath(targetDir, entryPoint.path);
|
||||
// Convert src/ path to dist/ path
|
||||
const outputPath = resolvePath(
|
||||
targetDir,
|
||||
entryPoint.path.replace(/^(\.\/)?src\//, 'dist/'),
|
||||
);
|
||||
|
||||
// Read source CSS
|
||||
const source = await fs.readFile(sourcePath, 'utf8');
|
||||
|
||||
// Bundle @import statements using postcss-import
|
||||
const result = await postcss([postcssImport()]).process(source, {
|
||||
from: sourcePath,
|
||||
to: outputPath,
|
||||
});
|
||||
|
||||
// Ensure output directory exists
|
||||
await fs.mkdir(dirname(outputPath), { recursive: true });
|
||||
|
||||
// Write the bundled CSS
|
||||
await fs.writeFile(outputPath, result.css);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds all CSS entry points for a package.
|
||||
*/
|
||||
export async function buildCSSEntryPoints(
|
||||
entryPoints: EntryPoint[],
|
||||
targetDir: string,
|
||||
): Promise<void> {
|
||||
const cssEntryPoints = entryPoints.filter(ep => ep.ext === '.css');
|
||||
|
||||
for (const entryPoint of cssEntryPoints) {
|
||||
await buildCSSEntryPoint(entryPoint, targetDir);
|
||||
}
|
||||
}
|
||||
@@ -23,8 +23,6 @@ import { makeRollupConfigs } from './config';
|
||||
import { BuildOptions, Output } from './types';
|
||||
import { PackageRoles } from '@backstage/cli-node';
|
||||
import { runParallelWorkers } from '../../../../lib/parallel';
|
||||
import { buildCSSEntryPoints } from './css';
|
||||
import { readEntryPoints } from '../../../../lib/entryPoints';
|
||||
|
||||
export function formatErrorMessage(error: any) {
|
||||
let msg = '';
|
||||
@@ -115,12 +113,6 @@ export const buildPackage = async (options: BuildOptions) => {
|
||||
const buildTasks = rollupConfigs.map(rollupBuild);
|
||||
|
||||
await Promise.all(buildTasks);
|
||||
|
||||
// Build CSS entry points after the main build
|
||||
if (options.packageJson) {
|
||||
const entryPoints = readEntryPoints(options.packageJson);
|
||||
await buildCSSEntryPoints(entryPoints, targetDir);
|
||||
}
|
||||
};
|
||||
|
||||
export const buildPackages = async (options: BuildOptions[]) => {
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
|
||||
import fs from 'fs-extra';
|
||||
import postcss from 'postcss';
|
||||
// @ts-expect-error - no types available
|
||||
import postcssImport from 'postcss-import';
|
||||
import {
|
||||
dirname,
|
||||
resolve as resolvePath,
|
||||
@@ -27,6 +30,7 @@ import {
|
||||
OutputChunk,
|
||||
HasModuleSideEffects,
|
||||
} from 'rollup';
|
||||
import { EntryPoint } from '../../../../lib/entryPoints';
|
||||
|
||||
type ForwardFileImportsOptions = {
|
||||
include: Array<string | RegExp> | string | RegExp | null;
|
||||
@@ -169,3 +173,44 @@ export function forwardFileImports(options: ForwardFileImportsOptions) {
|
||||
},
|
||||
} satisfies Plugin;
|
||||
}
|
||||
|
||||
interface CssEntryPointsOptions {
|
||||
entryPoints: EntryPoint[];
|
||||
targetDir: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollup plugin that bundles CSS entry points using postcss-import.
|
||||
* CSS files declared in package.json exports are processed and emitted
|
||||
* as part of the Rollup bundle.
|
||||
*/
|
||||
export function cssEntryPoints(options: CssEntryPointsOptions): Plugin {
|
||||
const cssEntries = options.entryPoints.filter(ep => ep.ext === '.css');
|
||||
|
||||
return {
|
||||
name: 'backstage-css-entry-points',
|
||||
|
||||
async generateBundle() {
|
||||
for (const entryPoint of cssEntries) {
|
||||
const sourcePath = resolvePath(options.targetDir, entryPoint.path);
|
||||
// Convert src/ path to dist/ path for output filename
|
||||
const outputPath = entryPoint.path.replace(/^(\.\/)?src\//, '');
|
||||
|
||||
// Read source CSS
|
||||
const source = await fs.readFile(sourcePath, 'utf8');
|
||||
|
||||
// Bundle @import statements using postcss-import
|
||||
const result = await postcss([postcssImport()]).process(source, {
|
||||
from: sourcePath,
|
||||
});
|
||||
|
||||
// Emit the bundled CSS as an asset
|
||||
this.emitFile({
|
||||
type: 'asset',
|
||||
fileName: outputPath,
|
||||
source: result.css,
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user