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 |
|
17 | A Stylus loader for webpack. Compiles Styl to CSS.
|
18 |
|
19 | ## Getting Started
|
20 |
|
21 | To begin, you'll need to install `stylus` and `stylus-loader`:
|
22 |
|
23 | ```console
|
24 | $ npm install stylus stylus-loader --save-dev
|
25 | ```
|
26 |
|
27 | Then add the loader to your `webpack` config. For example:
|
28 |
|
29 | **webpack.config.js**
|
30 |
|
31 | ```js
|
32 | module.exports = {
|
33 | module: {
|
34 | rules: [
|
35 | {
|
36 | test: /\.styl$/,
|
37 | loader: "stylus-loader", // compiles Styl to CSS
|
38 | },
|
39 | ],
|
40 | },
|
41 | };
|
42 | ```
|
43 |
|
44 | And 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 |
|
57 | Type: `Object|Function`
|
58 | Default: `{}`
|
59 |
|
60 | You 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).
|
61 | See the [Stylus documentation](https://stylus-lang.com/docs/js.html).
|
62 | Options in dash-case should use camelCase.
|
63 |
|
64 | #### `Object`
|
65 |
|
66 | Use an object to pass options through to Stylus.
|
67 |
|
68 | **webpack.config.js**
|
69 |
|
70 | ```js
|
71 | module.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 |
|
190 | Allows setting the options passed through to Stylus based off of the loader context.
|
191 |
|
192 | ```js
|
193 | module.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 |
|
230 | Type: `Boolean`
|
231 |
|
232 | **webpack.config.js**
|
233 |
|
234 | ```js
|
235 | module.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 |
|
263 | Type: `Boolean`
|
264 | Default: `true`
|
265 |
|
266 | Enables/Disables the default Webpack importer.
|
267 |
|
268 | This can improve performance in some cases.
|
269 | Use it with caution because aliases and `@import` at-rules starting with `~` will not work.
|
270 |
|
271 | **webpack.config.js**
|
272 |
|
273 | ```js
|
274 | module.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 |
|
297 | Type: `String|Function`
|
298 | Default: `undefined`
|
299 |
|
300 | Prepends `Stylus` code before the actual entry file.
|
301 | In this case, the `stylus-loader` will not override the source but just **prepend** the entry's content.
|
302 |
|
303 | This 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
|
310 | module.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
|
336 | module.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
|
370 | module.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 |
|
405 | Chain 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
|
410 | module.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 |
|
434 | To 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
|
439 | module.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
|
471 | module.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 |
|
501 | Stylus does not provide resolving capabilities in the `json` function.
|
502 | Therefore webpack resolver does not work for `.json` files.
|
503 | Use [`stylus resolver`](#stylus-resolver).
|
504 |
|
505 | **index.styl**
|
506 |
|
507 | ```styl
|
508 | // Suppose the file is located here `node_modules/vars/vars.json`
|
509 | json('vars.json')
|
510 |
|
511 | @media queries-small
|
512 | body
|
513 | display nope
|
514 |
|
515 | ```
|
516 |
|
517 | **webpack.config.js**
|
518 |
|
519 | ```js
|
520 | module.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 |
|
546 | Usually, 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 |
|
550 | Webpack provides an [advanced mechanism to resolve files](https://webpack.js.org/configuration/resolve/).
|
551 | The `stylus-loader` applies the webpack resolver when processing queries.
|
552 | Thus you can import your Stylus modules from `node_modules`.
|
553 | Just 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 |
|
559 | It's important to only prepend it with `~`, because `~/` resolves to the home-directory.
|
560 | Webpack needs to distinguish between `bootstrap` and `~bootstrap`, because CSS and Styl files have no special syntax for importing relative files.
|
561 | Writing `@import "file"` is the same as `@import "./file";`
|
562 |
|
563 | ### Stylus resolver
|
564 |
|
565 | If you specify the `paths` option, modules will be searched in the given `paths`.
|
566 | This is Stylus default behavior.
|
567 |
|
568 | **webpack.config.js**
|
569 |
|
570 | ```js
|
571 | module.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 |
|
600 | Bundling 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 |
|
602 | There 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 |
|
609 | Please 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
|