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

Common configs #477

Closed
MoOx opened this Issue Aug 5, 2015 · 143 comments

Comments

Projects
None yet
@MoOx
Contributor

MoOx commented Aug 5, 2015

I just read the thread about the upcoming Babel 6.0 babel/babel#2168

tl;dr: Instead of being something similar to cssnext, Babel will become an engine, like PostCSS.

I think this is a really nice road. PostCSS is already on it, so it's awesome. I was trying hard to make cssnext THE solution, but I guess I failed, people like modularity (and don't care that much about standard).
cssnext has too many problem to handle with potential specs changes (that's why Babel is moving from a solution with many transformers to none).

The idea of preset for Babel seems really the way to go ("preset-es2015" ❤️). The thing is, cssnext can't do that, because csswg is working on different modules. So I guess it's time to think about deprecating cssnext.
The thing I love in both cssnext and babel is that they have a cli builtin and an easy management for conf (.babelrc, I am currently working on .cssnextrc - but I am not sure I should finish my work).
What I am offering here (and really think it will be just awesome for PostCSS) is to bring you back my work to easily add a CLI builtin + a .postcssrc.
Direct benefits are:

  • cli builtin is a really nice thing, especially to share postcssified code (this will easily solve #434) because this way, you can add a prepublish hook to publish transformed code to npm for example.
  • all postcss runners will have less work to do (every plugins might be defined in .postcssrc) and PostCSS will handle a same config the same way from all runners. This is a great added value we can bring.

This will not require a lot of code in postcss because work is already done as separate module (or will be in a couple of days):

  • a recently made a ._rc loader that support YAML, JSON and JavaScript ! (module.exports = {/_config*/} like webpack, very nice to configure plugins) https://github.com/MoOx/rc-loader
  • I am exporting the cli+watcher of cssnext for stylelint (see stylelint/stylelint#288) as a standalone module, so using this into PostCSS will probably be just a small file of javascript.

Discussion is open !

@MoOx

This comment has been minimized.

Contributor

MoOx commented Aug 5, 2015

Sidenote: I will need to think a bit more about what cssnext can become (a preset, but like I said, not easy to handle...) or if I should just deprecate it with a ready to use .postcssrc as a replacement :)

@ai

This comment has been minimized.

Member

ai commented Aug 6, 2015

Babel has 2 projects: babel and babel-core.

We can have same 2, but with different names: postcss-cli and postcss. I think main problem is slow development and ideas stagntation of PostCSS CLI. I am really disappointed: no promotion, no development, unfixed big features. @pirxpilot

@ai ai added the question label Aug 6, 2015

@MoOx

This comment has been minimized.

Contributor

MoOx commented Aug 6, 2015

2 packages on npm. Babel have all source code in one repo https://github.com/babel/babel/tree/master/packages (babel-cli is babel on npm and babel is babel-core on npm).
And most people just npm install babel. That's an important point to think about. CLI by default.
I was talking about something bigger than just a cli anyway.
You cannot blame postcss-cli creator. He is not responsible of anything except what he created that probably works for him the way it is. Here I am talking (and asking) about handling things in a better way, in order to provide a better and more complete UX.

@MoOx

This comment has been minimized.

Contributor

MoOx commented Aug 9, 2015

Nobody thing these 2 things should be in core (cli + config file)?

@ben-eb

This comment has been minimized.

Member

ben-eb commented Aug 9, 2015

Looks good to me, I don't really have anything to add to this.

@magsout

This comment has been minimized.

Member

magsout commented Aug 9, 2015

Nobody thing these 2 things should be in core (cli + config file)?

👍

it's a very good idea.

@ai

This comment has been minimized.

Member

ai commented Aug 9, 2015

Maybe we can do it as part of 6.0 splitting PostCSS to seperated project.

But, do CLI tool is popular? I think most of users use Gulp/Webpack plugins.

@davidtheclark

This comment has been minimized.

Contributor

davidtheclark commented Aug 9, 2015

I always like it when tools have their own CLI. I can create projects with browserify, karma, tape, eslint, etc., without having to create a gulpfile. gulp-postcss has been great; but very often I've found that the intermediary of a gulp/whatever plugin adds bugs and annoyances. It all depends on the project, but I like being able to use both approaches.

@ai

This comment has been minimized.

Member

ai commented Aug 9, 2015

@davidtheclark but right now you can use postcss-cli for CLI.

@davidtheclark

This comment has been minimized.

Contributor

davidtheclark commented Aug 9, 2015

That's true. I'm fine either way, just throwing in my 2 cents — that I like the common practice of the canonical installation of a tool including the CLI, which I thought is what @MoOx is suggesting.

Also, I think that if there's any discrepancy between what you, @ai, want the CLI to be and what it actually is, then that would be good reason to take it into the core project and make sure that it always represents the best capabilities of PostCSS. I'm accustomed to the CLI and the JS API being the canonical interfaces for tools, the reliable ways to use them without any chance of middleman bugs; whereas gulp/grunt/etc. plugins may be more or less reliable, depending on the maintainers.

All that said, I understand the desire to keep things separate and have other maintainers, etc., so I'd repeat that I'd be pleased either way. :)

@ai

This comment has been minimized.

Member

ai commented Aug 10, 2015

@bdkjones you told, that you didn’t like postcss-cli. Can you explain us why? Your feedback ill be very useful for new CLI.

@MoOx

This comment has been minimized.

Contributor

MoOx commented Aug 10, 2015

FYI, it's almost done (as a separate module). I will push a PR soon to include the module + the module for .postcssrc

  config: [
    "-c, --config <file>",
    "use the config file",
  ],
  verbose: [
    "-V, --verbose",
    "verbose output (only when --out-file or --out-dir are used)",
  ],
  watcher: [
    "-w, --watch",
    "watch the input files for changes",
  ],
  outFile: [
    "-o, --out-file [out]",
    "Compile all input files into a single file",
  ],
  outDir: [
    "-d, --out-dir [out]",
    "Compile an input directory of modules into an output directory",
  ],

There will be also -v/--version and -h/--help and it will support stdin/stdout so people can use unix pipe :)

