11

Использование Coffeescript Мне нужно пройти скрипт сборки, чтобы обновить мои .js-файлы, и у меня есть два из них: один для отладки и один для производства (один использует Uglify для минимизации файлов, а другой нет). Поэтому я думал, что было бы удобно иметь некоторую условную компиляцию, а также код, который входит только в сборку отладки.Условная компиляция в CoffeeScript/UglifyJS

Что такое самый простой способ достичь этого, идеально управляемый простым переключателем командной строки, который я могу дать либо кофе, либо угадать?

ответ

7

Если вы пишете сценарий сборки в любом случае, вы можете добавить шаг препроцессора к нему. Поскольку CoffeeScript использует # для обозначения комментариев, препроцессор C кажется хорошим выбором. Вы можете обозначить отладочный код #ifdef с:

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

Затем вы можете препроцессировать отладочную версию с cpp -E -Xpreprocessor -DDEBUG <filename> -o <outfile> и компилировать <outfile> с CoffeeScript. Аналогичным образом, предварительная обработка производственной версии с cpp -E <filename> -o <outfile>.

Редактировать: Это сложно, потому что это означает, что любые комментарии CoffeeScript, которые не имеют отступов, прервут шаг предварительной обработки. Не знаете, какая проблема для вас. Например,

code... 
#comment about the code 

сломается сборки, но

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

будет работать нормально, потому что препроцессор не смотрит на линии, если их первый символ не является #.

+1

Мне нравится эта идея, хотя вы должны быть осторожны, чтобы не включать комментарии, такие как #if blah, #error blah или что-нибудь еще, что противоречило бы директивам препроцессора. – obmarg

+0

@obmarg Хорошая точка. Я запомню это. Изменить: любые комментарии, которые не имеют отступов, будут проблемой, поскольку препроцессор задохнется; комментарии с отступом будут проигнорированы, как ожидалось. –

+0

+1. Это сработает. Мне не нужно отступать от комментариев перед процессором. Но знаете ли вы о cpp-подобном инструменте, который работает на node.js (не нужно устанавливать что-либо дополнительное для этого, кроме как через npm, что легко)? – Thilo

2

Это звучит так, как будто вы говорите, что у вас есть два сценария сборки? Для string.js я просто использую Cakefile для достижения того, что вы думаете, что хотите. По сути, если исходный файл изменяется, он создает обычный JS-файл, а затем укрупненный файл.

Вот соответствующая часть 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() 
+0

Да, эта часть работает отлично. Но я также хочу, чтобы содержимое обрезанного файла несколько отличалось от содержимого. Подумайте #ifdef 'DEBUG'. Тот же исходный файл, но с внешними переключателями, влияющими на то, что удаляется. – Thilo

1

Альтернативой препроцессору C был бы макрос процессора M4 (Wikipedia intro). Я не использовал его сам, поэтому я не могу его пересмотреть, и я знаю, что это должно быть немного больно, но это решит вашу проблему. Также он, как и препроцессор C, работает на каждой ОС.

0

Я использую https://github.com/jsoverson/grunt-preprocess для этого товара. Это точно соответствует тому, что я пытаюсь сделать:

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