Let's make awesome validation for the config!
See original GitHub issueUpdate/TLDR:
- This issue was originally about validating brunch-config.js. That’s done (in a general way that ensures that future config is validated too).
- Then, I suggested better error handling of missing files and valid but bad config. That’s done. (Let’s improve things more as we find them.)
- What’s left to do is plugin config validation.
The last couple of days I’ve been migrating a legacy project to brunch, and it’s been a very positive experince!
I’ve used brunch a bit a few years ago, so it wasn’t entirely new to me, but I still bumped into a few problems along the way. Most of the time, the problems arose from a mistake I had made in brunch-config.js. Here are a few examples.
I had just finished installing some brunch plugins and making a few edits to brunch-config.js. I then ran brunch b
to test it out. (Yes, my primary testing consists of running brunch b
and inspecting the output in public/
. I don’t bother opening the browser until it looks ok.) This is the result:
$ brunch b
13 Apr 06:06:33 - error: Initialization error - TypeError: stylesheets.map is not a function
at /home/lydell/myproject/node_modules/deppack/lib/load-globs-styles.js:21:26
at Array.map (native)
at Object.keys.map.each.then (/home/lydell/myproject/node_modules/deppack/lib/load-globs-styles.js:15:42)
at /home/lydell/myproject/node_modules/deppack/lib/deppack.js:71:19
That’s not very helpful! Initially, I had no clue at all what was wrong. I didn’t know if it was my fault, some plugin’s fault or a bug in brunch. I then noticed the word “stylesheets” in the error message, and thought of config.files.stylesheets
, but that was a red herring. I then realized that if .map
is not a function, that probably means that brunch expects an array in my config, but I gave it something else. I started commenting out my most recent changes in brunch-config.js until the problem went away. Turned out this was the problem:
npm: {
styles: {
'font-awesome': 'css/font-awesome.css',
},
},
… which is supposed to be (note the added [
and ]
):
npm: {
styles: {
'font-awesome': ['css/font-awesome.css'],
},
},
Similarly to the above, I Initially thought that npm.static
could be used like this:
static: {
'font-awesome': ['fonts/font-awesome.woff']
},
That gave me this:
$ brunch b
/home/lydell/myproject/node_modules/deppack/lib/deppack.js:34
const isPackage = path => isNodeModule(path) && (statics || []).indexOf(path) === -1;
^
TypeError: (statics || []).indexOf is not a function
at Object.path [as isPackage] (/home/lydell/myproject/node_modules/deppack/lib/deppack.js:34:67)
at Deppack.isNpm (/home/lydell/myproject/node_modules/deppack/lib/deppack.js:100:27)
at FileList.isIgnored (/home/lydell/myproject/node_modules/brunch/lib/fs_utils/file_list.js:65:17)
at FileList._change (/home/lydell/myproject/node_modules/brunch/lib/fs_utils/file_list.js:187:26)
at emitMany (events.js:121:13)
at FileList.emit (events.js:195:7)
at BrunchWatcher.changeFileList (/home/lydell/myproject/node_modules/brunch/lib/watch.js:239:19)
at BrunchWatcher.startCompilation (/home/lydell/myproject/node_modules/brunch/lib/watch.js:314:12)
at FSWatcher.<anonymous> (/home/lydell/myproject/node_modules/brunch/lib/watch.js:177:14)
at emitTwo (events.js:100:13)
at FSWatcher.emit (events.js:185:7)
at FSWatcher.<anonymous> (/home/lydell/myproject/node_modules/chokidar/index.js:171:15)
at FSWatcher._emit (/home/lydell/myproject/node_modules/chokidar/index.js:212:5)
at FSWatcher.NodeFsHandler._handleFile (/home/lydell/myproject/node_modules/chokidar/lib/nodefs-handler.js:275:10)
at FSWatcher.<anonymous> (/home/lydell/myproject/node_modules/chokidar/lib/nodefs-handler.js:473:21)
at FSReqWrap.oncomplete (fs.js:82:15)
Once, I thought that the “conventions” option was called “convention”, and was frustrated when my config didn’t make any difference. Then I finally found that pesky missing “s”.
Proposal
eslint and stylelint both validate their config files in an awesome way. They warn about unrecognized (misspelled) options, and make sure that the options are of the correct type.
Here are a few eslint errors:
Definition for rule 'comma-dangel' was not found
Configuration for rule "comma-dangle" is invalid:
Value "always-multilin" must be an enum value.
Configuration for rule "comma-dangle" is invalid:
Severity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed 'true').
stylelint:
Error: Undefined rule "selector-no-ids"
>> Invalid Option: Invalid option value "always-single-lines" for rule "selector-list-comma-space-after"
I think we should follow their lead! It’s definitely worth the extra code!
- Warn about unrecognized options.
- Error on invalid option values.
Environment
- Brunch: 2.6.5 (both globally and locally)
- Node: 5.9.1
- NPM: 3.7.3
- Operating system: Ubuntu 15.10
Issue Analytics
- State:
- Created 7 years ago
- Comments:7 (7 by maintainers)
Top GitHub Comments
@lydell the idea was that plugins shouldn’t depend on skemata directly, instead, Brunch will explicitly pass it. A few upsides I can see is that if there’s some bug in skemata, a new Brunch comes out with bumped skemata version and plugins work as expected.
Leaving the validation entirely to the plugins doesn’t seem very cool from where I stand. The idea is that the all the config schemas (core, plugins’) are merged into one, which ultimately means less false-negatives like (“you have
a2
, did you meana1
” — when there are both a1 and a2 keys handled by two different plugins) which will happen if there are separate schemas that are not aware of each other.I understand the current version of skemata might be slightly limiting… which is why we are not exposing it to plugins at the moment. It’ll get better with time and at some point we could allow developers to write their own validators, too, etc.
@paulmillr I think we can close this now.