@ai

This comment has been minimized.

Member

ai commented Aug 10, 2015

@MoOx awesome. .postcssrc will be a CommonJS module like in webpack?

@ai

This comment has been minimized.

Member

ai commented Aug 10, 2015

@MoOx also we need source map options

@MoOx

This comment has been minimized.

Contributor

MoOx commented Aug 10, 2015

.postcssrc will use this rc-loader https://github.com/MoOx/rc-loader that support YAML/JSON/Common JS.
Yeah we might also add support for some postcss related option like sourcemap. But not directly in the module I am writing ;)

@bdkjones

This comment has been minimized.

bdkjones commented Aug 10, 2015

The real trouble is that this is a solution in search of a problem. You're adding a needless layer of abstraction on top of various tools like Autoprefixer.

Folks already have places that they configure their projects. For my users, that in's an app. For people on Grunt or Gulp, that's in their gruntfile. No one wants another hidden configuration file named .postcssrc. People want to integrate the configuration of things like Autoprefixer into their existing configurations.

It seems like you guys are trying to create your own competitor to the Grunt/Gulp environment, which is a really bad idea because (a) the existing systems are really good and (b) that's a bunch of duplicated effort that could be spent on better things.

Now, I understand that the idea behind this thing is that all the smaller "PostCSS" stuff could use this single CLI wrapper. And that's fine. But the major tools like Autoprefixer should be usable with or without this CLI wrapper.

@ai

This comment has been minimized.

Member

ai commented Aug 10, 2015

@bdkjones cssnext and cssnano have separated CLI. But I am too tired on two projects. So I try to move some task to community projects.

Of course, I think that Grunt and Gulp users should be able use PostCSS without .postcssrc.

@ai

This comment has been minimized.

