UNPKG

18.2 kBMarkdownView Raw
1<div align="center">
2 <a href="https://github.com/webpack/webpack">
3 <img width="200" height="200" src="https://webpack.js.org/assets/icon-square-big.svg">
4 </a>
5</div>
6
7[![npm][npm]][npm-url]
8[![node][node]][node-url]
9[![deps][deps]][deps-url]
10[![tests][tests]][tests-url]
11[![cover][cover]][cover-url]
12[![chat][chat]][chat-url]
13[![size][size]][size-url]
14
15# stylus-loader
16
17A Stylus loader for webpack. Compiles Styl to CSS.
18
19## Getting Started
20
21To begin, you'll need to install `stylus` and `stylus-loader`:
22
23```console
24npm install stylus stylus-loader --save-dev
25```
26
27or
28
29```console
30yarn add -D stylus stylus-loader
31```
32
33or
34
35````console
36pnpm add -D stylus stylus-loader
37
38Then add the loader to your `webpack` config. For example:
39
40**webpack.config.js**
41
42```js
43module.exports = {
44 module: {
45 rules: [
46 {
47 test: /\.styl$/,
48 loader: "stylus-loader", // compiles Styl to CSS
49 },
50 ],
51 },
52};
53````
54
55And run `webpack` via your preferred method.
56
57## Options
58
59- **[`stylusOptions`](#stylusOptions)**
60- **[`sourceMap`](#sourcemap)**
61- **[`webpackImporter`](#webpackimporter)**
62- **[`additionalData`](#additionalData)**
63- **[`implementation`](#implementation)**
64
65### `stylusOptions`
66
67Type:
68
69```ts
70type stylusOptions =
71 | {
72 use: Array<string | Function>;
73 include: string;
74 import: string;
75 define: Array;
76 includeCSS: false;
77 resolveURL: boolean | Object;
78 lineNumbers: boolean;
79 hoistAtrules: boolean;
80 compress: boolean;
81 }
82 | (loaderContext: LoaderContext) => Array<string>;
83```
84
85Default: `{}`
86
87You can pass any Stylus specific options to the `stylus-loader` through the `stylusOptions` property in the [loader options](https://webpack.js.org/configuration/module/#rule-options-rule-query).
88See the [Stylus documentation](https://stylus-lang.com/docs/js.html).
89Options in dash-case should use camelCase.
90
91#### `object`
92
93Use an object to pass options through to Stylus.
94
95**webpack.config.js**
96
97```js
98module.exports = {
99 module: {
100 rules: [
101 {
102 test: /\.styl$/,
103 use: [
104 {
105 loader: "style-loader",
106 },
107 {
108 loader: "css-loader",
109 },
110 {
111 loader: "stylus-loader",
112 options: {
113 stylusOptions: {
114 /**
115 * Specify Stylus plugins to use. Plugins may be passed as
116 * strings instead of importing them in your Webpack config.
117 *
118 * @type {(string|Function)[]}
119 * @default []
120 */
121 use: ["nib"],
122
123 /**
124 * Add path(s) to the import lookup paths.
125 *
126 * @type {string[]}
127 * @default []
128 */
129 include: [path.join(__dirname, "src/styl/config")],
130
131 /**
132 * Import the specified Stylus files/paths.
133 *
134 * @type {string[]}
135 * @default []
136 */
137 import: ["nib", path.join(__dirname, "src/styl/mixins")],
138
139 /**
140 * Define Stylus variables or functions.
141 *
142 * @type {Array|Object}
143 * @default {}
144 */
145 // Array is the recommended syntax: [key, value, raw]
146 define: [
147 ["$development", process.env.NODE_ENV === "development"],
148 ["rawVar", 42, true],
149 ],
150 // Object is deprecated syntax (there is no possibility to specify "raw')
151 // define: {
152 // $development: process.env.NODE_ENV === 'development',
153 // rawVar: 42,
154 // },
155
156 /**
157 * Include regular CSS on @import.
158 *
159 * @type {boolean}
160 * @default false
161 */
162 includeCSS: false,
163
164 /**
165 * Resolve relative url()'s inside imported files.
166 *
167 * @see https://stylus-lang.com/docs/js.html#stylusresolveroptions
168 *
169 * @type {boolean|Object}
170 * @default { nocheck: true }
171 */
172 resolveURL: true,
173 // resolveURL: { nocheck: true },
174
175 /**
176 * Emits comments in the generated CSS indicating the corresponding Stylus line.
177 *
178 * @see https://stylus-lang.com/docs/executable.html
179 *
180 * @type {boolean}
181 * @default false
182 */
183 lineNumbers: true,
184
185 /**
186 * Move @import and @charset to the top.
187 *
188 * @see https://stylus-lang.com/docs/executable.html
189 *
190 * @type {boolean}
191 * @default false
192 */
193 hoistAtrules: true,
194
195 /**
196 * Compress CSS output.
197 * In the "production" mode is `true` by default
198 *
199 * @see https://stylus-lang.com/docs/executable.html
200 *
201 * @type {boolean}
202 * @default false
203 */
204 compress: true,
205 },
206 },
207 },
208 ],
209 },
210 ],
211 },
212};
213```
214
215#### `function`
216
217Allows setting the options passed through to Stylus based off of the loader context.
218
219```js
220module.exports = {
221 module: {
222 rules: [
223 {
224 test: /\.styl/,
225 use: [
226 "style-loader",
227 "css-loader",
228 {
229 loader: "stylus-loader",
230 options: {
231 stylusOptions: (loaderContext) => {
232 // More information about available properties https://webpack.js.org/api/loaders/
233 const { resourcePath, rootContext } = loaderContext;
234 const relativePath = path.relative(rootContext, resourcePath);
235
236 if (relativePath === "styles/foo.styl") {
237 return {
238 paths: ["absolute/path/c", "absolute/path/d"],
239 };
240 }
241
242 return {
243 paths: ["absolute/path/a", "absolute/path/b"],
244 };
245 },
246 },
247 },
248 ],
249 },
250 ],
251 },
252};
253```
254
255### `sourceMap`
256
257Type:
258
259```ts
260type sourceMap = boolean;
261```
262
263**webpack.config.js**
264
265```js
266module.exports = {
267 module: {
268 rules: [
269 {
270 test: /\.styl$/i,
271 use: [
272 "style-loader",
273 {
274 loader: "css-loader",
275 options: {
276 sourceMap: true,
277 },
278 },
279 {
280 loader: "stylus-loader",
281 options: {
282 sourceMap: true,
283 },
284 },
285 ],
286 },
287 ],
288 },
289};
290```
291
292### `webpackImporter`
293
294Type:
295
296```ts
297type webpackImporter = boolean;
298```
299
300Default: `true`
301
302Enables/Disables the default Webpack importer.
303
304This can improve performance in some cases.
305Use it with caution because aliases and `@import` at-rules starting with `~` will not work.
306
307**webpack.config.js**
308
309```js
310module.exports = {
311 module: {
312 rules: [
313 {
314 test: /\.styl/i,
315 use: [
316 "style-loader",
317 "css-loader",
318 {
319 loader: "stylus-loader",
320 options: {
321 webpackImporter: false,
322 },
323 },
324 ],
325 },
326 ],
327 },
328};
329```
330
331### `additionalData`
332
333Type:
334
335```ts
336type additionalData =
337 | string
338 | (
339 content: string | Buffer,
340 loaderContext: LoaderContext,
341 meta: any
342 ) => string;
343```
344
345Default: `undefined`
346
347Prepends `Stylus` code before the actual entry file.
348In this case, the `stylus-loader` will not override the source but just **prepend** the entry's content.
349
350This is especially useful when some of your Stylus variables depend on the environment:
351
352> ℹ Since you're injecting code, this will break the source mappings in your entry file. Often there's a simpler solution than this, like multiple Stylus entry files.
353
354#### `string`
355
356```js
357module.exports = {
358 module: {
359 rules: [
360 {
361 test: /\.styl/,
362 use: [
363 "style-loader",
364 "css-loader",
365 {
366 loader: "stylus-loader",
367 options: {
368 additionalData: `@env: ${process.env.NODE_ENV};`,
369 },
370 },
371 ],
372 },
373 ],
374 },
375};
376```
377
378#### `function`
379
380##### Sync
381
382```js
383module.exports = {
384 module: {
385 rules: [
386 {
387 test: /\.styl/,
388 use: [
389 "style-loader",
390 "css-loader",
391 {
392 loader: "stylus-loader",
393 options: {
394 additionalData: (content, loaderContext) => {
395 // More information about available properties https://webpack.js.org/api/loaders/
396 const { resourcePath, rootContext } = loaderContext;
397 const relativePath = path.relative(rootContext, resourcePath);
398
399 if (relativePath === "styles/foo.styl") {
400 return "value = 100px" + content;
401 }
402
403 return "value 200px" + content;
404 },
405 },
406 },
407 ],
408 },
409 ],
410 },
411};
412```
413
414##### Async
415
416```js
417module.exports = {
418 module: {
419 rules: [
420 {
421 test: /\.styl/,
422 use: [
423 "style-loader",
424 "css-loader",
425 {
426 loader: "stylus-loader",
427 options: {
428 additionalData: async (content, loaderContext) => {
429 // More information about available properties https://webpack.js.org/api/loaders/
430 const { resourcePath, rootContext } = loaderContext;
431 const relativePath = path.relative(rootContext, resourcePath);
432
433 if (relativePath === "styles/foo.styl") {
434 return "value = 100px" + content;
435 }
436
437 return "value 200px" + content;
438 },
439 },
440 },
441 ],
442 },
443 ],
444 },
445};
446```
447
448### `implementation`
449
450Type:
451
452```ts
453type implementation = Function | string;
454```
455
456The special `implementation` option determines which implementation of Stylus to use. Overrides the locally installed `peerDependency` version of `stylus`.
457
458#### `function`
459
460**webpack.config.js**
461
462```js
463module.exports = {
464 module: {
465 rules: [
466 {
467 test: /\.styl/i,
468 use: [
469 "style-loader",
470 "css-loader",
471 {
472 loader: "stylus-loader",
473 options: {
474 implementation: require("stylus"),
475 },
476 },
477 ],
478 },
479 ],
480 },
481};
482```
483
484#### `string`
485
486**webpack.config.js**
487
488```js
489module.exports = {
490 module: {
491 rules: [
492 {
493 test: /\.styl/i,
494 use: [
495 "style-loader",
496 "css-loader",
497 {
498 loader: "stylus-loader",
499 options: {
500 implementation: require.resolve("stylus"),
501 },
502 },
503 ],
504 },
505 ],
506 },
507};
508```
509
510## Examples
511
512### Normal usage
513
514Chain the `stylus-loader` with the [`css-loader`](https://github.com/webpack-contrib/css-loader) and the [`style-loader`](https://github.com/webpack-contrib/style-loader) to immediately apply all styles to the DOM.
515
516**webpack.config.js**
517
518```js
519module.exports = {
520 module: {
521 rules: [
522 {
523 test: /\.styl$/,
524 use: [
525 {
526 loader: "style-loader", // creates style nodes from JS strings
527 },
528 {
529 loader: "css-loader", // translates CSS into CommonJS
530 },
531 {
532 loader: "stylus-loader", // compiles Stylus to CSS
533 },
534 ],
535 },
536 ],
537 },
538};
539```
540
541### Source maps
542
543To enable sourcemaps for CSS, you'll need to pass the `sourceMap` property in the loader's options. If this is not passed, the loader will respect the setting for webpack source maps, set in `devtool`.
544
545**webpack.config.js**
546
547```javascript
548module.exports = {
549 devtool: "source-map", // any "source-map"-like devtool is possible
550 module: {
551 rules: [
552 {
553 test: /\.styl$/,
554 use: [
555 "style-loader",
556 {
557 loader: "css-loader",
558 options: {
559 sourceMap: true,
560 },
561 },
562 {
563 loader: "stylus-loader",
564 options: {
565 sourceMap: true,
566 },
567 },
568 ],
569 },
570 ],
571 },
572};
573```
574
575### Using nib with stylus
576
577**webpack.config.js**
578
579```js
580module.exports = {
581 module: {
582 rules: [
583 {
584 test: /\.styl$/,
585 use: [
586 {
587 loader: "style-loader", // creates style nodes from JS strings
588 },
589 {
590 loader: "css-loader", // translates CSS into CommonJS
591 },
592 {
593 loader: "stylus-loader", // compiles Stylus to CSS
594 options: {
595 stylusOptions: {
596 use: [require("nib")()],
597 import: ["nib"],
598 },
599 },
600 },
601 ],
602 },
603 ],
604 },
605};
606```
607
608### Import JSON files
609
610Stylus does not provide resolving capabilities in the `json` function.
611Therefore webpack resolver does not work for `.json` files.
612Use [`stylus resolver`](#stylus-resolver).
613
614**index.styl**
615
616```styl
617// Suppose the file is located here `node_modules/vars/vars.json`
618json('vars.json')
619
620@media queries-small
621 body
622 display nope
623
624```
625
626**webpack.config.js**
627
628```js
629module.exports = {
630 module: {
631 rules: [
632 {
633 test: /\.styl$/,
634 use: [
635 "style-loader",
636 "css-loader",
637 {
638 loader: "stylus-loader",
639 options: {
640 stylusOptions: {
641 // Specify the path. where to find files
642 paths: ["node_modules/vars"],
643 },
644 },
645 },
646 ],
647 },
648 ],
649 },
650};
651```
652
653### In production
654
655Usually, it's recommended to extract the style sheets into a dedicated file in production using the [MiniCssExtractPlugin](https://github.com/webpack-contrib/mini-css-extract-plugin). This way your styles are not dependent on JavaScript.
656
657### webpack resolver
658
659Webpack provides an [advanced mechanism to resolve files](https://webpack.js.org/configuration/resolve/).
660The `stylus-loader` applies the webpack resolver when processing queries.
661Thus you can import your Stylus modules from `node_modules`.
662
663```styl
664@import 'bootstrap-styl/bootstrap/index.styl';
665```
666
667Using `~` is deprecated and can be removed from your code (**we recommend it**), but we still support it for historical reasons.
668Why you can removed it? The loader will first try to resolve `@import`/`@require` as relative, if it cannot be resolved, the loader will try to resolve `@import`/`@require` inside [`node_modules`](https://webpack.js.org/configuration/resolve/#resolve-modules).
669Just prepend them with a `~` which tells webpack to look up the [`modules`](https://webpack.js.org/configuration/resolve/#resolve-modules).
670
671```styl
672@import "~bootstrap-styl/bootstrap/index.styl";
673```
674
675It's important to only prepend it with `~`, because `~/` resolves to the home-directory.
676Webpack needs to distinguish between `bootstrap` and `~bootstrap`, because CSS and Styl files have no special syntax for importing relative files.
677Writing `@import "file"` is the same as `@import "./file";`
678
679### Stylus resolver
680
681If you specify the `paths` option, modules will be searched in the given `paths`.
682This is Stylus default behavior.
683
684**webpack.config.js**
685
686```js
687module.exports = {
688 module: {
689 rules: [
690 {
691 test: /\.styl/,
692 use: [
693 {
694 loader: "style-loader",
695 },
696 {
697 loader: "css-loader",
698 },
699 {
700 loader: "stylus-loader",
701 options: {
702 stylusOptions: {
703 paths: [path.resolve(__dirname, "node_modules")],
704 },
705 },
706 },
707 ],
708 },
709 ],
710 },
711};
712```
713
714### Extracting style sheets
715
716Bundling CSS with webpack has some nice advantages like referencing images and fonts with hashed urls or [hot module replacement](https://webpack.js.org/concepts/hot-module-replacement/) in development. In production, on the other hand, it's not a good idea to apply your style sheets depending on JS execution. Rendering may be delayed or even a [FOUC](https://en.wikipedia.org/wiki/Flash_of_unstyled_content) might be visible. Thus it's often still better to have them as separate files in your final production build.
717
718There are two possibilities to extract a style sheet from the bundle:
719
720- [`extract-loader`](https://github.com/peerigon/extract-loader) (simpler, but specialized on the css-loader's output)
721- [MiniCssExtractPlugin](https://github.com/webpack-contrib/mini-css-extract-plugin) (more complex, but works in all use-cases)
722
723## Contributing
724
725Please take a moment to read our contributing guidelines if you haven't yet done so.
726
727[CONTRIBUTING](./.github/CONTRIBUTING.md)
728
729## License
730
731[MIT](./LICENSE)
732
733[npm]: https://img.shields.io/npm/v/stylus-loader.svg
734[npm-url]: https://npmjs.com/package/stylus-loader
735[node]: https://img.shields.io/node/v/stylus-loader.svg
736[node-url]: https://nodejs.org
737[deps]: https://david-dm.org/webpack-contrib/stylus-loader.svg
738[deps-url]: https://david-dm.org/webpack-contrib/stylus-loader
739[tests]: https://github.com/webpack-contrib/stylus-loader/workflows/stylus-loader/badge.svg
740[tests-url]: https://github.com/webpack-contrib/stylus-loader/actions
741[cover]: https://codecov.io/gh/webpack-contrib/stylus-loader/branch/master/graph/badge.svg
742[cover-url]: https://codecov.io/gh/webpack-contrib/stylus-loader
743[chat]: https://img.shields.io/badge/gitter-webpack%2Fwebpack-brightgreen.svg
744[chat-url]: https://gitter.im/webpack/webpack
745[size]: https://packagephobia.now.sh/badge?p=stylus-loader
746[size-url]: https://packagephobia.now.sh/result?p=stylus-loader