Webpack loader for compiling Stylus CSS preprocessor files into regular CSS
npx @tessl/cli install tessl/npm-stylus-loader@8.1.0stylus-loader is a webpack loader that compiles Stylus CSS preprocessor files into regular CSS. It provides comprehensive webpack integration with configurable options for Stylus compilation, import resolution, source maps, and plugin support.
npm install stylus stylus-loader --save-devstylus-loader is a webpack loader, so it's not imported directly in your application code. Instead, it's configured in your webpack configuration:
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/,
use: [
"style-loader",
"css-loader",
"stylus-loader"
]
}
]
}
};For custom configuration:
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/,
use: [
"style-loader",
"css-loader",
{
loader: "stylus-loader",
options: {
stylusOptions: {
use: ["nib"],
compress: true
}
}
}
]
}
]
}
};npm install stylus stylus-loader css-loader style-loader --save-dev// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/,
use: [
"style-loader", // creates style nodes from JS strings
"css-loader", // translates CSS into CommonJS
"stylus-loader" // compiles Stylus to CSS
]
}
]
}
};// styles.styl
$primary = #ff6b6b
$secondary = #4ecdc4
.header
background-color $primary
color white
padding 20px// app.js
import './styles.styl';stylus-loader implements a webpack-integrated Stylus compilation pipeline with several key components:
The compilation flow:
This architecture enables seamless integration with webpack's module system while preserving all Stylus features and providing robust development tooling support.
Configure stylus-loader behavior through webpack options.
interface LoaderOptions {
implementation?: string | Function;
stylusOptions?: StylusOptions | ((loaderContext: LoaderContext) => StylusOptions);
sourceMap?: boolean;
webpackImporter?: boolean;
additionalData?: string | ((content: string, loaderContext: LoaderContext) => string | Promise<string>);
}Usage Example:
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/,
use: [
"style-loader",
"css-loader",
{
loader: "stylus-loader",
options: {
stylusOptions: {
use: ["nib"],
compress: true,
lineNumbers: true
},
sourceMap: true,
additionalData: `@env: ${process.env.NODE_ENV};`
}
}
]
}
]
}
};Configure the underlying Stylus compiler through stylusOptions.
interface StylusOptions {
use?: (string | Function)[];
include?: string[];
import?: string[];
define?: any[] | { [key: string]: any };
includeCSS?: boolean;
resolveURL?: boolean | URLResolverOptions;
lineNumbers?: boolean;
hoistAtrules?: boolean;
compress?: boolean;
disableCache?: boolean;
sourcemap?: boolean | SourceMapOptions;
paths?: string[];
}
interface URLResolverOptions {
nocheck?: boolean;
paths?: string[];
}
interface SourceMapOptions {
comment?: boolean;
sourceRoot?: string;
basePath?: string;
}Usage Example:
// webpack.config.js with comprehensive Stylus options
{
loader: "stylus-loader",
options: {
stylusOptions: {
// Use Stylus plugins (can be strings or functions)
use: ["nib", require("autoprefixer-stylus")()],
// Additional include paths for imports
include: [path.join(__dirname, "src/styles")],
// Files to automatically import
import: ["nib", "variables.styl"],
// Define variables (recommended array syntax)
define: [
["$development", process.env.NODE_ENV === "development"],
["$version", JSON.stringify(require("./package.json").version)]
],
// Include regular CSS on @import
includeCSS: false,
// Resolve relative url()'s inside imported files
resolveURL: true,
// Emit line number comments in generated CSS
lineNumbers: true,
// Move @import and @charset to the top
hoistAtrules: true,
// Compress CSS output (auto-enabled in production)
compress: process.env.NODE_ENV === "production",
// Disable Stylus caching for faster rebuilds in development
disableCache: process.env.NODE_ENV === "development"
}
}
}Enable source map generation for debugging compiled Stylus code.
interface SourceMapConfiguration {
sourceMap?: boolean;
}Usage Example:
// webpack.config.js with source maps
module.exports = {
devtool: "source-map",
module: {
rules: [
{
test: /\.styl$/,
use: [
"style-loader",
{
loader: "css-loader",
options: { sourceMap: true }
},
{
loader: "stylus-loader",
options: { sourceMap: true }
}
]
}
]
}
};Control webpack-style import resolution for Stylus files.
interface WebpackImporterConfiguration {
webpackImporter?: boolean;
}With webpack importer enabled (default), you can import from node_modules:
@import "bootstrap-styl/bootstrap/index.styl"
@import "~package-name/styles.styl" // ~ prefix (legacy, still supported)Usage Example:
// Disable webpack importer for performance
{
loader: "stylus-loader",
options: {
webpackImporter: false // Use only Stylus native resolution
}
}Prepend data to Stylus files before compilation.
interface AdditionalDataConfiguration {
additionalData?: string | AdditionalDataFunction;
}
type AdditionalDataFunction = (
content: string,
loaderContext: LoaderContext
) => string | Promise<string>;
interface LoaderContext {
resourcePath: string;
rootContext: string;
// ... other webpack loader context properties
}Usage Examples:
// String injection
{
loader: "stylus-loader",
options: {
additionalData: `@env: ${process.env.NODE_ENV};`
}
}
// Function injection (sync)
{
loader: "stylus-loader",
options: {
additionalData: (content, loaderContext) => {
const { resourcePath, rootContext } = loaderContext;
const relativePath = path.relative(rootContext, resourcePath);
if (relativePath.includes("admin")) {
return `@theme: admin;\n${content}`;
}
return `@theme: default;\n${content}`;
}
}
}
// Function injection (async)
{
loader: "stylus-loader",
options: {
additionalData: async (content, loaderContext) => {
const config = await loadConfig();
return `@config: ${JSON.stringify(config)};\n${content}`;
}
}
}Specify a custom Stylus implementation instead of the default.
interface ImplementationConfiguration {
implementation?: string | Function;
}Usage Examples:
// Use specific Stylus version by package name
{
loader: "stylus-loader",
options: {
implementation: "stylus" // or "stylus-legacy", etc.
}
}
// Use specific Stylus instance
{
loader: "stylus-loader",
options: {
implementation: require("stylus")
}
}
// Use resolved path
{
loader: "stylus-loader",
options: {
implementation: require.resolve("stylus")
}
}// webpack.config.js with nib plugin
{
loader: "stylus-loader",
options: {
stylusOptions: {
use: [require("nib")()],
import: ["nib"]
}
}
}// Now you can use nib mixins
.box
border-radius 5px
gradient #fff #000// webpack.config.js with environment-based config
{
loader: "stylus-loader",
options: {
stylusOptions: (loaderContext) => {
const isDev = loaderContext.mode === "development";
return {
compress: !isDev,
lineNumbers: isDev,
sourcemap: isDev,
use: isDev ? [] : ["autoprefixer-stylus"]
};
}
}
}// webpack.config.js with custom import paths
{
loader: "stylus-loader",
options: {
stylusOptions: {
paths: [
path.resolve(__dirname, "src/styles"),
path.resolve(__dirname, "node_modules")
]
}
}
}// Can now import from configured paths
@import "variables" // resolves to src/styles/variables.styl
@import "bootstrap" // resolves from node_modules// Import multiple files with glob patterns
@import "components/**/*.styl"
@import "mixins/*.styl"// webpack.config.js for development
{
loader: "stylus-loader",
options: {
sourceMap: true,
stylusOptions: {
lineNumbers: true,
compress: false,
sourcemap: {
comment: true
}
}
}
}// webpack.config.js for production
{
loader: "stylus-loader",
options: {
stylusOptions: {
compress: true,
hoistAtrules: true,
resolveURL: true
}
}
}// webpack.config.js for library development
{
loader: "stylus-loader",
options: {
stylusOptions: {
use: ["nib"],
include: [path.resolve(__dirname, "src/lib")],
define: [
["$library-version", JSON.stringify(require("./package.json").version)]
]
}
}
}stylus-loader provides detailed error messages for common issues:
use option via require.resolve()Errors include webpack-style error reporting with:
Common error scenarios:
@import files: Check file paths and ensure files exist~package/**/* not ~**/*)interface LoaderContext {
resourcePath: string;
rootContext: string;
mode: string;
sourceMap: boolean;
getOptions: (schema?: object) => LoaderOptions;
async: () => (error: Error | null, content?: string, sourceMap?: object) => void;
addDependency: (file: string) => void;
addContextDependency: (context: string) => void;
addBuildDependency: (file: string) => void;
emitError: (error: Error) => void;
fs: object;
}
interface LoaderOptions {
implementation?: string | Function;
stylusOptions?: StylusOptions | ((loaderContext: LoaderContext) => StylusOptions);
sourceMap?: boolean;
webpackImporter?: boolean;
additionalData?: string | ((content: string, loaderContext: LoaderContext) => string | Promise<string>);
}
interface StylusOptions {
use?: (string | Function)[];
include?: string[];
import?: string[];
define?: any[] | { [key: string]: any };
includeCSS?: boolean;
resolveURL?: boolean | URLResolverOptions;
lineNumbers?: boolean;
hoistAtrules?: boolean;
compress?: boolean;
disableCache?: boolean;
sourcemap?: boolean | SourceMapOptions;
paths?: string[];
filename?: string;
dest?: string;
}
interface URLResolverOptions {
nocheck?: boolean;
paths?: string[];
}
interface SourceMapOptions {
comment?: boolean;
sourceRoot?: string;
basePath?: string;
}