Rollup plugin for processing and bundling Sass/SCSS files with support for CSS modules, PostCSS integration, and multiple output formats
—
Advanced features for CSS processing, modules generation, PostCSS integration, and custom transformations.
Custom CSS processor function for advanced transformations like PostCSS integration, autoprefixing, and CSS modules.
/**
* Custom CSS processor function for advanced transformations
* @param styles - Compiled CSS string
* @param id - File path/ID of the processed file
* @returns Processed CSS string or object with css and additional exports
*/
type RollupPluginSassProcessorFn<T = RollupPluginSassProcessorFnOutput> =
(styles: string, id: string) => Promise<T> | T;
type RollupPluginSassProcessorFnOutput =
| string
| {
css: string;
cssModules?: Record<string, string>;
[key: string]: unknown;
};Usage Examples:
import sass from 'rollup-plugin-sass';
import postcss from 'postcss';
import autoprefixer from 'autoprefixer';
// PostCSS integration
sass({
processor: async (css, id) => {
const result = await postcss([autoprefixer])
.process(css, { from: id });
return result.css;
},
});
// Multiple PostCSS plugins
sass({
processor: async (css, id) => {
const result = await postcss([
autoprefixer(),
require('cssnano')({ preset: 'default' }),
]).process(css, { from: id });
return result.css;
},
});Generate CSS modules by returning cssModules object from processor function.
interface CSSModulesOutput {
/** Processed CSS string */
css: string;
/** CSS modules mapping object that becomes the default export */
cssModules?: Record<string, string>;
/** Additional named exports */
[key: string]: unknown;
}Usage Examples:
import sass from 'rollup-plugin-sass';
import postcss from 'postcss';
import postcssModules from 'postcss-modules';
// CSS Modules with postcss-modules
sass({
processor: async (css, id) => {
let cssModules = {};
const result = await postcss([
postcssModules({
getJSON: (_, json) => {
if (json) cssModules = json;
},
}),
]).process(css, { from: id });
return {
css: result.css,
cssModules,
};
},
});Then in your JavaScript:
import styles from './component.scss';
// styles is now the CSS modules object
console.log(styles.className); // "component_className_abc123"Create additional named exports alongside the default CSS export.
interface ProcessorWithExports {
css: string;
/** Additional named exports available via import { exportName } */
[exportName: string]: unknown;
}Usage Examples:
sass({
processor: (css, id) => {
return {
css: css,
theme: 'dark',
version: '1.0.0',
breakpoints: {
mobile: '768px',
tablet: '1024px',
},
};
},
});Usage in JavaScript:
import styles, { theme, version, breakpoints } from './styles.scss';Extract Sass variables and make them available as JavaScript exports using icss-utils.
Usage Examples:
import sass from 'rollup-plugin-sass';
import postcss from 'postcss';
import { extractICSS } from 'icss-utils';
sass({
processor: (css) => {
const pcssRoot = postcss.parse(css);
const extractedIcss = extractICSS(pcssRoot, true);
const cleanedCss = pcssRoot.toString();
return {
css: cleanedCss,
...extractedIcss.icssExports,
};
},
});With Sass file containing:
:export {
primaryColor: #007bff;
fontSize: 16px;
}
.button {
color: $primary-color;
font-size: $font-size;
}Available in JavaScript:
import styles, { primaryColor, fontSize } from './styles.scss';Built-in support for importing Sass files from node_modules using ~ syntax.
interface ImporterSupport {
/** Legacy API importer for node_modules resolution */
getImporterListLegacy: (
importOption: LegacyImporter<'async'> | LegacyImporter<'async'>[]
) => LegacyImporter<'async'>[];
/** Modern API importer for node_modules resolution */
getImporterListModern: (
importOption: FileImporter<'async'>[]
) => FileImporter<'async'>[];
}Usage Examples:
// Import from node_modules
@import '~bootstrap/scss/bootstrap';
@import '~normalize.css/normalize';
// Import local files normally
@import './variables';
@import '../components/button';Client-side utility function for injecting styles into the document head.
/**
* Creates and appends style tag to document head (browser-side utility)
* @param css - CSS string to inject
* @returns The injected CSS string or undefined if no CSS or not in browser
*/
function insertStyle(css: string | undefined): string | undefined;This function is automatically included when using insert: true option:
sass({
insert: true, // Automatically includes insertStyle utility
});Advanced output control with detailed style node information.
/**
* Custom output handler with access to individual style nodes
* @param styles - Concatenated CSS string
* @param styleNodes - Array of individual style objects with metadata
*/
type RollupPluginSassOutputFn = (
styles: string,
styleNodes: StyleSheetIdAndContent[]
) => unknown;
interface StyleSheetIdAndContent {
/** File path/ID of the style */
id?: string;
/** Compiled CSS content */
content?: string;
}Usage Examples:
sass({
output(styles, styleNodes) {
// Write concatenated styles
writeFileSync('all-styles.css', styles);
// Write individual style files
styleNodes.forEach((node) => {
if (node.id && node.content) {
const filename = path.basename(node.id, path.extname(node.id)) + '.css';
writeFileSync(`dist/individual/${filename}`, node.content);
}
});
// Generate style manifest
const manifest = {
totalSize: styles.length,
fileCount: styleNodes.length,
files: styleNodes.map(node => ({
id: node.id,
size: node.content?.length || 0,
})),
};
writeFileSync('style-manifest.json', JSON.stringify(manifest, null, 2));
},
});import sass from 'rollup-plugin-sass';
import postcss from 'postcss';
import autoprefixer from 'autoprefixer';
import postcssModules from 'postcss-modules';
import cssnano from 'cssnano';
export default {
input: 'src/index.js',
output: {
file: 'dist/bundle.js',
format: 'esm',
},
plugins: [
sass({
api: 'modern',
include: ['src/**/*.scss'],
// Advanced processor with CSS modules and PostCSS
processor: async (css, id) => {
let cssModules = {};
const result = await postcss([
postcssModules({
getJSON: (_, json) => {
if (json) cssModules = json;
},
}),
autoprefixer(),
cssnano({ preset: 'default' }),
]).process(css, { from: id });
return {
css: result.css,
cssModules,
processedAt: new Date().toISOString(),
};
},
// Custom output with detailed logging
output(styles, styleNodes) {
console.log(`Generated ${styleNodes.length} style files`);
console.log(`Total CSS size: ${styles.length} characters`);
writeFileSync('dist/styles.css', styles);
// Generate source map of style files
const sourceMap = styleNodes.map(node => ({
source: node.id,
size: node.content?.length || 0,
}));
writeFileSync('dist/style-sources.json', JSON.stringify(sourceMap, null, 2));
},
options: {
style: 'compressed',
loadPaths: ['node_modules'],
data: '@import "theme-variables";',
},
}),
],
};Install with Tessl CLI
npx tessl i tessl/npm-rollup-plugin-sass