Member

ai commented Aug 10, 2015

@bdkjones so, what do you need from PostCSS CLI to use it in CodeKit? As I remember some users ask about PostCSS support in CodeKit. Also I will not have time for Autoprefixer CLI.

@MoOx

This comment has been minimized.

Contributor

MoOx commented Aug 11, 2015

@bdkjones the idea here is just to ADD (not replace) another way to use postcss (mainly the cli).
All serious tools have their own cli (eg: babel have one) and this help to tests and/or publish things.
(Btw, more and more people are ditching task runners to use simpler workflow using npm scripts only.)
So having an official cli is a must have for me.

.postcssrc will be another way to configure your postcss workflow. This means that if you switch from grunt to gulp, you won't have to update your task, just relpace the simple wrapper, without the need to adjust your configuration. Same thing here, all serious tools provide a way to configure using a file (babel does, eslint does, so many example out there). Obviously you will be able to NOT use this and configure like you currently does, using the JS api directly.

So here there is not breaking changes, just sugar.

@codemakerlive

This comment has been minimized.

codemakerlive commented Aug 18, 2015

@MoOx Do you have any anticipation as to when your rc-loader (+ ,postcssrc) and CLI will be in PostCSS? Very much looking forward to official inclusion of these kinds of interfaces.

@MoOx

This comment has been minimized.

Contributor

MoOx commented Aug 18, 2015

Probably at the end of August or in the beginning of September. Should be a minor change (feature added, not a breaking change), so minor release should works.

@codemakerlive

This comment has been minimized.

codemakerlive commented Aug 18, 2015

Thanks, I was just about to edit my above to add...

I'm curious if/how you forsee the CLI differing from https://github.com/code42day/postcss-cli

@michael-ciniawsky

This comment has been minimized.

michael-ciniawsky commented May 27, 2016

both :) the extend in root config given the path of the local config is the index placeholder (entry point), from where the plugins from local config(s) (one extend per config) will be push in.

@michael-ciniawsky

This comment has been minimized.

michael-ciniawsky commented May 27, 2016

in local configs the extend option can take to values extend: path/of/config # root by default and extend: false # use just this config

@ai

This comment has been minimized.

Member

ai commented May 27, 2016

@michael-ciniawsky so it is like a placeholder to be filled in some other config? Nice idea! Really instersting way.

But I just remembered important thing. We want to make PostCSS order-free in next 6.0 release. So plugin order is not really important.

What if we create a simple solution without extend right now, and then implement it in future version? We will have more feedback to do it correctly.

“Minimum value product” and “Getting Real” ideas are important!

@michael-ciniawsky

This comment has been minimized.

michael-ciniawsky commented May 27, 2016

But I just remembered important thing. We want to make PostCSS order-free in next 6.0 release. So plugin order is not really important.

I didn't know about that, awesome that eases things alot. 👍
Well, then the placeholding part lived short and partied hard :D

Are there some resources / discussions how this works, it's off topic but maybe of use for PostHTML (by the way there should by more 'getting together' anyways imho) :)

@michael-ciniawsky

This comment has been minimized.

michael-ciniawsky commented May 27, 2016

+1 for making this working the rigth way from the start no need to rush.

@davidtheclark

This comment has been minimized.

Contributor

davidtheclark commented May 27, 2016

I'm unclear on where you two have settled — extends, cascading configs, or both? (By "cascading configs" I mean that first/second/config.json automatically extends & overrides first/config.json, which extends & overrides ./config.json.)

But I can clarify that neither of those is currently supported by cosmiconfig out-of-the-box. I wrote the pieces of cosmiconfig that I knew stylelint needed and I knew other projects could use out of the box. So cosmiconfig now just finds and parses configs of various formats in standard places. (You can specify where the search should start from (cwd option), so you could do a separate search for each directory containing CSS files, if you wanted to.)

I have not yet had input from people doing other projects who want additional features in cosmiconfig, so the extra features that stylelint needed I built into stylelint.

