UNPKG

5.85 kBMarkdownView Raw
1# css-modulesify
2
3[![Build Status](https://travis-ci.org/css-modules/css-modulesify.svg?branch=master)](https://travis-ci.org/css-modules/css-modulesify)
4
5A browserify plugin to load [CSS Modules].
6
7[CSS Modules]: https://github.com/css-modules/css-modules
8
9**Please note that this is still highly experimental.**
10
11## Why CSS Modules?
12
13Normally you need to use a strict naming convention like BEM to ensure that one component's CSS doesn't collide with another's. CSS Modules are locally scoped, which allows you to use names that are meaningful within the context of the component, without any danger of name collision.
14
15Read Mark Dalgleish's excellent ["End of Global CSS"](https://medium.com/seek-ui-engineering/the-end-of-global-css-90d2a4a06284) and check out [css-modules](https://github.com/css-modules/css-modules) for more context.
16
17## Getting started
18
19First install the package: `npm install --save css-modulesify`
20
21Then you can use it as a browserify plugin, eg: `browserify -p [ css-modulesify -o dist/main.css ] example/index.js`
22
23Inside `example/index.js` you can now load css into your scripts. When you do `var box1 = require('./box1.css')`, `box1` will be an object to lookup the localized classname for one of the selectors in that file.
24
25So to apply a class to an element you can do something like:
26
27```js
28var styles = require('./styles.css');
29var div = `<div class="${styles.inner}">...</div>`;
30```
31
32The generated css will contain locally-scoped versions of any css you have `require`'d, and will be written out to the file you specify in the `--output` or `-o` option.
33
34## API Usage
35
36```js
37var b = require('browserify')();
38
39b.add('./main.js');
40b.plugin(require('css-modulesify'), {
41 rootDir: __dirname,
42 output: './path/to/my.css'
43});
44
45b.bundle();
46```
47
48```js
49// or, get the output as a stream
50var b = require('browserify')();
51var fs = require('fs');
52
53b.add('./main.js');
54b.plugin(require('css-modulesify'), {
55 rootDir: __dirname
56});
57
58var bundle = b.bundle()
59b.on('css stream', function (css) {
60 css.pipe(fs.createWriteStream('mycss.css'));
61});
62```
63
64### Options:
65
66- `rootDir`: absolute path to your project's root directory. This is optional but providing it will result in better generated classnames. css-modulesify will try to use the browserify `basedir` if `rootDir` is not specified, if both are not specified it will use the location from which the command was executed.
67- `output`: path to write the generated css. If not provided, you'll need to listen to the `'css stream'` event on the bundle to get the output.
68- `jsonOutput`: optional path to write a json manifest of classnames.
69- `use`: optional array of postcss plugins (by default we use the css-modules core plugins). NOTE: it's safer to use `after`
70- `before`: optional array of postcss plugins to run before the required css-modules core plugins are run.
71- `after`: optional array of postcss plugins to run after the required css-modules core plugins are run.
72- `generateScopedName`: (API only) a function to override the default behaviour of creating locally scoped classnames.
73- `global`: optional boolean. Set to `true` if you want `css-modulesify` to apply to `node_modules` as well as local files. You can read more about it in the [browserify docs](https://github.com/substack/node-browserify/#btransformtr-opts).
74
75### Events
76- `b.on('css stream', callback)` The callback is called with a readable stream containing the compiled CSS. You can write this to a file.
77
78## Using CSS Modules on the backend
79
80If you want to use CSS Modules in server-generated templates there are a couple of options:
81
82- Option A (nodejs only): register the [require-hook](https://github.com/css-modules/css-modules-require-hook) so that `var styles = require('./foo.css')` operates the same way as on the frontend. Make sure that the `rootDir` option matches to guarantee that the classnames are the same.
83
84- Option B: configure the `jsonOutput` option with a file path and `css-modulesify` will generate a JSON manifest of classnames.
85
86
87## PostCSS Plugins
88
89The following PostCSS plugins are enabled by default:
90
91 * [postcss-modules-local-by-default]
92 * [postcss-modules-extract-imports]
93 * [postcss-modules-scope]
94 * [postcss-modules-values]
95
96(i.e. the [CSS Modules] specification).
97
98You can override the default PostCSS Plugins (and add your own) by passing `--use|-u` to `css-modulesify`.
99
100Or if you just want to add some extra plugins to run after the default, add them to the `postcssAfter` array option (API only at this time). In the same way, add extra plugins to `postcssBefore` to run the before the defaults.
101
102In addition you may also wish to configure defined PostCSS plugins by passing `--plugin.option true`.
103
104An example of this would be:
105
106```
107browserify -p [css-modulesify \
108 --after autoprefixer --autoprefixer.browsers '> 5%' \
109 -o dist/main.css] -o dist/index.js src/index.js
110```
111
112[postcss-modules-local-by-default]: https://github.com/css-modules/postcss-modules-local-by-default
113[postcss-modules-extract-imports]: https://github.com/css-modules/postcss-modules-extract-imports
114[postcss-modules-scope]: https://github.com/css-modules/postcss-modules-scope
115[postcss-modules-values]: https://github.com/css-modules/postcss-modules-values
116
117## Building for production
118
119If you set `NODE_ENV=production` then `css-modulesify` will generate shorter (though less useful) classnames.
120
121You can also manually switch to short names by setting the `generateScopedName` option. Eg:
122
123```
124browserify.plugin(cssModulesify, {
125 rootDir: __dirname,
126 output: './dist/main.css',
127 generateScopedName: cssModulesify.generateShortName
128})
129```
130
131## Example
132
133An example implementation can be found [here](https://github.com/css-modules/browserify-demo).
134
135## Licence
136
137MIT
138
139## With thanks
140
141 - Tobias Koppers
142 - Mark Dalgleish
143 - Glen Maddern
144
145----
146Josh Johnston, 2015.