stylus-loader (which inherits a lot of behavior from Stylus itself),
relative path imports like
./color, don't necessarily
resolve to the path relative to the file in which the import is found. In fact,
they have the same meaning as just importing
color. This means
the paths are resolved using the Stylus "context" – in effect, you could get the
file at the requested relative path, a file in some ancestor directory, a node
module, or a file that happens to have the same name within another module.
styles ├── a │ ├── color.styl │ └── index.styl ├── b │ ├── color.styl │ └── index.styl ├── color.styl └── index.styl
@import './a';@import './b';@import './color';
b/index.styl both contain:
stylus-loader, the output would be ONLY the contents of
styles/color.styl, repeated 3 times. Despite the
./color imports in
b explicitly calling for
b/color.styl to be included,
they won't be – merely because another relative path was imported with the
If you're using very modularized styles (say, some of your imports come from
node_modules) this behavior can spell big trouble. You basically have to
ensure that all Stylus filenames in your dependency tree are unique, otherwise
some styles/variables/mixins might go missing!
stylus-relative-loader fixes this issue by patching relative imports to all
resolve as if they were full absolute paths. That means you'd get all of
stylus-relative-loader supports dynamic imports, such as those in conditional
branches or with
$variable interpolation in the path.
stylus-loader does not
support these and sometimes emits confusing error messages as a result.
This is possible because the static import analysis step in
stylus-relative-loader exists purely to increase performance, and is not a
requirement for import resolution like it is in
stylus-loader. Our general
strategy is to invoke the Stylus renderer, and when any "unresolved" imports are
encountered, we stop rendering, resolved any queued up imports, then try
rendering again from the beginning. This makes
stylus-loader if you have many dynamic imports, but has the benefit of
correctness. Be careful if you have Stylus plugins with expensive side-effects.
precacheImportVariables query option
If you are using the above dynamic import feature and have a lot of Stylus imports, it can balloon your build time due to the multiple render attempts that will be necessary.
If you tend to use the same variable in a lot of dynamic imports, and there are
only a few potential values, you can optimize dynamic import discovery by
precacheImportVariables option. Before rendering, while the
Stylus import tree is being discovered (by
resolved (by webpack), these values will be used to discover more potential
imports, eliminating the need for additional render attempts if the value at
render time happens to match.
Note that this option doesn't affect the output; the variables in your imports can still have any value at render time – but your build will potentially be much faster.
precacheImportVariables:$tenant: "foo"$tenant: "bar"$tenant: "baz"
This behavior currently only works for
@require syntax using
variables like so:
@import $foo;@import "~my-style-lib/styl/" + $foo;@require "./styles/" + $foo + "/more/" + $bar;
Status of this fork
There are no doubt people depending on the behavior described above, using it as a feature, not a bug. We'd love it if this behavior were adopted upstream, as we don't intend to fully support this fork for a wide audience in the long-term.
var css = ; // Just the CSSvar css = ; // CSS with processed url(...)s
See css-loader to see the effect of processed
Or within the webpack config:
module:loaders:test: /\.styl$/loader: 'css-loader!stylus-relative-loader?paths=node_modules/bootstrap-stylus/stylus/'
Then you can:
var css = require('./file.styl');.
Use in tandem with the style-loader to add the css rules to your
module:loaders:test: /\.styl$/ loader: 'style-loader!css-loader!stylus-relative-loader'
require('./file.styl'); will compile and add the CSS to your page.
stylus-relative-loader can also take advantage of webpack's resolve options. With the default options it'll find files in
web_modules as well as
node_modules, make sure to prefix any lookup in node_modules with
~. For example if you have a styles package lookup files in it like
@import '~styles/my-styles. It can also find stylus files without having the extension specified in the
@import and index files in folders if webpack is configured for stylus's file extension.
module:resolve:extensions: '' '.js' '.styl'
will let you have an
index.styl file in your styles package and
@import '~styles' it. It also lets you load a stylus file from a package installed in node_modules or if you add a modulesDirectories, like
modulesDirectories: ['node_modules', 'web_modules', 'bower_components'] option you could load from a folder like bower_components. To load files from a relative path leave off the
@import 'relative-styles/my-styles'; it.
Be careful though not to use the extensions configuration for two types of in one folder. If a folder has a
index.js and a
index.styl and you
You can also use stylus plugins by adding an extra
stylus section to your
var stylus_plugin = ;module:loaders:test: /\.styl$/ loader: 'style-loader!css-loader!stylus-relative-loader'stylus:use:
Using nib with stylus
The easiest way of enabling
nib is to import it in the stylus options:
~ resolves to
npm install stylus-relative-loader stylus --save-dev
Important: in order to have ability use any
stylus package version,
it won't be installed automatically. So it's required to
add it to
package.json along with
npm test open http://localhost:8080/test/
In lieu of a formal styleguide, take care to maintain the existing coding style.
- See the Releases page for newer releases.
- 3.0.0 - New import resolver supporting dynamic import paths.
- 2.1.1 - Sync with
Support Node 6 (@yyx990803), Test in webpack 1 and 2 (@phyllisstein)
- 2.1.0 - Initial release tracking
email@example.com, with fixed relative imports.
- Find pre-fork releases of