Инструмент сборки: проект Coffeescript/Node с несколькими компонентами

Я запускаю проект на работе и задаюсь вопросом, какой лучший инструмент для сборки будет использоваться.

Все это написано в CoffeeScript, используя AngularJS для клиентской стороны и NodeJS для сервера.

В приложении есть несколько компонентов:

  • Приложение для iPad
  • Приложение для iPhone (различные функции от ipad)
  • CMS для приложений
  • Сервер NodeJS

Существует много общего кода между ними, снова все написанное на CoffeeScript.

Мне нужен инструмент построения, где я могу указать, какое приложение использует какой код (большая часть его разделяла), и он будет создавать каждый файл javascript приложения в отдельной папке.

Например, я бы установил папку с именем /compiled/ipad/, которая имеет index.html, и папки для js, css, img и т.д. Я бы перечислил, какие скомпилированные файлы кофе, которые я хочу добавить в /ipad/js (некоторые из них из /src/shared/ *.coffee, некоторые из них из /src/ipad/ *.coffee и т.д.) и какие файлы я хочу загрузить в/скомпилированный/ipad/css. Я бы хотел, чтобы он мог легко конкатенировать файлы, как я тоже хочу.

Он также скомпилирует мои тесты из /src/test/ipad в/compiled/test/ipad/*. js.

Все мои тестовые тесты на стороне клиента написаны с использованием testacular, и я не уверен, что я напишу на стороне сервера еще нет.

Какой инструмент сборки/конфигурации лучше всего подходит? Makefile? Что-то вроде Грунта? Я честно новичок во всей сборной.

edit. Решено перейти с Browserify. Вы можете найти решение для работы с Angular здесь: https://groups.google.com/forum/#!topic/angular/ytoVaikOcCs

Ответ 1

Я бы поместил весь общий код в модули Node.js и создал проект, который выглядит примерно так:

Project
|~apps/
| |~cms/
| | `-app.js
| |~ipad/
| | `-app.js
| |~iphone/
| | `-app.js
| `~node/
|   `-app.js
|~libs/
| |-module.js
| `-module2.js
|~specs/
| |~cms/
| | `-app.js
| |~ipad/
| | `-app.js
| |~iphone/
| | `-app.js
| `~node/
|   `-app.js
| `~libs/
|   |-module.js
|   `-module2.js
`-Makefile

Затем я использовал бы что-то вроде Browserify (есть другие), чтобы делать приложения на стороне клиента там, где это необходимо. Таким образом, вместо того, чтобы иметь файл сборки, в котором вы говорите, что вам нужно, у вас действительно есть реальные приложения, импортирующие модули.

Ответ 2

Лично я думаю, что диск для написания кода на стороне сервера в javascript или coffeescript также распространяется на вашу цепочку инструментов сборки: так что придерживайтесь там же javascript/coffeescript. Это позволит вам легко автоматизировать задачи сервера и клиента из вашего инструмента сборки. Я сомневаюсь, что это было бы значимо возможным с помощью другого инструмента, такого как make (вы просто пишете обертки вокруг вызовов команд node.js). Предложения, упорядоченные по структурированности:

  • node.js: просто сверните скрипты сборки в javascript и вызовите их с помощью node. Полагаю, похоже на сценарии оболочки. Я не рекомендую этот маршрут.
  • jake или cake: я 'm из java мира, так что не удивительно, что эти виды напоминают мне ant. Я предпочитаю coffeescript и, следовательно, предпочитаю торт.
  • grunt: Я не слышал об этом раньше, поэтому не могу дать много советов. Это, конечно, напоминает мне maven... и я могу просто сказать... чем больше структура, тем сложнее инструмент построения, тем менее гибким он может быть. Это что-то вроде компромисса. Пока вы делаете это "способ сборки", вы можете сэкономить массу времени. Но если у вас проблемы с конкретным приложением, это может быть одна королевская боль, чтобы решить.

Конечно, вы можете пойти с другим инструментом сборки, с которым вы уже знакомы с каким-то другим языком: rake, maven, ant, gradle и т.д. и т.д.

Ответ 3

Я сделал почти все это в Cakefile, используя node модули по мере необходимости.

Задайте некоторые глобальные переменные, которые представляют собой массивы с контуром каждого файла, объедините эти файлы в файл в скомпилированном каталоге, который вы указали, затем скомпилируйте этот файл в js.

Для стилей одно и то же с конкатенацией без компиляции, очевидно.

fs = require 'fs'
path = require 'path'
{spawn, exec} = require 'child_process'
parser = require('uglify-js').parser
uglify = require('uglify-js').uglify
cleanCss = require 'clean-css'

coffees = 
 [
  "/src/shared/file1.coffee"
  "/src/shared/file2.coffee"
  "/src/ipad/file1.coffee"
 ]

tests = 
  [
   "/src/ipad/tests.coffee"
  ]

styles = 
 [
  "/src/ipad/styles1.css"
  "/src/shared/styles2.css"
 ]

concatenate = (destinationFile, files, type) ->
  newContents = new Array
  remaining = files.length
  for file, index in files then do (file, index) ->
      fs.readFile file, 'utf8', (err, fileContents) ->
          throw err if err
          newContents[index] = fileContents
          if --remaining is 0
              fs.writeFile destinationFile, newContents.join '\n\n', 'utf8', (err) ->
                throw err if err
              if type is 'styles'
                 minifyCss fileName
              else
                 compileCoffee fileName


 compileCoffee = (file) ->
    exec "coffee -c #{file}", (err) ->
       throw err if err
       # delete coffee file leaving only js
       fs.unlink 'path/specifying/compiled_coffee', (err) -> 
          throw err if err
          minifyJs file

 minifyJs = (file) ->
  fs.readFile f, 'utf8', (err, contents) ->
      ast = parser.parse contents
      ast = uglify.ast_mangle ast 
      ast = uglify.ast_squeeze ast
      minified = uglify.gen_code ast

      writeMinified file, minified

writeMinified = (file, contents) ->
   fs.writeFile file, contents, 'utf8', (err) -> throw err if err  


minifyCss = (file) ->
    fs.readFile file, 'utf8', (err, contents) ->
    throw err if err
    minimized = cleanCss.process contents
    clean = minimized.replace 'app/assets', ''

    fs.writeFile file, clean, 'utf8', (err) ->
        throw err if err


task 'compile_coffees', 'concat, compile, and minify coffees', ->
  concatenate '/compiled/ipad/code.coffee', coffees, 'coffee'

task 'concat_styles', 'concat and minify styles', ->
  concatenate '/compiled/ipad/css/styles.css', styles, 'styles'

task 'compile_tests', 'concat, compile, and minify test', ->
  concatenate '/compiled/ipad/tests.coffee', tests, 'tests'

Теперь это примерно то, о чем я думаю, что вы просите.

Может определенно быть красивее, особенно с отдельной функцией для записи миниатюрного содержимого, но он работает.

Не идеально подходит для стилей, потому что я использовал Sass и имел другие функции, прежде чем он попал в мини-функцию, но я думаю, что вы поняли эту идею.