Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional compilation in CoffeeScript/UglifyJS

Using Coffeescript I need to have a go through a build script anyway to update my .js files, and I have two of them, one for debugging and one for production (one uses Uglify to minimize the files, one does not). So I was thinking that it would be convenient to have some conditional compilation as well, with code that only enters the debug build.

What is the easiest way to achieve this, ideally controlled by a simple command line switch that I can give to either coffee or uglify?

like image 344
Thilo Avatar asked Mar 14 '12 02:03

Thilo


3 Answers

If you're writing a build script anyway, you can add a preprocessor step to it. Since CoffeeScript uses # to denote comments, the C preprocessor seems like a good choice. You can denote debug code with #ifdefs:

some code...
#ifdef DEBUG
debug code...
#endif

Then, you can preprocess the debug version with cpp -E -Xpreprocessor -DDEBUG <filename> -o <outfile> and compile <outfile> with CoffeeScript. Similarly, preprocess the production version with cpp -E <filename> -o <outfile>.

Edit: This one's tough, because it means any CoffeeScript comments that are not indented will break the preprocessing step. Not sure how much of a problem this is to you. For example,

code...
#comment about the code

will break the build, but

code...
  indented code...
  #indented comment

will work fine, because the preprocessor doesn't look at lines unless their first character is a #.

like image 58
Aaron Dufour Avatar answered Sep 27 '22 16:09

Aaron Dufour


It sounds to me like you're saying that you have two build scripts? For string.js, I just use a Cakefile to achieve what you I think that you want. Essentially, if the source file changes, it produces a regular JS file and then an uglified file.

Here is the relevant portion of the Cakefile:

 task 'watch', 'Watch src/ for changes', ->
    browserTestFile = path.join(process.cwd(), 'test_browser', 'string.test.js')

    coffee = spawn 'coffee', ['-w', '-c', '-o', 'lib', 'src']
    coffee.stderr.on 'data', (data) -> 'ERR: ' + process.stderr.write data.toString()
    coffee.stdout.on 'data', (data) ->
      d = data.toString()
      if d.indexOf('compiled') > 0
        #invoke 'test'

        fsw = fs.createWriteStream(browserTestFile, flags: 'w', encoding: 'utf8', mode: 0666)
        coffee_test = spawn 'coffee', ['-c', '-p', 'test/string.test.coffee']
        coffee_test.stdout.pipe(fsw, end: false)

        uglify = spawn 'uglifyjs', ['lib/string.js']
        uglify.stdout.pipe(fs.createWriteStream('lib/string.min.js'))

      else
        growl(d, title: 'Error', image: './resources/error.png')

      process.stdout.write data.toString()
like image 44
JP Richardson Avatar answered Sep 27 '22 18:09

JP Richardson


An alternative to the C preprocessor would be the M4 macro processor (Wikipedia intro). I haven't used it myself so I can't review it and I know it's supposed to be somewhat of a pain but it would solve your problem. Also it, like the C preprocessor, runs on every OS conceivable.

like image 30
Jacob Oscarson Avatar answered Sep 27 '22 16:09

Jacob Oscarson