Skip to content

Commit

Permalink
Improve config documentation and remove 22 dependencies from cssnano (#…
Browse files Browse the repository at this point in the history
…1168)

* test: add configuration loading tests and docs

Closes #904
Add tests for configuration loading and correct the documentation.

* correct configuration file names in the docs
* specify that the PostCss config overrides the cssnano-specific config
* remove mention of cosmiconfig to avoid being tied to a single implementation

* chore(deps): replace cosmiconfig with lilconfig

Remove about 22 dependencies according to npm i --production (from 110 to 88 deps)

* reduce node_modules after `yarn install cssnano` in empty project from 14MB to 13MB
* add YAML dep to preserve YAML configuration compatibility
  YAML configuration was only implicitly documented by referring to cosmiconfig,
  but removing it would be a breaking change
  • Loading branch information
ludofischer committed Jul 19, 2021
1 parent 9886775 commit 506a823
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 37 deletions.
3 changes: 2 additions & 1 deletion packages/cssnano/package.json
Expand Up @@ -24,7 +24,8 @@
],
"license": "MIT",
"dependencies": {
"cosmiconfig": "^7.0.0",
"lilconfig": "^2.0.3",
"yaml": "^1.10.2",
"cssnano-preset-default": "^5.1.3",
"is-resolvable": "^1.1.0"
},
Expand Down
3 changes: 3 additions & 0 deletions packages/cssnano/src/__tests__/config_loading/.cssnanorc.json
@@ -0,0 +1,3 @@
{
"preset": "lite"
}
22 changes: 22 additions & 0 deletions packages/cssnano/src/__tests__/config_loading/config-loading.js
@@ -0,0 +1,22 @@
import process from 'process';
import postcss from 'postcss';
import litePreset from 'cssnano-preset-lite';
import defaultPreset from 'cssnano-preset-default';
import cssnano from '../..';

/* The configuration is loaded relative to the current working directory,
when running the repository tests, the working directory is
the repostiory root, so we need to change it to avoid having to place
the configuration file for this test in the repo root */
const spy = jest.spyOn(process, 'cwd');
spy.mockReturnValue(__dirname);

test('should read the cssnano configuration file', () => {
const processor = postcss([cssnano]);
expect(processor.plugins.length).toBe(litePreset().plugins.length);
});

test('PostCSS config should override the cssnano config', () => {
const processor = postcss([cssnano({ preset: 'default' })]);
expect(processor.plugins.length).toBe(defaultPreset().plugins.length);
});
21 changes: 18 additions & 3 deletions packages/cssnano/src/index.js
@@ -1,6 +1,7 @@
import path from 'path';
import postcss from 'postcss';
import { cosmiconfigSync } from 'cosmiconfig';
import yaml from 'yaml';
import { lilconfigSync } from 'lilconfig';
import isResolvable from 'is-resolvable';

const cssnano = 'cssnano';
Expand Down Expand Up @@ -59,7 +60,7 @@ function resolvePreset(preset) {

/*
* cssnano will look for configuration firstly as options passed
* directly to it, and failing this it will use cosmiconfig to
* directly to it, and failing this it will use lilconfig to
* load an external file.
*/

Expand All @@ -76,7 +77,21 @@ function resolveConfig(options) {
configPath = path.resolve(process.cwd(), options.configFile);
}

const configExplorer = cosmiconfigSync(cssnano);
const configExplorer = lilconfigSync(cssnano, {
searchPlaces: [
'package.json',
'.cssnanorc',
'.cssnanorc.json',
'.cssnanorc.yaml',
'.cssnanorc.yml',
'.cssnanorc.js',
'cssnano.config.js',
],
loaders: {
'.yaml': (filepath, content) => yaml.parse(content),
'.yml': (filepath, content) => yaml.parse(content),
},
});
const config = configPath
? configExplorer.load(configPath)
: configExplorer.search(searchPath);
Expand Down
89 changes: 61 additions & 28 deletions site/docs/config-file.mdx
Expand Up @@ -21,46 +21,84 @@ export const ExampleChart = () => {

<ExampleChart/>

## `cssnano` config files
You can configure cssnano either in the PostCSS configuration file or in a dedicated cssnano configuration file. The PostCSS configuration file takes precedence over the dedicated cssnano configuration.
If you don't pass any configuration, cssnano runs with the `default` preset.


## Configure through PostCSS configuration files

In the [PostCSS configuration file](https://github.com/postcss/postcss#usage), you can pass both the `preset` and `plugins` options when you add `cssnano` to the PostCSS plugins. For example, if you use PostCSS programmatically, the following uses cssnano with the `lite` preset and adds autoprefixer.

```js
import postcss from 'postcss';
import cssnano from 'cssnano';
import litePreset from 'cssnano-preset-lite';
import autoprefixer from 'autoprefixer';
const preset = litePreset({ discardComments: false });

postcss([cssnano({ preset, plugins: [autoprefixer] })]).process("/* Your CSS here */")
```

## Configure through dedicated `cssnano` configuration

If you cannot configure cssnano in the PostCSS configuration file, you can configure cssnano with a cssnano configuration option in `package.json` or with a dedicated configuration file. This file can be in different formats.

* `.cssnanorc.config.json` and `.cssnanorc` must contain a JSON object
* `cssnano.config.js` must export the configuration as a JavaScript object

We use configuration for `cssnano` using file name as `cssnano.config.js` , `cssnano` property in your `package.json`, using `cssnano.config.json` and `.cssnanorc` as well.
We are using `cosmiconfig` in order to load cssnano config. Please read [here](https://github.com/davidtheclark/cosmiconfig) for more details

## Options

### `preset`

- **Type:** `string` | `function` | `[string, Objects<preset options here>]` | `[function(preset options here)]`

> For `string`, the name should be of type `cssnano-preset-<name>` and you need to use `name` alone eg : `preset : ['default', {}]`
Pass a preset to choose a pre-configured set of optimizations. You can either import the preset package or use the preset name as a string.

Contains lists of `postcss` plugins where each plugin does their own minification.
With the preset as import:

- **Example:**

```js
// cssnano.config.js
module.exports = {
preset: [require('cssnano-preset-default')]

// or
preset: require('cssnano-preset-default')

// or
preset: ['advanced', { discardComments: false }]
```js
cssnano({ preset: require('cssnano-preset-default') })
```

Using a string is useful if you use a configuration file in the JSON format.
When you use a string, if the preset is called `cssnano-preset-<name>`, use `name` alone:

```js
cssnano({ preset: 'default' })
```

Presets themselves can take options.
Pass options to the preset by using an array where the first element is the preset and the second is an object with the preset options.
You can specify a preset with the preset name as a string or by passing the result of importing the preset package.

```js
// cssnano.config.js
module.exports = {
preset: [ require('cssnano-preset-default'), { discardComments: false } ]
};
```


You can also pass preset options when you use the preset name as a string:
For example, here's how to deactivate the `discardComments` plugin when using the `advanced` preset:

```js
cssnano({ preset: ['advanced', { discardComments: false }] })
```

// or
preset: [require('cssnano-preset-default'), {discardComments: false}]
}
```

### `plugins`

- **Type:** `Array<'string' | 'function' | ['string' | 'function', Object<Options for the plugin here>]>`

> If you want to pass config to the plugin, you need to use Array's of array for the plugins i.e `plugins: [ ['autoprefixer', {}] ]`
In addition to the preset, you can pass a list of plugins to cssnano.
This is equivalent to adding the plugins after cssnano in the PostCSS plugins array.
If you want to configure the individual plugins, use an array of arrays:

These plugins will run after once all presets operations are complete.
```js
cssnano({ plugins: [['autoprefixer', {}]] })
```

- **Example:**

Expand All @@ -84,8 +122,3 @@ These plugins will run after once all presets operations are complete.
]
}
```

## Alternatives

You can use the `postcss` config file and both `preset` and `plugins` will be passed as the options for `cssnano`.
Refer [here](https://github.com/postcss/postcss#usage) for more details.
16 changes: 11 additions & 5 deletions yarn.lock
Expand Up @@ -6325,6 +6325,11 @@ libnpmpublish@^4.0.0:
semver "^7.1.3"
ssri "^8.0.1"

lilconfig@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.3.tgz#68f3005e921dafbd2a2afb48379986aa6d2579fd"
integrity sha512-EHKqr/+ZvdKCifpNrJCKxBTgk5XupZA3y/aCPY9mxfgBzmgh93Mt/WqjjQ38oMxXuvDokaKiM3lAgvSH2sjtHg==

lines-and-columns@^1.1.6:
version "1.1.6"
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
Expand Down Expand Up @@ -7942,12 +7947,13 @@ postcss-font-magician@^3.0.0:
google-fonts-complete "^2.1.1"

postcss-load-config@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.0.1.tgz#d214bf9cfec1608ffaf0f4161b3ba20664ab64b9"
integrity sha512-/pDHe30UYZUD11IeG8GWx9lNtu1ToyTsZHnyy45B4Mrwr/Kb6NgYl7k753+05CJNKnjbwh4975amoPJ+TEjHNQ==
version "3.1.0"
resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.0.tgz#d39c47091c4aec37f50272373a6a648ef5e97829"
integrity sha512-ipM8Ds01ZUophjDTQYSVP70slFSYg3T0/zyfII5vzhN6V57YSxMgG5syXuwi5VtS8wSf3iL30v0uBdoIVx4Q0g==
dependencies:
cosmiconfig "^7.0.0"
import-cwd "^3.0.0"
lilconfig "^2.0.3"
yaml "^1.10.2"

postcss-reporter@^1.3.0:
version "1.4.1"
Expand Down Expand Up @@ -10270,7 +10276,7 @@ yallist@^4.0.0:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==

yaml@^1.10.0:
yaml@^1.10.0, yaml@^1.10.2:
version "1.10.2"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
Expand Down

0 comments on commit 506a823

Please sign in to comment.