For stylelint we decided that we would rather have extends than cascading configs. You can do the same thing with extends that cascading configs allow, but extends are also more flexible and powerful — so why not just stick with extends? Here is the code that implements extends in stylelint: https://github.com/stylelint/stylelint/blob/master/src/buildConfig.js#L137. If you are interested, we could try to figure out a way to genericize that and bring it into cosmiconfig so postcss can use it.

@michael-ciniawsky

This comment has been minimized.

michael-ciniawsky commented May 27, 2016

I'm unclear on where you two have settled

@davidtheclark You're not alone i think we currently settled nowhere :) discussion is open improve until all concerns are rendered silent and best solution is found.

I have not yet had input from people doing other projects who want additional features in cosmiconfig, so the extra features that stylelint needed I built into stylelint.

I think same should be done by PostCSS, it's a specific issue. But not my piece of the pie :)

Here is the code that implements extends in stylelint: https://github.com/stylelint/stylelint/blob/master/src/buildConfig.js#L137.

👍

@ai

This comment has been minimized.

Member

ai commented May 28, 2016

@michael-ciniawsky

Well, then the placeholding part lived short and partied hard :D

If you really want a placeholder feature, let’s change the API to more clear one.

package.json:

{
  plugins: [
    { placeholder: 'beginning' },
    { autoprefixer: null },
    { placeholder: 'afterPrefixes' }
  ]
}

dir/postcss.js:

{
  extend: '../',
  placeholders: {
    beginning: {
      cssnext: null
    },
    afterPrefixes: {
      cssnano: null
    }
  }
}

But I am really think that we should not implement it right now. We should have simple solution first and extend it on real feedback.

If we will implement some feature, we need support it until major release. And people always hate broken API. So if we don’t really need placeholders in future, we should not implement it, so users will not change API and our code will be clear.

@ai

This comment has been minimized.

Member

ai commented May 28, 2016

@voischev does PostHTML has some standard config? Are you interesting of having same config principles with PostCSS? What you think about out latest idea and that placeholders?

@michael-ciniawsky

This comment has been minimized.

michael-ciniawsky commented May 28, 2016

@voischev does PostHTML has some standard config? Are you interesting of having same config principles with PostCSS? What you think about out latest idea and that placeholders?

Nope :( sadly, it's currently rejected, to keep the core simple #141. But maybe could be reconsidered @voischev :D?

But I am really think that we should not implement it right now. We should have simple solution first and extend it on real feedback.

:+1 Load various common configs from root to start with, extending or cascading is a progressive enhancement.

module.exports = {
  extend: true/false // true extend root config on given position, false just use this config ignore root
  plugins: {}
}

@use plugin for plugins local to just one file would also be an option, maybe simpler, and in root you set the options for that

@use plugin // @extend plugin // @local plugin

.css {}

common config*

module.exports = {
  plugin1: null,
  use: { plugin: {options} }, // use when @use plugin in file found
  plugin2: null
}
                                       // main chain
postcss().process..... => [plugin1(), use(),      plugin2()]   => result.css
                                        |              |
                            //use chain |              |
                            postcss([ use1() ]). process...

Like spawning child_processes, x in y subdir declared postcss.config.js files will be avoided => one place where all config takes place

@ai

This comment has been minimized.

Member

ai commented May 28, 2016

@michael-ciniawsky ouh, postcss-use is for next iteration too. Let’s make first config simple, just to solve current problem. Could you update purposal docs to see our final stage?

@michael-ciniawsky

This comment has been minimized.

michael-ciniawsky commented May 28, 2016

yeap :) its was just an attempt for @-rule-syntax extends as second option to additional postcss.config.js files. But let's focus on the common config first, before i scratch your nerves to dust completely :+1 👯

@michael-ciniawsky

This comment has been minimized.

michael-ciniawsky commented May 28, 2016

@ai

This comment has been minimized.

Member

ai commented May 28, 2016

@michael-ciniawsky

