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

Compress all files in the directory #18

Closed
pavelloz opened this issue Feb 26, 2018 · 24 comments
Closed

Compress all files in the directory #18

pavelloz opened this issue Feb 26, 2018 · 24 comments

Comments

@pavelloz
Copy link

I have a case where i would just like to apply cleancss to every file in the directory, without name changing etc.

Ideally this would work:

cleancss path/to/css/*.min.css

I know i can dance around i with xargs and thats what I'm going to do ATM, but i suppose it can be a pretty common use case so i decided to create an issue to hear what you think about it.

Thanks for the great tool :)

@pavelloz pavelloz changed the title Compress whole directory (or glob *) Compress all files in the directory (or glob *) Feb 26, 2018
@pavelloz pavelloz changed the title Compress all files in the directory (or glob *) Compress all files in the directory Feb 26, 2018
@jakubpawlowicz
Copy link
Collaborator

Thanks @pavelloz for an idea - I think it could either work by replacing files inline or by placing optimized output in a .min file, e.g.

cleancss --in-place path/to/css/(one|two).css would create two new files: path/to/css/one.min.css and path/to/css/two.min.css. Ideally it should respect existing .min files by overwriting them.

What do you think?

@pavelloz
Copy link
Author

pavelloz commented Mar 2, 2018

Well, replacing in-place would be even better, but listing all the files in arguments is still much harder than passing * or even straight up a directory name, which could be recursively traversed and .css files selected.

Having regexp-like syntax would force me to still go around and gather all the filenames without extension and build the string to be able to match all of them, so i would end up creating my own abstraction layer anyway, with recursive ls-all.

I think the most common way of using cli tools are actually (at least for me) two cases:

  1. npm scripts
  2. CI scripts

I have no idea if thats true, but in you 4.1 introduced -o with merging with *.css so i guess you had similar feeling that having the benefit of pattern matching it can be a huge time saver :)

The only difference is now skipping the -o, meaning: by default, override the file it was read from. Of course this would be a breaking change, so flag (ie. --in-place) is preferred.

PS. I think auto-renaming should be an opt-in, in below example it would ruin filenames for me (some files don't have min.css in filename and they are referenced that way somewhere beyond my control, so i would need to remove the .min suffix for those files :) )


I'll describe exact use case to bring some context and maybe it will be easier to abstract a general feature from that.

I have a project that has assets (not mine, half of them 3rd party, half of them minified), but i will be handing it over to someone else whose skills might vary (im responsible for assets preparing from source to target format in an efficient way and hopefully fast, reliable and cross browser), so I want to use micro-tools (cli as much as possible, as little as possible node programmatically) and small configs as much as i can to ease the pain for any future maintainer.

Example assets pipeline:
file.scss: sass cli -> css cp to dist/ -> postcss (with autoprefixer etc.) -> cleancss
file.es6: babel cli -> cp to dist/ -> uglifyjs

And all that handled by couple npm scripts.

Because all files from the build process land in dist/ folder i could do uglify for dist/js, cleancss for dist/css (hopefully recursively).

Because there wont be much of a nesting in dist/css, having *.css option would be enough for me, but i can easily see huge apps having multiple directories and needing recursive option.


Maybe i got carried away by all the 0 config idea that webpack is now implementing as well, but i just thought it would be cool to have a command: cleancss dist/css --in-place to cleancss every .css file in dist/css and doing it recursively with -r flag. :)

@jakubpawlowicz
Copy link
Collaborator

Thanks for detailed comment @pavelloz - I see your point here.

First using files explicitly in my example was only to illustrate the idea - clean-css-cli supports glob matching since e877d27. This may also save us from explicit -r option as one can say clean-css --in-place dist/css/*.css vs clean-css --in-place dist/css/**/*.css for flat vs recursive way.

In general I'm all for adding this feature.

@pavelloz
Copy link
Author

pavelloz commented Mar 5, 2018

Ouh, thats great, I didn't catch the glob change before :)

I hope it isn't just my weird use case and a lot of other users will also benefit from it while composing their assets processing.

Thank you :)

@mtsknn
Copy link

mtsknn commented Mar 12, 2018

I had a similar problem and found this issue, so +1 from me.

As a quick workaround I just installed foreach-cli package so I can do this:

foreach -g "./dist/css/*.css" -x "cleancss -O2 #{path} -o #{path}" --no-c

I'm on Windows so I had to use the --no-c param, otherwise I'd get an error.

