UNPKG

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