Conditional compilation in CoffeeScript/UglifyJS

2019-03-13 01:09发布

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?

4条回答
该账号已被封号
2楼-- · 2019-03-13 01:45

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()
查看更多
Rolldiameter
3楼-- · 2019-03-13 02:03

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 #.

查看更多
淡お忘
4楼-- · 2019-03-13 02:03

I use https://github.com/jsoverson/grunt-preprocess for this kind of thing. It fit exactly with what I'm trying to do:

detect_ennemy_collision: (ennemies) ->

# @ifdef DEBUG 
    expect(ennemies).to.be.an 'array'
    expect(ennemies.length).to.be.ok

    for ennemy in ennemies
        (expect ennemy).to.be.an.instanceof Character

# @endif
#...
查看更多
霸刀☆藐视天下
5楼-- · 2019-03-13 02:08

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.

查看更多
登录 后发表回答