@PatricNox
Copy link

PatricNox commented Aug 3, 2019

Well, I get that your input can be globed.

"cleancss": "cleancss -o public/merged.css public/assets/**/styles/*.css",

The neat npm script i'd like to have is something such as:

"cleancss": "cleancss -o public/assets/**/styles/*.css public/assets/**/styles/*.css",

so every corresponding file gets minified and don't need to be merged into a combined one. I know this is doable using gulp or grunt, but it's not my goal to use these. 🤔

mtsk's solution didn't work for me.
However, one from the referenced issue above did:

"css-minify-all": "foreach -g \"css/**/*.css\" -x \"cleancss --level 1 #{path} -o #{path}\" --no-c"

@onetrev
Copy link

onetrev commented Jan 9, 2021

Just to make sure, this issue is not about compressing all the files in the directory into a single output file, but rather each .css file in a directory (or multiple directories) into their own compressed files?

I would say @pavelloz you are definitely not alone in needing this workflow. For anyone working in WordPress (lots of people) and creating their own custom blocks with ACF (maybe not as many), this is exactly what you need. Each custom block is in it's own folder under template_parts/blocks so I need each .css file generated by my .scss in each folder minified. I can do something similar with my JS with uglifyjs-folder by doing:

uglifyjs-folder template-parts/blocks --pattern '**/*.js,!**/*min.js' -e -o template-parts/blocks

It would be great if cleancss could do the same. :) But in the meantime @pavelloz I was wondering if you have a rough example of how you are accomplishing this with xargs? Thanks!

@jakubpawlowicz
Copy link
Collaborator

Looks like this is a requested feature, let me have a look how to do it.

clean-css will be bumped to version 5.0 next week, so maybe it's a good time to include this feature in clean-css-cli v5 release.

@jakubpawlowicz
Copy link
Collaborator

Since clean-css v5.0.0 is out and there's a new batch option there clean-css/clean-css@d8380fe, I'll take on this feature next week.

@jakubpawlowicz
Copy link
Collaborator

Please check the main branch for the feature - there are two new options --batch and --batch-suffix.

The --batch option turns on batch processing, so you can run clean-css-cli like this:

cleancss --batch path/to/stylesheets/*.css

and all styles under that path will get optimized one by one.

The --batch-suffix option specifies what gets added to input filename (without extension) in batch mode, e.g.

cleancss --batch --batch-suffix '.min' path/to/stylesheets/*.css

will optimize path/to/stylesheets/reset.css to path/to/stylesheets/reset.min.css.

The default for --batch-suffix option is '-min'.

@jakubpawlowicz
Copy link
Collaborator

@PatricNox @onetrev I'd love your feedback on this.

@onetrev
Copy link

onetrev commented Feb 6, 2021

Hey @jakubpawlowicz thanks so much for doing this! I have some feedback, actually I'm having some issues. This is what I'm finding...

  1. If I don't put --batch-suffix then I get an error: "error: unknown option --batch". Not a biggie as I want to change it to .min anyway.

  2. With batch-suffix option in place it works, but only if I output to screen (no -o command). I'm using this:

cleancss --batch --batch-suffix '.min' template-parts/blocks/**/*.css

  1. If I put in the -o option then it chucks some JS errors. I'll send those along if you want those.

Hopefully this is not me missing something obvious. Let me know if I can help test anything further.

@jakubpawlowicz
Copy link
Collaborator

Hey @onetrev - thanks for testing! Just to make sure we are on the same page:

  1. You checked out latest main branch and ran those code snippets against them, right?

  2. What system did you run them on?

  3. Please send those JS errors when -o is used.

Do you think --batch-suffix should default to -min or sth else?

@onetrev
Copy link

onetrev commented Feb 6, 2021

No worries, happy to help! And yes good call to double check these details.

  1. I'm using [email protected] as a global package.

  2. I'm on Windows 10, but using WSL2 using a Ubuntu distro. So in reality I'm running Ubuntu 20.04.1 LTS

  3. Error output below...

