Gatsby plugin that provides drop-in support for Sass/SCSS stylesheets by integrating sass-loader with webpack configuration
npx @tessl/cli install tessl/npm-gatsby-plugin-sass@6.15.0gatsby-plugin-sass provides drop-in support for Sass/SCSS stylesheets in Gatsby projects by integrating sass-loader with Gatsby's webpack configuration. It supports both regular stylesheets and CSS Modules with extensive configuration options.
npm install sass gatsby-plugin-sassThis is a Gatsby plugin that is configured in gatsby-config.js rather than imported directly in code:
// gatsby-config.js
plugins: [`gatsby-plugin-sass`]For advanced configuration:
// gatsby-config.js
plugins: [
{
resolve: `gatsby-plugin-sass`,
options: {
// Plugin options here
},
},
]npm install sass gatsby-plugin-sass// gatsby-config.js
module.exports = {
plugins: [`gatsby-plugin-sass`]
}// src/styles/main.scss
$primary-color: #663399;
html {
background-color: $primary-color;
p {
color: white;
font-size: 1.2rem;
}
}// In gatsby-browser.js, components, or pages
import "./src/styles/main.scss"The plugin exports two main functions that integrate with Gatsby's build system:
/**
* Main webpack configuration function called by Gatsby during build
* @param helpers - Gatsby build helpers including actions, stage, and loaders
* @param options - Plugin configuration options
*/
function onCreateWebpackConfig(
helpers: {
actions: { setWebpackConfig: (config: any) => void };
stage: 'develop' | 'build-javascript' | 'develop-html' | 'build-html';
loaders: {
miniCssExtract: (options?: any) => any;
css: (options?: any) => any;
postcss: (options?: any) => any;
null: () => any;
};
},
options: GatsbyPluginSassOptions
): void;
/**
* Plugin options validation schema using Joi
* @param helpers - Gatsby schema helpers
* @returns Joi validation schema
*/
function pluginOptionsSchema(helpers: { Joi: any }): any;Configure gatsby-plugin-sass with various options to customize Sass compilation behavior.
// Plugin configuration interface
interface GatsbyPluginSassOptions {
implementation?: any;
additionalData?: string | ((content: string, loaderContext: any) => string);
cssLoaderOptions?: CssLoaderOptions;
postCssPlugins?: any[];
useResolveUrlLoader?: boolean | ResolveUrlLoaderOptions;
sassRuleTest?: RegExp;
sassRuleModulesTest?: RegExp;
sassOptions?: SassOptions;
// Additional sass-loader options can be passed through
[key: string]: any;
}
// CSS loader options - compatible with css-loader v5.x used by Gatsby
interface CssLoaderOptions {
camelCase?: boolean;
esModule?: boolean;
modules?: boolean | CssModulesOptions;
importLoaders?: number;
[key: string]: any;
}
// CSS Modules configuration
interface CssModulesOptions {
namedExport?: boolean;
[key: string]: any;
}
// Resolve URL loader options
interface ResolveUrlLoaderOptions {
options?: {
debug?: boolean;
sourceMap?: boolean;
[key: string]: any;
};
}
// Gatsby build stage types
type GatsbyStage = 'develop' | 'build-javascript' | 'develop-html' | 'build-html';
// Webpack loader configuration returned by Gatsby
interface GatsbyLoaders {
miniCssExtract: (options?: { modules?: { namedExport?: boolean } }) => any;
css: (options?: CssLoaderOptions) => any;
postcss: (options?: { plugins?: any[] }) => any;
null: () => any;
}Usage Examples:
// Basic configuration with Sass options
{
resolve: `gatsby-plugin-sass`,
options: {
sassOptions: {
includePaths: ["src/styles", "node_modules"],
precision: 6,
},
},
}
// Advanced configuration with CSS loader options
{
resolve: `gatsby-plugin-sass`,
options: {
cssLoaderOptions: {
camelCase: false,
modules: {
namedExport: true,
},
},
postCssPlugins: [require('autoprefixer')],
},
}Configure which Sass implementation to use (Dart Sass or Node Sass).
interface SassImplementationOptions {
implementation: any; // require('sass') or require('node-sass')
}Usage Examples:
// Use Dart Sass (default)
{
resolve: `gatsby-plugin-sass`,
options: {
implementation: require('sass'),
},
}
// Use Node Sass
{
resolve: `gatsby-plugin-sass`,
options: {
implementation: require('node-sass'),
},
}Prepend Sass code before actual entry files for global variables or imports.
interface AdditionalDataOptions {
additionalData: string | ((content: string, loaderContext: any) => string);
}Usage Examples:
// String-based additional data
{
resolve: `gatsby-plugin-sass`,
options: {
additionalData: `$env: "${process.env.NODE_ENV}"; @import "variables.scss";`,
},
}
// Function-based additional data
{
resolve: `gatsby-plugin-sass`,
options: {
additionalData: (content, loaderContext) => {
return `$theme: ${getTheme()}; ${content}`;
},
},
}Configure CSS Modules for component-scoped styling.
// CSS Modules are automatically enabled for files matching:
// /\.module\.s(a|c)ss$/
// Custom regex patterns
interface CssModulesPatterns {
sassRuleTest?: RegExp; // Override default Sass file pattern
sassRuleModulesTest?: RegExp; // Override default CSS Modules pattern
}Usage Examples:
// Custom file patterns
{
resolve: `gatsby-plugin-sass`,
options: {
sassRuleTest: /\.global\.s(a|c)ss$/,
sassRuleModulesTest: /\.mod\.s(a|c)ss$/,
},
}/* styles.module.scss - CSS Modules enabled */
.button {
background-color: blue;
color: white;
}
.primaryButton {
composes: button;
background-color: green;
}// Import CSS Modules
import { button, primaryButton } from './styles.module.scss';
const MyComponent = () => (
<button className={primaryButton}>Click me</button>
);Enable relative URL resolution in Sass files.
interface ResolveUrlLoaderConfig {
useResolveUrlLoader: boolean | {
options?: {
debug?: boolean;
sourceMap?: boolean;
[key: string]: any;
};
};
}Usage Examples:
// Enable resolve-url-loader
{
resolve: `gatsby-plugin-sass`,
options: {
useResolveUrlLoader: true,
},
}
// With custom options
{
resolve: `gatsby-plugin-sass`,
options: {
useResolveUrlLoader: {
options: {
debug: true,
sourceMap: true,
},
},
},
}Configure PostCSS plugins for additional CSS processing.
interface PostCssConfiguration {
postCssPlugins: any[]; // Array of PostCSS plugins
}Usage Examples:
{
resolve: `gatsby-plugin-sass`,
options: {
postCssPlugins: [
require('autoprefixer'),
require('cssnano')({ preset: 'default' }),
],
},
}The plugin automatically configures webpack loaders based on build stage and file patterns:
// Internal webpack rule configuration
interface WebpackSassRule {
test: RegExp;
use: Array<{
loader: string;
options?: any;
}>;
}
// Loader chain for regular Sass files:
// 1. sass-loader (compiles Sass/SCSS to CSS)
// 2. resolve-url-loader (optional, if useResolveUrlLoader is enabled)
// 3. postcss-loader (applies PostCSS plugins)
// 4. css-loader (processes CSS imports and url())
// 5. mini-css-extract-plugin (extracts CSS to separate files)
// Loader chain for CSS Modules:
// Same as above but with CSS Modules enabled in css-loaderStage-specific behavior:
The plugin uses Joi for comprehensive option validation:
/**
* Complete validation schema for plugin options
*/
interface PluginValidationSchema {
implementation?: object; // Sass implementation (sass or node-sass)
additionalData?: string | function; // Prepended Sass code
cssLoaderOptions?: object; // css-loader configuration
postCssPlugins?: array; // PostCSS plugins array
sassRuleTest?: RegExp; // Override Sass file pattern
sassRuleModulesTest?: RegExp; // Override CSS Modules pattern
useResolveUrlLoader?: boolean | object; // resolve-url-loader config
sassOptions?: SassOptions; // Sass compiler options
[key: string]?: any; // Additional sass-loader options
}Configure Sass compiler behavior with comprehensive options.
interface SassOptions {
// File and data options
file?: string | null; // Default: null - Path to a file for LibSass to compile
data?: string | null; // Default: null - A string to pass to LibSass to compile
// Import and function options
importer?: (url: string, prev: string, done: (result: any) => void) => any; // Custom importer function
functions?: { [key: string]: (arg1?: any, arg2?: any) => any }; // Custom Sass functions
includePaths?: string[]; // Default: [] - Array of paths for @import resolution
// Syntax and formatting
indentedSyntax?: boolean; // Default: false - Enable Sass indented syntax
indentType?: string; // Default: "space" - Use space or tab for indentation
indentWidth?: number; // Default: 2, Max: 10 - Number of spaces/tabs for indentation
linefeed?: 'cr' | 'crlf' | 'lf' | 'lfcr'; // Default: "lf" - Line break sequence
// Output options
outputStyle?: 'nested' | 'expanded' | 'compact' | 'compressed'; // CSS output format
precision?: number; // Default: 5 - Decimal precision for numbers
omitSourceMapUrl?: boolean; // Default: false - Disable source map URL in output
outFile?: string | null; // Default: null - Intended output file location
sourceComments?: boolean; // Default: false - Emit line number comments
// Source map options
sourceMap?: boolean | string; // Enable source map generation or specify location
sourceMapContents?: boolean; // Default: false - Include contents in source map
sourceMapEmbed?: boolean; // Default: false - Embed source map as data URI
sourceMapRoot?: string; // Source map root path
// Additional options allowed for sass-loader compatibility
[key: string]: any;
}Usage Examples:
// Comprehensive Sass options
{
resolve: `gatsby-plugin-sass`,
options: {
sassOptions: {
includePaths: ["src/styles", "node_modules/bootstrap/scss"],
outputStyle: "compressed",
precision: 8, // Useful for Bootstrap
sourceMap: true,
sourceComments: false,
functions: {
'get-theme()': () => {
return new sass.types.String(process.env.THEME || 'default');
}
}
},
},
}
// Bootstrap 4 configuration
{
resolve: `gatsby-plugin-sass`,
options: {
implementation: require('node-sass'),
sassOptions: {
precision: 6,
includePaths: ["node_modules/bootstrap/scss"],
},
postCssPlugins: [require('autoprefixer')],
},
}The plugin automatically processes files based on these patterns:
/\.s(a|c)ss$/ - Compiled to global CSS/\.module\.s(a|c)ss$/ - Compiled with CSS Modules enabledsassRuleTest and sassRuleModulesTestCommon configuration errors and solutions:
sass or node-sass as peer dependencyprecision: 6 for Bootstrap 4 or precision: 8 for Bootstrap 3useResolveUrlLoader for proper URL resolutionincludePaths in sassOptions for module resolution