333 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			333 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
# postcss-modules
 | 
						|
 | 
						|
A [PostCSS] plugin to use [CSS Modules] everywhere. Not only at the client side.
 | 
						|
 | 
						|
[postcss]: https://github.com/postcss/postcss
 | 
						|
[css modules]: https://github.com/css-modules/css-modules
 | 
						|
 | 
						|
## Support the developer
 | 
						|
 | 
						|
I maintain the plugin in my free time, so I don't receive any payment for this work.
 | 
						|
To have better docs, new features and integrations with frameworks, you can [support me on Patreon](https://www.patreon.com/bePatron?u=25976212).
 | 
						|
 | 
						|
The sponsors are listed [below in the README](#sponsors)
 | 
						|
 | 
						|
## What is this?
 | 
						|
 | 
						|
For example, you have the following CSS:
 | 
						|
 | 
						|
```css
 | 
						|
/* styles.css */
 | 
						|
:global .page {
 | 
						|
  padding: 20px;
 | 
						|
}
 | 
						|
 | 
						|
.title {
 | 
						|
  composes: title from "./mixins.css";
 | 
						|
  color: green;
 | 
						|
}
 | 
						|
 | 
						|
.article {
 | 
						|
  font-size: 16px;
 | 
						|
}
 | 
						|
 | 
						|
/* mixins.css */
 | 
						|
.title {
 | 
						|
  color: black;
 | 
						|
  font-size: 40px;
 | 
						|
}
 | 
						|
 | 
						|
.title:hover {
 | 
						|
  color: red;
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
After the transformation it will become like this:
 | 
						|
 | 
						|
```css
 | 
						|
._title_116zl_1 {
 | 
						|
  color: black;
 | 
						|
  font-size: 40px;
 | 
						|
}
 | 
						|
 | 
						|
._title_116zl_1:hover {
 | 
						|
  color: red;
 | 
						|
}
 | 
						|
 | 
						|
.page {
 | 
						|
  padding: 20px;
 | 
						|
}
 | 
						|
 | 
						|
._title_xkpkl_5 {
 | 
						|
  color: green;
 | 
						|
}
 | 
						|
 | 
						|
._article_xkpkl_10 {
 | 
						|
  font-size: 16px;
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
And the plugin will give you a JSON object for transformed classes:
 | 
						|
 | 
						|
```json
 | 
						|
{
 | 
						|
  "title": "_title_xkpkl_5 _title_116zl_1",
 | 
						|
  "article": "_article_xkpkl_10"
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
## Usage
 | 
						|
 | 
						|
### Saving exported classes
 | 
						|
 | 
						|
By default, a JSON file with exported classes will be placed next to corresponding CSS.
 | 
						|
But you have a freedom to make everything you want with exported classes, just
 | 
						|
use the `getJSON` callback. For example, save data about classes into a corresponding JSON file:
 | 
						|
 | 
						|
```js
 | 
						|
postcss([
 | 
						|
  require("postcss-modules")({
 | 
						|
    getJSON: function (cssFileName, json, outputFileName) {
 | 
						|
      var path = require("path");
 | 
						|
      var cssName = path.basename(cssFileName, ".css");
 | 
						|
      var jsonFileName = path.resolve("./build/" + cssName + ".json");
 | 
						|
      fs.writeFileSync(jsonFileName, JSON.stringify(json));
 | 
						|
    },
 | 
						|
  }),
 | 
						|
]);
 | 
						|
```
 | 
						|
 | 
						|
`getJSON` may also return a `Promise`.
 | 
						|
 | 
						|
### Generating scoped names
 | 
						|
 | 
						|
By default, the plugin assumes that all the classes are local. You can change
 | 
						|
this behaviour using the `scopeBehaviour` option:
 | 
						|
 | 
						|
```js
 | 
						|
postcss([
 | 
						|
  require("postcss-modules")({
 | 
						|
    scopeBehaviour: "global", // can be 'global' or 'local',
 | 
						|
  }),
 | 
						|
]);
 | 
						|
```
 | 
						|
 | 
						|
To define paths for global modules, use the `globalModulePaths` option.
 | 
						|
It is an array with regular expressions defining the paths:
 | 
						|
 | 
						|
```js
 | 
						|
postcss([
 | 
						|
  require('postcss-modules')({
 | 
						|
    globalModulePaths: [/path\/to\/legacy-styles/, /another\/paths/],
 | 
						|
  });
 | 
						|
]);
 | 
						|
```
 | 
						|
 | 
						|
To generate custom classes, use the `generateScopedName` callback:
 | 
						|
 | 
						|
```js
 | 
						|
postcss([
 | 
						|
  require("postcss-modules")({
 | 
						|
    generateScopedName: function (name, filename, css) {
 | 
						|
      var path = require("path");
 | 
						|
      var i = css.indexOf("." + name);
 | 
						|
      var line = css.substr(0, i).split(/[\r\n]/).length;
 | 
						|
      var file = path.basename(filename, ".css");
 | 
						|
 | 
						|
      return "_" + file + "_" + line + "_" + name;
 | 
						|
    },
 | 
						|
  }),
 | 
						|
]);
 | 
						|
```
 | 
						|
 | 
						|
Or just pass an interpolated string to the `generateScopedName` option
 | 
						|
(More details [here](https://github.com/webpack/loader-utils#interpolatename)):
 | 
						|
 | 
						|
```js
 | 
						|
postcss([
 | 
						|
  require("postcss-modules")({
 | 
						|
    generateScopedName: "[name]__[local]___[hash:base64:5]",
 | 
						|
  }),
 | 
						|
]);
 | 
						|
```
 | 
						|
 | 
						|
It's possible to add custom hash to generate more unique classes using the `hashPrefix` option (like in [css-loader](https://webpack.js.org/loaders/css-loader/#hashprefix)):
 | 
						|
 | 
						|
```js
 | 
						|
postcss([
 | 
						|
  require("postcss-modules")({
 | 
						|
    generateScopedName: "[name]__[local]___[hash:base64:5]",
 | 
						|
    hashPrefix: "prefix",
 | 
						|
  }),
 | 
						|
]);
 | 
						|
```
 | 
						|
 | 
						|
### Exporting globals
 | 
						|
 | 
						|
If you need to export global names via the JSON object along with the local ones, add the `exportGlobals` option:
 | 
						|
 | 
						|
```js
 | 
						|
postcss([
 | 
						|
  require("postcss-modules")({
 | 
						|
    exportGlobals: true,
 | 
						|
  }),
 | 
						|
]);
 | 
						|
```
 | 
						|
 | 
						|
### Loading source files
 | 
						|
 | 
						|
If you need, you can pass a custom loader (see [FileSystemLoader] for example):
 | 
						|
 | 
						|
```js
 | 
						|
postcss([
 | 
						|
  require("postcss-modules")({
 | 
						|
    Loader: CustomLoader,
 | 
						|
  }),
 | 
						|
]);
 | 
						|
```
 | 
						|
 | 
						|
You can also pass any needed root path:
 | 
						|
 | 
						|
```js
 | 
						|
postcss([
 | 
						|
  require('postcss-modules')({
 | 
						|
    root: 'C:\\',
 | 
						|
  });
 | 
						|
]);
 | 
						|
```
 | 
						|
 | 
						|
### localsConvention
 | 
						|
 | 
						|
Type: `String | (originalClassName: string, generatedClassName: string, inputFile: string) => className: string`
 | 
						|
Default: `null`
 | 
						|
 | 
						|
Style of exported classnames, the keys in your json.
 | 
						|
 | 
						|
|         Name          |    Type    | Description                                                                                      |
 | 
						|
| :-------------------: | :--------: | :----------------------------------------------------------------------------------------------- |
 | 
						|
|   **`'camelCase'`**   | `{String}` | Class names will be camelized, the original class name will not to be removed from the locals    |
 | 
						|
| **`'camelCaseOnly'`** | `{String}` | Class names will be camelized, the original class name will be removed from the locals           |
 | 
						|
|    **`'dashes'`**     | `{String}` | Only dashes in class names will be camelized                                                     |
 | 
						|
|  **`'dashesOnly'`**   | `{String}` | Dashes in class names will be camelized, the original class name will be removed from the locals |
 | 
						|
 | 
						|
In lieu of a string, a custom function can generate the exported class names.
 | 
						|
 | 
						|
### Resolve path alias
 | 
						|
 | 
						|
You can rewrite paths for `composes/from` by using `resolve` options.
 | 
						|
It's useful when you need to resolve custom path alias.
 | 
						|
 | 
						|
```js
 | 
						|
postcss([
 | 
						|
  require("postcss-modules")({
 | 
						|
    resolve: function (file) {
 | 
						|
     return file.replace(/^@/, process.cwd());
 | 
						|
    },
 | 
						|
  }),
 | 
						|
]);
 | 
						|
```
 | 
						|
 | 
						|
`resolve` may also return a `Promise<string>`.
 | 
						|
 | 
						|
 | 
						|
## Integration with templates
 | 
						|
 | 
						|
The plugin only transforms CSS classes to CSS modules.
 | 
						|
But you probably want to integrate these CSS modules with your templates.
 | 
						|
Here are some examples.
 | 
						|
 | 
						|
Assume you've saved project's CSS modules in `cssModules.json`:
 | 
						|
 | 
						|
```json
 | 
						|
{
 | 
						|
  "title": "_title_xkpkl_5 _title_116zl_1",
 | 
						|
  "article": "_article_xkpkl_10"
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
### Pug (ex-Jade)
 | 
						|
 | 
						|
Let's say you have a Pug template `about.jade`:
 | 
						|
 | 
						|
```jade
 | 
						|
h1(class=css.title) postcss-modules
 | 
						|
article(class=css.article) A PostCSS plugin to use CSS Modules everywhere
 | 
						|
```
 | 
						|
 | 
						|
Render it:
 | 
						|
 | 
						|
```js
 | 
						|
var jade = require("jade");
 | 
						|
var cssModules = require("./cssModules.json");
 | 
						|
var html = jade.compileFile("about.jade")({ css: cssModules });
 | 
						|
console.log(html);
 | 
						|
```
 | 
						|
 | 
						|
And you'll get the following HTML:
 | 
						|
 | 
						|
```html
 | 
						|
<h1 class="_title_xkpkl_5 _title_116zl_1">postcss-modules</h1>
 | 
						|
<article class="_article_xkpkl_10">
 | 
						|
  A PostCSS plugin to use CSS Modules everywhere
 | 
						|
</article>
 | 
						|
```
 | 
						|
 | 
						|
### HTML
 | 
						|
 | 
						|
For HTML transformation we'll use [PostHTML](https://github.com/posthtml/posthtml) and [PostHTML CSS Modules](https://github.com/maltsev/posthtml-css-modules):
 | 
						|
 | 
						|
```bash
 | 
						|
npm install --save posthtml posthtml-css-modules
 | 
						|
```
 | 
						|
 | 
						|
Here is our template `about.html`:
 | 
						|
 | 
						|
```html
 | 
						|
<h1 css-module="title">postcss-modules</h1>
 | 
						|
<article css-module="article">
 | 
						|
  A PostCSS plugin to use CSS Modules everywhere
 | 
						|
</article>
 | 
						|
```
 | 
						|
 | 
						|
Transform it:
 | 
						|
 | 
						|
```js
 | 
						|
var fs = require("fs");
 | 
						|
var posthtml = require("posthtml");
 | 
						|
var posthtmlCssModules = require("posthtml-css-modules");
 | 
						|
var template = fs.readFileSync("./about.html", "utf8");
 | 
						|
 | 
						|
posthtml([posthtmlCssModules("./cssModules.json")])
 | 
						|
  .process(template)
 | 
						|
  .then(function (result) {
 | 
						|
    console.log(result.html);
 | 
						|
  });
 | 
						|
```
 | 
						|
 | 
						|
(for using other build systems please check [the documentation of PostHTML](https://github.com/posthtml/posthtml/blob/master/README.md))
 | 
						|
 | 
						|
And you'll get the following HTML:
 | 
						|
 | 
						|
```html
 | 
						|
<h1 class="_title_xkpkl_5 _title_116zl_1">postcss-modules</h1>
 | 
						|
<article class="_article_xkpkl_10">
 | 
						|
  A PostCSS plugin to use CSS Modules everywhere
 | 
						|
</article>
 | 
						|
```
 | 
						|
 | 
						|
## May I see the plugin in action?
 | 
						|
 | 
						|
Sure! Take a look at the [example](https://github.com/outpunk/postcss-modules-example).
 | 
						|
 | 
						|
See [PostCSS] docs for examples for your environment and don't forget to run
 | 
						|
 | 
						|
```
 | 
						|
npm install --save-dev postcss postcss-modules
 | 
						|
```
 | 
						|
 | 
						|
[filesystemloader]: https://github.com/css-modules/css-modules-loader-core/blob/master/src/file-system-loader.js
 | 
						|
 | 
						|
 | 
						|
## Sponsors
 | 
						|
- Dmitry Olyenyov
 |