Robert K. Bell Robert K. Bell - 2 months ago 17
Less Question

How to autoprefix css files generated by less, in Webstorm?

I've got Webstorm 7 (on Win7) compiling my .less files into minified css with sourcemaps (using lessc on nodejs v0.10.26, run from a File Watcher in Webstorm), and I can then run autoprefixer on that generated css to automatically insert vendor prefixes.

What I'm not sure how to do, is combine the two steps. Is it possible to chain File Watchers in Webstorm?

Possible approaches:

  • Create a batch script that is called from the file watcher, then calls less and autoprefixer in sequence.

  • Create a node.js script/module that calls less, then autoprefixer.

  • Have the less transpiler output the css with a custom extension (e.g., .unprefixedcss), then have a File Watcher specifically for that extension.

  • Something I'm missing?


I tried the batch script approach with a python script, called from a single File Watcher:

#!/usr/bin/env python


Chains less and autoprefixer, to produce a minified, vendor-prefixed css file.

# TODO: move config data to a config file
# TODO: delete the intermediate files generated by less

import argparse
import os
import subprocess
from pprint import pprint as pp

# Config data
node_folder = r'C:/Users/ClementMandragora/AppData/Roaming/npm'
less_script = os.path.join(node_folder, 'lessc.cmd')
autoprefixer_script = os.path.join(node_folder, 'autoprefixer.cmd')

parser = argparse.ArgumentParser()
parser.add_argument("--file-name", help="filename, not including the extension", required=True)
parser.add_argument("--working-dir", help="the directory to do the work in", required=True)
args = parser.parse_args()


print('CWD: {c}\n'.format(c=os.getcwd() + '\n'))

print('Running less-css...')

# Compile and minify the less file to css.
# Include a sourcemap.
exitcode = subprocess.Popen([
    '{n}.less'.format(n=args.file_name),  # source
    '{n}.min.css'.format(n=args.file_name)  # dest
], cwd=args.working_dir).wait()

assert exitcode is 0, 'Nonzero return code from less! Got: {r}'.format(r=exitcode)
print('less compilation completed.\nRunning autoprefixer...')

# Run autoprefixer over the result from lessc.
exitcode = subprocess.Popen([
    '{n}.prefixed.min.css'.format(n=args.file_name),  # dest
    '{n}.min.css'.format(n=args.file_name)  # source
], cwd=args.working_dir).wait()

assert exitcode is 0, 'Nonzero return code from autoprefixer! Got: {r}'.format(r=exitcode)

print('autoprefixer completed.\nFinal filename is {n}.prefixed.min.css'.format(n=args.file_name))

It worked, but seemed unwieldy.

Next attempt was having multiple file watchers; it turns out that have autoprefixer watch for changes to css files, then generate another css file, results in a loop.

So I created a custom File Type in Webstorm for files matching *.min.css (the output of the less transpiler), then created a File Watcher for that extension. The other differences from the default/included less File Watcher are:

  • Program: C:\Users\ClementMandragora\AppData\Roaming\npm\autoprefixer.cmd
  • Arguments: -o $FileNameWithoutExtension$.prefixed.css $FileName$
  • Output paths to refresh: $FileNameWithoutExtension$.prefixed.css:$FileNameWithoutExtension$

It wasn't initially clear to me that the 'Output paths to refresh' also signal Webstorm to parent the generated files under the main *.less file, reducing project clutter. (I'm keeping source and output in the same folder.)