Skip to content

Instantly share code, notes, and snippets.

@conradz
Created November 28, 2013 03:21
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save conradz/7686821 to your computer and use it in GitHub Desktop.
Save conradz/7686821 to your computer and use it in GitHub Desktop.
rework-npm

rework-npm

I recently published rework-npm that allows you to import CSS files using the same rules that the Node.js uses for modules. This lets you install and manage CSS packages using npm the same way you manage JS modules.

Why npm?

First of all, why use npm? Why does it make sense to use npm for CSS? Npm is good for a number of reasons.

First, it is simple to use. Want to publish a module? Just use npm publish. Want to install a new package and save it to the dependencies? Just use npm install --save mymodule. This makes it super easy to create and maintain small modules, instead of putting everything into one large module.

It also resolves dependencies in a predictable manner. When using npm install, npm will automatically install all the required dependencies for that module. But instead of installing it into a global modules directory, npm will install the module's dependencies into a node_modules directory inside the module. This means that you can have conflicting versions and both will be loaded (see more on this below). This helps you by ensuring that the exact version you defined in the package dependencies will be used, and not some incompatible version.

Finally, the module system and semantics will be familiar with anyone that has used Node.js. Rework-npm uses the exact same path resolution algorithm that Node.js uses (except for using .css by default instead of .js).

Using rework-npm

So npm is great and all, but how do I use it for CSS? By using rework-npm, of course! First of all, you need to use rework. Rework is a simple library for processing CSS. By itself it basically does nothing, but depends on plugins for doing what you need it to do.

To process a file using rework-npm, you can run the following code in Node.js:

var rework = require('rework'),
    reworkNPM = require('rework-npm'),
    fs = require('fs');
    
var contents = fs.readFileSync('my-file.css', 'utf8');
contents = rework(contents)
    .use(reworkNPM(/* optionally provide directory that source file is in */))
    .toString();

fs.writeFileSync('output.css', 'utf8', contents);

Say we have my-file.css and buttons.css in a folder. To import buttons.css into my-file.css, simply use @import "./buttons";. When importing paths that begin with ., it will resolve the path to the directory of the current file.

To import files from other packages, use @import "package/file";. This will import file.css from package, which is installed in a node_modules folder. To import a package you will normally use the simpler @import "<package name>"; code, which will import the file specified by the style property in the package's package.json file, or index.css if no style property is provided.

Complete example:

/* my-file.css */
@import "my-package";
@import "./buttons";
/* buttons.css */
button {
  /* Some code here */
}
/* node_modules/my-package/index.css */

.package {
  /* Some code here */
}

After processing my-file.css, it would output:

.package {
  /* Some code here */
}

button {
  /* Some code here */
}

But do I want duplicated packages?

So duplicated packages in CSS aren't always a good thing. CSS really doesn't have any good way to handle local vs. global imports (everything is imported globally), unlike Node.js modules. Thankfully, npm has a good way to handle this. It has a npm dedupe command, which lifts packages that are required in multiple sub-packages up into a parent node_modules folder. It will ensure that all the version requirements are met before doing so. After doing this, you should not have any duplicated packages unless there are packages that depend on conflicting version of the same dependency. If you have conflicting version requirements, CSS doesn't have any good way to handle them, no matter how you import them.

When importing packages using rework-npm, it will avoid including the same file multiple times. Multiple packages can depend on the same package, and when using npm dedupe there should not be any duplicated CSS code in the output code.

Go forth and modularize!

With these tools available, it makes it super simple to create small, targeted modules that do one thing well. If you need to style buttons, just @import "my-buttons-package"; and install the required package with npm. With small modules you can reduce the size of the code, since you are only including the things that you actually need. This improves download times, and makes the user happy. After all, everyone likes happy users.

@kristoferjoseph
Copy link

This is really great! If you don't mind I think I'll expound a bit and publish this to the topcoat blog.
The workflow this enables is very compelling.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment