Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve config documentation and remove 22 dependencies from cssnano #1168

Merged
merged 2 commits into from Jul 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was uncertain whether to keep YAML config parsing since it was never documented explicitly, but removing would be a breaking change in theory.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like a good call to keep it for now, even if the chance of it being used is remote 👍

Question:

Since the tests you added were paired with a .cssnanorc.json and you mentioned keeping YAML support, I decided to attempt running the test suite with a .cssnanorc.yaml and a few other variations (replacing .cssnanorc.json in the config_loading dir) for the sake of diligence. And it doesn't appear to be picked up.

It's entirely possible I'm having some form of "brainfart" and doing something wrong here - but shouldn't that work?

(Out of curiosity I had a look at the searchItems found by lilconfig in lilconfigSync.search() and it only appears to look for package.json, cssnanorc.json, cssnano.config.js, and cssnanorc.js, .cssnanorc.cjs, and cssnano.config.cjs)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My inner conviction is nobody is really using the YAML format, so I did not bother checking whether it works, I have just copied the instructions on the lilconfig repo. Looking at the lilconfig code, it seems it does not even load .rc (with no extension) by default.

"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),
},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if you may also need to add something like searchPlaces: ['.cssnanorc.yaml', '.cssnanorc.yml'] to the options in order for lilconfig to actually look for yaml files?

It seems like lilconfig uses this as basis for merging in the loaders.

Ref. #1168 (comment)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like a bit of a bug or design weakness on their part

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the code with explicit search places. I did try renaming the file to .cssnanorc.yml and it worked.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed! And perhaps not such a bad thing for it to be explicit anyway 👍

});
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:
ludofischer marked this conversation as resolved.
Show resolved Hide resolved

- **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
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The section about the PostCSS config file has been moved to the top as that is what most people will use and the PostCSS config overrides the config in the cssnano files.


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