cleancss -o --batch --batch-suffix '.min' template-parts/blocks/blockname/*.css
internal/fs/utils.js:620
    throw new ERR_INVALID_ARG_TYPE(propName, ['string', 'Buffer', 'URL'], path);
    ^

TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string or an instance of Buffer or URL. Received type boolean (true)
    at Object.openSync (fs.js:468:10)
    at Object.writeFileSync (fs.js:1467:35)
    at output (/home/onetrev/.nvm/versions/node/v14.15.4/lib/node_modules/clean-css-cli/index.js:323:8)
    at /home/onetrev/.nvm/versions/node/v14.15.4/lib/node_modules/clean-css-cli/index.js:266:7
    at /home/onetrev/.nvm/versions/node/v14.15.4/lib/node_modules/clean-css-cli/node_modules/clean-css/lib/clean.js:125:9
    at /home/onetrev/.nvm/versions/node/v14.15.4/lib/node_modules/clean-css-cli/node_modules/clean-css/lib/reader/read-sources.js:26:64
    at loadOriginalSources (/home/onetrev/.nvm/versions/node/v14.15.4/lib/node_modules/clean-css-cli/node_modules/clean-css/lib/reader/load-original-sources.js:26:5)
    at /home/onetrev/.nvm/versions/node/v14.15.4/lib/node_modules/clean-css-cli/node_modules/clean-css/lib/reader/read-sources.js:26:14
    at applySourceMaps (/home/onetrev/.nvm/versions/node/v14.15.4/lib/node_modules/clean-css-cli/node_modules/clean-css/lib/reader/apply-source-maps.js:34:5)
    at Object.callback (/home/onetrev/.nvm/versions/node/v14.15.4/lib/node_modules/clean-css-cli/node_modules/clean-css/lib/reader/read-sources.js:25:12) {
  code: 'ERR_INVALID_ARG_TYPE'
}

Personally I think I see minimized files as .min more often than -min, so I would say .min should be the default, but not a big deal either way. The bigger problem was I received the error mentioned in my previous message if I didn't set a --batch-suffix value.

@PatricNox
Copy link

PatricNox commented Feb 7, 2021

Hej @jakubpawlowicz, this is exactly what I was looking for and now is the "core way" replacement of my previous script:

"css-minify-all": "foreach -g "css/**/*.css" -x "cleancss --level 1 #{path} -o #{path}" --no-c"

to

cleancss --batch resources/sass/themes/*.scss

I like the argument names as well, as it's clear what's to be happening.

@jakubpawlowicz
Copy link
Collaborator

Glad it works for you, @PatricNox!

@onetrev I think you need to clone this repo in order to test it before 5.0 release, here's how to do it: https://github.com/jakubpawlowicz/clean-css-cli#how-to-get-started

Once you have it locally and after npm install just replace cleancss in command you issue with path/to/checked/out/repo/bin/cleancss and you should be in the right place to start testing it.

If you need any help just let us know.

@onetrev
Copy link

onetrev commented Feb 9, 2021

Awesome, works perfectly. Very exciting this addition does exactly what I need. I'm sure it will help many others too. A bit embarrassing I didn't realise v5 wasn't released yet. I was just so excited to try it out I guess. And I saw the v5.0 details in the docs of the repo so made the assumption. Totally my bad.

@jakubpawlowicz
Copy link
Collaborator

@onetrev Awesome, thanks for giving it a try. I've realised the description in Readme is a bit misleading as v5 is not released yet, so I should phrase v5 changes section a bit differently. Sorry, my bad!

Expect v5 to land on npm tomorrow.

@jakubpawlowicz
Copy link
Collaborator

Thanks a lot for testing and your patience on this! v5 is on npm now. 🎉

@BenediktBergmann
Copy link

BenediktBergmann commented Feb 16, 2021

@jakubpawlowicz is there a way of omitting the suffix?

I would like to have the same filename after clean-css was run. So when I have a demo.css file it should be still demo.css after minifying. At the moment it adds "-min" when I don't have the "--batch-suffix" parameter and I can't find a way of telling it to not add a suffix at all.

@jakubpawlowicz
Copy link
Collaborator

Sorry @BenediktBergmann I missed your comment. Please use --batch-suffix '' to write output under same file name as input. Shall we change the docs to list such use case?

@PatricNox
Copy link

@jakubpawlowicz That's probably a good idea as it may otherwise be treated as diverted

@jakubpawlowicz
Copy link
Collaborator

@PatricNox added in 3a6f98f

@Dynamo6Dev
Copy link

I'm using v5.3.2 on Windows 10 with Node 20 and --batch-suffix '' doesnt work for me - it puts apostrophes into the generated filenames. I've found that switching to --batch-suffix "" fixes that problem.

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

No branches or pull requests

7 participants