npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

stylus-relative-loader

v4.0.0

Published

Stylus loader for webpack, with fixed imports

Downloads

10,147

Readme

stylus-relative-loader

A stylus loader for webpack, with fixed imports.

NPM version

vs. stylus-loader

Relative imports

With stylus-loader (which inherits a lot of behavior from Stylus itself), relative path imports like ./variables and ./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 variables and 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.

For example:

styles
├── a
│   ├── color.styl
│   └── index.styl
├── b
│   ├── color.styl
│   └── index.styl
├── color.styl
└── index.styl

Let's say styles/index.styl contains:

@import './a';
@import './b';
@import './color';

...while a/index.styl and b/index.styl both contain:

@import './color';

With vanilla stylus-loader, the output would be ONLY the contents of styles/color.styl, repeated 3 times. Despite the ./color imports in a and b explicitly calling for a/color.styl and b/color.styl to be included, they won't be – merely because another relative path was imported with the same name.

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 color.styl, a/color.styl, and b/color.styl above.

Dynamic imports

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-relative-loader slower than 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.

New 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 providing the precacheImportVariables option. Before rendering, while the Stylus import tree is being discovered (by stylus-relative-loader) and 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 @import and @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.

Usage

var css = require('!raw!stylus-relative!./file.styl'); // Just the CSS
var css = require('!css!stylus-relative!./file.styl'); // CSS with processed url(...)s

See css-loader to see the effect of processed url(...)s.

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 document:

module: {
  loaders: [
    { test: /\.styl$/, loader: 'style-loader!css-loader!stylus-relative-loader' }
  ]
}

and then 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 require('styles') or @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 ~ and @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 @import './that-folder', it'll end up importing a javascript file into your stylus.

Stylus Plugins

You can also use stylus plugins by adding an extra stylus section to your webpack.config.js.

var stylus_plugin = require('stylus_plugin');
module: {
  loaders: [
    { test: /\.styl$/, loader: 'style-loader!css-loader!stylus-relative-loader' }
  ]
},
stylus: {
  use: [stylus_plugin()]
}

Using nib with stylus

The easiest way of enabling nib is to import it in the stylus options:

stylus: {
  use: [require('nib')()],
  import: ['~nib/lib/nib/index.styl']
}

where ~ resolves to node_modules/

Install

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 stylus-relative-loader.

Testing

npm test
open http://localhost:8080/test/

Contributing

In lieu of a formal styleguide, take care to maintain the existing coding style.

Release History

  • See the Releases page for newer releases.
  • 3.0.0 - New import resolver supporting dynamic import paths.
  • 2.1.1 - Sync with stylus-loader 2.1.1:

    Support Node 6 (@yyx990803), Test in webpack 1 and 2 (@phyllisstein)

  • 2.1.0 - Initial release tracking [email protected], with fixed relative imports.
  • Find pre-fork releases of stylus-loader at https://github.com/shama/stylus-loader/releases