Plugin names are without the postcss- prefix.

  1. How did you understand that autoprefixer is just autoprefixer and not postcss-autoprefixer? ;) What about cssnext and postcss-cssnext which are exist together? ;)

Plugin names containing an hyphen must use camelCase.

  1. I think it is too tricky. We have hyphens in dependencies. It easy to copy plugin name and paste to Google.
  2. Why you put plugins to the root of config? Where we will put options like syntax or map? What do you think about:
{
  "parser": "sugarss",
  "plugins": {
    "postcss-inline-svg": null,
    "postcss-assets": null,
    "postcss-cssnext": null
  }
}
@michael-ciniawsky

This comment has been minimized.

michael-ciniawsky commented May 28, 2016

As i understand autoprefixer is based on postcss and can be used standalone or as 'plugin' in your plugin chain? Depends on how you like to use it, if in config no plugins.key (eg. plugins.autoprefixer, plugins.cssnext) is set nothing will be loaded. You can use unprefixed names which will be reprefixed when inclusion in deps will be checked or you leave them prefixed from the start.

// Config
// {
//    import: {path: './css/, endcoding: 'utf8'},
//    bem: {style: 'bem'},
//    cssnano: null
// }
//
// deps = pkg.dependencies
// devDeps = pkg.devDependencies

//.. somewhere in load.es6

function prefix (plugin) {
   return `postcss-${plugin}`
}

let plugins = []

Object.keys(plugins).forEach((key) => {
    // Filter for prefixed plugins (e.g postcss-bem, postcss-cssnext) in pkg.deps/devDeps
    if (deps[prefix(key)] || devDeps[prefix(key)]) {
      plugins.push(new Plugin(prefix(key), options[key])) 

      // =>  [ 
              require('postcss-import')({path: './css/', encoding: 'utf8'}), 
              require('postcss-bem')({style: 'bem'})
             ]
    }

    // Filter for unprefixed plugins (e.g autoprefixer, cssnext cssnano) in pkg.deps/devDeps
    if (deps[key] || devDeps[key]) {
      plugins.push(new Plugin(key, options[key]))

      // =>  [ 
              require('postcss-import')({path: './css/', encoding: 'utf8'}), 
              require('postcss-bem')({style: 'bem'}), 
              require('cssnano')() 
             ]
    }

  })
  return plugins
@ai

This comment has been minimized.

Member

ai commented May 28, 2016

@michael-ciniawsky and why we need this logic with postcss- autprefixing?

@michael-ciniawsky

This comment has been minimized.

michael-ciniawsky commented May 28, 2016

to write keys like bem: null instead of "postcss-bem": null in your config. In the deps the name is "postcss-bem": x.y.z just bem would not be found in the deps on checking.

// keys coming from config => ['import', 'bem']
// prefix for deps check
function prefix (key) {
   return `postcss-${key}`
  // => ['postcss-import', 'postcss-bem']
}

If the plugins.key is prefixed 'postcss-bem': null the match would be found during the unprefix check.

but writing 'postcss-xxx' : null everytime is redundant chore work => automate that away :)

{
  "parser": "sugarss",
  "plugins": {
    "inline-svg": null,
    "assets": null,
    "cssnext": null    // would match either/both cssnext or/and postcss-cssnext 
                       // when both are used with different options, for whatever reason ,  
                       // then just set 2 different keys
                       // => 'postcss-next': options,
                       //    'cssnext':  options
  }
}
  1. Why you put plugins to the root of config? Where we will put options like syntax or map? What do you think about:
{
  "parser": "sugarss",
  "plugins": {
    "postcss-inline-svg": null,
    "postcss-assets": null,
    "postcss-cssnext": null
  }
}

? :D i thought the options should not be in the config, could be there of course, i removed that from a previous version of the propsal

@ai

This comment has been minimized.

Member

ai commented May 28, 2016

