0
# stylus-loader
1
2
stylus-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.
3
4
## Package Information
5
6
- **Package Name**: stylus-loader
7
- **Package Type**: npm
8
- **Language**: JavaScript
9
- **Installation**: `npm install stylus stylus-loader --save-dev`
10
11
## Core Imports
12
13
stylus-loader is a webpack loader, so it's not imported directly in your application code. Instead, it's configured in your webpack configuration:
14
15
```javascript
16
// webpack.config.js
17
module.exports = {
18
module: {
19
rules: [
20
{
21
test: /\.styl$/,
22
use: [
23
"style-loader",
24
"css-loader",
25
"stylus-loader"
26
]
27
}
28
]
29
}
30
};
31
```
32
33
For custom configuration:
34
35
```javascript
36
// webpack.config.js
37
module.exports = {
38
module: {
39
rules: [
40
{
41
test: /\.styl$/,
42
use: [
43
"style-loader",
44
"css-loader",
45
{
46
loader: "stylus-loader",
47
options: {
48
stylusOptions: {
49
use: ["nib"],
50
compress: true
51
}
52
}
53
}
54
]
55
}
56
]
57
}
58
};
59
```
60
61
## Basic Usage
62
63
1. Install the required dependencies:
64
65
```bash
66
npm install stylus stylus-loader css-loader style-loader --save-dev
67
```
68
69
2. Configure webpack to use stylus-loader:
70
71
```javascript
72
// webpack.config.js
73
module.exports = {
74
module: {
75
rules: [
76
{
77
test: /\.styl$/,
78
use: [
79
"style-loader", // creates style nodes from JS strings
80
"css-loader", // translates CSS into CommonJS
81
"stylus-loader" // compiles Stylus to CSS
82
]
83
}
84
]
85
}
86
};
87
```
88
89
3. Create and import Stylus files:
90
91
```stylus
92
// styles.styl
93
$primary = #ff6b6b
94
$secondary = #4ecdc4
95
96
.header
97
background-color $primary
98
color white
99
padding 20px
100
```
101
102
```javascript
103
// app.js
104
import './styles.styl';
105
```
106
107
## Architecture
108
109
stylus-loader implements a webpack-integrated Stylus compilation pipeline with several key components:
110
111
- **Loader Function**: Main async webpack loader that orchestrates the compilation process
112
- **Stylus Integration**: Direct integration with the Stylus compiler API, supporting all Stylus options
113
- **Webpack Importer**: Custom import resolver that enables webpack-style module resolution (@import from node_modules)
114
- **Source Map Processing**: Advanced source map generation and normalization for debugging support
115
- **Dependency Tracking**: Automatic dependency tracking for webpack's watch mode and incremental builds
116
- **Error Handling**: Comprehensive error reporting with file locations and webpack-compatible error formatting
117
118
The compilation flow:
119
1. Receives Stylus source code from webpack
120
2. Applies additionalData preprocessing if configured
121
3. Creates Stylus compiler instance with merged options
122
4. Configures webpack import resolver for node_modules support
123
5. Processes imports, includes, and dependencies
124
6. Compiles Stylus to CSS with source maps
125
7. Tracks all file dependencies for webpack watch mode
126
8. Returns compiled CSS and source maps to webpack
127
128
This architecture enables seamless integration with webpack's module system while preserving all Stylus features and providing robust development tooling support.
129
130
## Capabilities
131
132
### Loader Configuration
133
134
Configure stylus-loader behavior through webpack options.
135
136
```javascript { .api }
137
interface LoaderOptions {
138
implementation?: string | Function;
139
stylusOptions?: StylusOptions | ((loaderContext: LoaderContext) => StylusOptions);
140
sourceMap?: boolean;
141
webpackImporter?: boolean;
142
additionalData?: string | ((content: string, loaderContext: LoaderContext) => string | Promise<string>);
143
}
144
```
145
146
**Usage Example:**
147
148
```javascript
149
// webpack.config.js
150
module.exports = {
151
module: {
152
rules: [
153
{
154
test: /\.styl$/,
155
use: [
156
"style-loader",
157
"css-loader",
158
{
159
loader: "stylus-loader",
160
options: {
161
stylusOptions: {
162
use: ["nib"],
163
compress: true,
164
lineNumbers: true
165
},
166
sourceMap: true,
167
additionalData: `@env: ${process.env.NODE_ENV};`
168
}
169
}
170
]
171
}
172
]
173
}
174
};
175
```
176
177
### Stylus Options Configuration
178
179
Configure the underlying Stylus compiler through stylusOptions.
180
181
```javascript { .api }
182
interface StylusOptions {
183
use?: (string | Function)[];
184
include?: string[];
185
import?: string[];
186
define?: any[] | { [key: string]: any };
187
includeCSS?: boolean;
188
resolveURL?: boolean | URLResolverOptions;
189
lineNumbers?: boolean;
190
hoistAtrules?: boolean;
191
compress?: boolean;
192
disableCache?: boolean;
193
sourcemap?: boolean | SourceMapOptions;
194
paths?: string[];
195
}
196
197
interface URLResolverOptions {
198
nocheck?: boolean;
199
paths?: string[];
200
}
201
202
interface SourceMapOptions {
203
comment?: boolean;
204
sourceRoot?: string;
205
basePath?: string;
206
}
207
```
208
209
**Usage Example:**
210
211
```javascript
212
// webpack.config.js with comprehensive Stylus options
213
{
214
loader: "stylus-loader",
215
options: {
216
stylusOptions: {
217
// Use Stylus plugins (can be strings or functions)
218
use: ["nib", require("autoprefixer-stylus")()],
219
220
// Additional include paths for imports
221
include: [path.join(__dirname, "src/styles")],
222
223
// Files to automatically import
224
import: ["nib", "variables.styl"],
225
226
// Define variables (recommended array syntax)
227
define: [
228
["$development", process.env.NODE_ENV === "development"],
229
["$version", JSON.stringify(require("./package.json").version)]
230
],
231
232
// Include regular CSS on @import
233
includeCSS: false,
234
235
// Resolve relative url()'s inside imported files
236
resolveURL: true,
237
238
// Emit line number comments in generated CSS
239
lineNumbers: true,
240
241
// Move @import and @charset to the top
242
hoistAtrules: true,
243
244
// Compress CSS output (auto-enabled in production)
245
compress: process.env.NODE_ENV === "production",
246
247
// Disable Stylus caching for faster rebuilds in development
248
disableCache: process.env.NODE_ENV === "development"
249
}
250
}
251
}
252
```
253
254
### Source Map Support
255
256
Enable source map generation for debugging compiled Stylus code.
257
258
```javascript { .api }
259
interface SourceMapConfiguration {
260
sourceMap?: boolean;
261
}
262
```
263
264
**Usage Example:**
265
266
```javascript
267
// webpack.config.js with source maps
268
module.exports = {
269
devtool: "source-map",
270
module: {
271
rules: [
272
{
273
test: /\.styl$/,
274
use: [
275
"style-loader",
276
{
277
loader: "css-loader",
278
options: { sourceMap: true }
279
},
280
{
281
loader: "stylus-loader",
282
options: { sourceMap: true }
283
}
284
]
285
}
286
]
287
}
288
};
289
```
290
291
### Webpack Import Resolution
292
293
Control webpack-style import resolution for Stylus files.
294
295
```javascript { .api }
296
interface WebpackImporterConfiguration {
297
webpackImporter?: boolean;
298
}
299
```
300
301
With webpack importer enabled (default), you can import from node_modules:
302
303
```stylus
304
@import "bootstrap-styl/bootstrap/index.styl"
305
@import "~package-name/styles.styl" // ~ prefix (legacy, still supported)
306
```
307
308
**Usage Example:**
309
310
```javascript
311
// Disable webpack importer for performance
312
{
313
loader: "stylus-loader",
314
options: {
315
webpackImporter: false // Use only Stylus native resolution
316
}
317
}
318
```
319
320
### Additional Data Injection
321
322
Prepend data to Stylus files before compilation.
323
324
```javascript { .api }
325
interface AdditionalDataConfiguration {
326
additionalData?: string | AdditionalDataFunction;
327
}
328
329
type AdditionalDataFunction = (
330
content: string,
331
loaderContext: LoaderContext
332
) => string | Promise<string>;
333
334
interface LoaderContext {
335
resourcePath: string;
336
rootContext: string;
337
// ... other webpack loader context properties
338
}
339
```
340
341
**Usage Examples:**
342
343
```javascript
344
// String injection
345
{
346
loader: "stylus-loader",
347
options: {
348
additionalData: `@env: ${process.env.NODE_ENV};`
349
}
350
}
351
352
// Function injection (sync)
353
{
354
loader: "stylus-loader",
355
options: {
356
additionalData: (content, loaderContext) => {
357
const { resourcePath, rootContext } = loaderContext;
358
const relativePath = path.relative(rootContext, resourcePath);
359
360
if (relativePath.includes("admin")) {
361
return `@theme: admin;\n${content}`;
362
}
363
return `@theme: default;\n${content}`;
364
}
365
}
366
}
367
368
// Function injection (async)
369
{
370
loader: "stylus-loader",
371
options: {
372
additionalData: async (content, loaderContext) => {
373
const config = await loadConfig();
374
return `@config: ${JSON.stringify(config)};\n${content}`;
375
}
376
}
377
}
378
```
379
380
### Custom Stylus Implementation
381
382
Specify a custom Stylus implementation instead of the default.
383
384
```javascript { .api }
385
interface ImplementationConfiguration {
386
implementation?: string | Function;
387
}
388
```
389
390
**Usage Examples:**
391
392
```javascript
393
// Use specific Stylus version by package name
394
{
395
loader: "stylus-loader",
396
options: {
397
implementation: "stylus" // or "stylus-legacy", etc.
398
}
399
}
400
401
// Use specific Stylus instance
402
{
403
loader: "stylus-loader",
404
options: {
405
implementation: require("stylus")
406
}
407
}
408
409
// Use resolved path
410
{
411
loader: "stylus-loader",
412
options: {
413
implementation: require.resolve("stylus")
414
}
415
}
416
```
417
418
## Advanced Usage Patterns
419
420
### Using with Stylus Plugins
421
422
```javascript
423
// webpack.config.js with nib plugin
424
{
425
loader: "stylus-loader",
426
options: {
427
stylusOptions: {
428
use: [require("nib")()],
429
import: ["nib"]
430
}
431
}
432
}
433
```
434
435
```stylus
436
// Now you can use nib mixins
437
.box
438
border-radius 5px
439
gradient #fff #000
440
```
441
442
### Dynamic Configuration Based on Environment
443
444
```javascript
445
// webpack.config.js with environment-based config
446
{
447
loader: "stylus-loader",
448
options: {
449
stylusOptions: (loaderContext) => {
450
const isDev = loaderContext.mode === "development";
451
return {
452
compress: !isDev,
453
lineNumbers: isDev,
454
sourcemap: isDev,
455
use: isDev ? [] : ["autoprefixer-stylus"]
456
};
457
}
458
}
459
}
460
```
461
462
### Import Resolution with Paths
463
464
```javascript
465
// webpack.config.js with custom import paths
466
{
467
loader: "stylus-loader",
468
options: {
469
stylusOptions: {
470
paths: [
471
path.resolve(__dirname, "src/styles"),
472
path.resolve(__dirname, "node_modules")
473
]
474
}
475
}
476
}
477
```
478
479
```stylus
480
// Can now import from configured paths
481
@import "variables" // resolves to src/styles/variables.styl
482
@import "bootstrap" // resolves from node_modules
483
```
484
485
### Glob Pattern Imports
486
487
```stylus
488
// Import multiple files with glob patterns
489
@import "components/**/*.styl"
490
@import "mixins/*.styl"
491
```
492
493
## Common Configuration Examples
494
495
### Development Configuration
496
497
```javascript
498
// webpack.config.js for development
499
{
500
loader: "stylus-loader",
501
options: {
502
sourceMap: true,
503
stylusOptions: {
504
lineNumbers: true,
505
compress: false,
506
sourcemap: {
507
comment: true
508
}
509
}
510
}
511
}
512
```
513
514
### Production Configuration
515
516
```javascript
517
// webpack.config.js for production
518
{
519
loader: "stylus-loader",
520
options: {
521
stylusOptions: {
522
compress: true,
523
hoistAtrules: true,
524
resolveURL: true
525
}
526
}
527
}
528
```
529
530
### Library Development Configuration
531
532
```javascript
533
// webpack.config.js for library development
534
{
535
loader: "stylus-loader",
536
options: {
537
stylusOptions: {
538
use: ["nib"],
539
include: [path.resolve(__dirname, "src/lib")],
540
define: [
541
["$library-version", JSON.stringify(require("./package.json").version)]
542
]
543
}
544
}
545
}
546
```
547
548
## Error Handling
549
550
stylus-loader provides detailed error messages for common issues:
551
552
- **Stylus Compilation Errors**: Syntax errors in Stylus files with file location and line numbers
553
- **Import Resolution Errors**: Missing files or incorrect import paths, including module resolution failures
554
- **Plugin Loading Errors**: Issues loading Stylus plugins specified in `use` option via require.resolve()
555
- **Implementation Errors**: Problems with custom Stylus implementation (e.g., "The Stylus implementation 'xyz' not found")
556
- **Glob Resolution Errors**: Invalid glob patterns in imports (e.g., "Glob resolving without a glob base is not supported")
557
- **File System Errors**: Issues reading imported files or source maps during compilation
558
- **Parser Errors**: Stylus AST parsing errors that prevent dependency analysis
559
560
Errors include webpack-style error reporting with:
561
- File paths and line numbers for precise error location
562
- Detailed error descriptions with context
563
- Automatic dependency tracking for failed imports
564
- Stack trace preservation from underlying Stylus compiler
565
- Resolution suggestions where applicable
566
567
Common error scenarios:
568
- Missing `@import` files: Check file paths and ensure files exist
569
- Plugin loading failures: Verify plugin names and installation
570
- Glob import issues: Use proper glob base syntax (`~package/**/*` not `~**/*`)
571
- Custom implementation not found: Ensure implementation package is installed
572
573
## Version Compatibility
574
575
- **Node.js**: >= 18.12.0
576
- **webpack**: ^5.0.0
577
- **Stylus**: >= 0.52.4
578
- **@rspack/core**: 0.x || 1.x (optional alternative to webpack)
579
580
## Types
581
582
```typescript { .api }
583
interface LoaderContext {
584
resourcePath: string;
585
rootContext: string;
586
mode: string;
587
sourceMap: boolean;
588
getOptions: (schema?: object) => LoaderOptions;
589
async: () => (error: Error | null, content?: string, sourceMap?: object) => void;
590
addDependency: (file: string) => void;
591
addContextDependency: (context: string) => void;
592
addBuildDependency: (file: string) => void;
593
emitError: (error: Error) => void;
594
fs: object;
595
}
596
597
interface LoaderOptions {
598
implementation?: string | Function;
599
stylusOptions?: StylusOptions | ((loaderContext: LoaderContext) => StylusOptions);
600
sourceMap?: boolean;
601
webpackImporter?: boolean;
602
additionalData?: string | ((content: string, loaderContext: LoaderContext) => string | Promise<string>);
603
}
604
605
interface StylusOptions {
606
use?: (string | Function)[];
607
include?: string[];
608
import?: string[];
609
define?: any[] | { [key: string]: any };
610
includeCSS?: boolean;
611
resolveURL?: boolean | URLResolverOptions;
612
lineNumbers?: boolean;
613
hoistAtrules?: boolean;
614
compress?: boolean;
615
disableCache?: boolean;
616
sourcemap?: boolean | SourceMapOptions;
617
paths?: string[];
618
filename?: string;
619
dest?: string;
620
}
621
622
interface URLResolverOptions {
623
nocheck?: boolean;
624
paths?: string[];
625
}
626
627
interface SourceMapOptions {
628
comment?: boolean;
629
sourceRoot?: string;
630
basePath?: string;
631
}
632
```