@michael-ciniawsky let’s me show 5 examples, why assets is worse, than postcss-assets:

  1. What if user have cssnext and postcss-cssnext is project (legacy code and new code)?
  2. assets could by in package.json too. Not as PostCSS plugin, but as some npm library. So that code will not save us from name conflicts.
  3. If I find some new plugin in config, I can’t just copy name to Google. I need to use complicated algorithm with package.json dependencies to understand is is just assets or it will be postcss-assets.
  4. With assets we need more text in docs. New user will not understand how it works. It can’t change/read config without reading a docs about config.
  5. This autoprefixing algorithm is too complicated. Simple things are always better than complicated.

And for this 5 problems we have only 1 benefit — less symbols in config. I think it is not good deal 5 bad things vs. 1 good ;).

@michael-ciniawsky

This comment has been minimized.

michael-ciniawsky commented May 28, 2016

  1. What if user have cssnext and postcss-cssnext is project (legacy code and new code)?

Both would work, depends on how it's listed in the config and installed as dependency

2 assets could by in package.json too. Not as PostCSS plugin, but as some npm library. So that code will not save us from name conflicts.

When prefixed check matches => don't check unprefixed.

But...you're right, i'm 'afraid' that's the show stopper :)

  1. If I find some new plugin in config, I can’t just copy name to Google. I need to use complicated algorithm with package.json dependencies to understand is is just assets or it will be postcss-assets.
  2. With assets we need more text in docs. New user will not understand how it works. It can’t change/read config without reading a docs about config.

Maybe, for the future => no google searching necessary at all 👍 :) but thats a different topic

$ postcss  --help | --usage  # lists PostCSS README from npm, or something like that
$ postcss plugin --help | --usage  # lists Plugin README from npm, or something like that
  1. This autoprefixing algorithm is too complicated. Simple things are always better than complicated.

i will by no means insist on this, we can leave it. It's not that killer feature anyway.

@ai

This comment has been minimized.

Member

ai commented May 28, 2016

Let’s keep full name, you can use some custom config preprocessor if you want to keep them short :)

@michael-ciniawsky

This comment has been minimized.

michael-ciniawsky commented May 28, 2016

yeap, can i assume we settle on this now for the moment,

Cosmiconfig Config Names
-package.json
-postcssrc.json
-postcss.config.js

Config Style

{
  parser: 'whatever'
  map: 'however'
  plugins: {
    'postcss-plugin': null
    'postcss-plugin2': {/* options */}
    'cssnext': {}
}

? :) i will develop it here here and here as plugins first, when working see if,how,when to implement in postcss . 👍?

@ai

This comment has been minimized.

Member

ai commented May 28, 2016

Yeap, create a some playground tools first and them move implementation to core is awesome idea.

So we will get first feedback before we freeze API.

@michael-ciniawsky

This comment has been minimized.

michael-ciniawsky commented May 28, 2016

yeap exactly :). lf not directly into postcss core for the moment the repos will transfered to the org when ready and you or someone from postcss can publish them to npm.

result should look like this:

import postcss from 'postcss'

import plugins from 'postcss-load-plugins'
import options from 'postcss-load-options'
// maybe import { plugins, options } from 'postcss-load-config' but let's discuss that later :)

postcss(plugins()).process(css, options())...

kk i'm back here when i actually can show something.
Thank you for your the time and patience sketching this out 👍

@michael-ciniawsky

This comment has been minimized.

michael-ciniawsky commented Jun 1, 2016

postcss-load-plugins Plugins only
postcss-load-options Options only

Available on npm for testing:
postcss-load-config Plugins && Options

Currently all alpha, e.g the return of a promise is subject to change in my opinion.

const postcss = require('postcss')
const postcssrc = require('postcss-load-config')

postcssrc().then(( { plugins, options } ) => {  
  postcss(plugins)
   .process(css, options)
   .then((result) => console.log(result.css))
})
@ai

This comment has been minimized.

Member

ai commented Jul 16, 2018

Common config was created and implemented in most of runners

@ai ai closed this Jul 16, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment