أداة البناء:مشروع Coffeescript/Node ذو مكونات متعددة
-
12-12-2019 - |
سؤال
لقد بدأت مشروعًا في العمل وكنت أتساءل عن أفضل أداة بناء يمكن استخدامها.
كل شيء مكتوب بلغة CoffeeScript، باستخدام AngularJS من جانب العميل وNodeJS من أجل الخادم.
هناك عدة مكونات للتطبيق:
- تطبيق آيباد
- تطبيق iPhone (وظيفة مختلفة عن iPad)
- نظام إدارة المحتوى للتطبيقات
- خادم NodeJS
هناك الكثير من التعليمات البرمجية المشتركة بين كل هذه العناصر، وكلها مكتوبة مرة أخرى بلغة CoffeeScript.
أرغب في الحصول على أداة بناء يمكنني من خلالها سرد التطبيق الذي يستخدم الكود (معظمه مشترك) وسيقوم بإنشاء ملفات جافا سكريبت لكل تطبيق في مجلد منفصل.
على سبيل المثال، سأقوم بإعداد مجلد يسمى "/compiled/ipad/" والذي يحتوي على ملف Index.html، ومجلدات لـ js، وcss، وimg، وما إلى ذلك.أود أن أدرج ملفات القهوة المجمعة التي أريد طرحها في /compiled/ipad/js (بعضها من /src/shared/*.coffee، وبعضها من /src/ipad/*.coffee، وما إلى ذلك) وما هي الملفات التي أستخدمها تريد طرحها في /compiled/ipad/css.أريد أن يكون قادرًا على ربط الملفات بسهولة بالطريقة التي أريدها أيضًا.
كما أنه سيجمع اختباراتي من /src/test/ipad إلى /compiled/test/ipad/*.js.
تتم كتابة جميع اختبارات الوحدة الخاصة بي من جانب العميل باستخدام الخصية ولست متأكدًا مما سأكتبه في اختبارات الوحدة من جانب الخادم حتى الآن.
ما هي أداة البناء/التكوين التي تعتبر أفضل طريقة هنا؟ملف تعريفي؟شيء مثل الناخر؟أنا بصراحة جديد في مشهد البناء بأكمله.
يحرر:قررت الذهاب مع Browserify.يمكنك العثور على الحل الخاص بي لجعله يعمل مع Angular هنا: https://groups.google.com/forum/#!topic/angular/ytoVaikOcCs
المحلول
أود أن أضع كل التعليمات البرمجية المشتركة في وحدات 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 (هناك أشياء أخرى) لإنشاء التطبيقات من جانب العميل عند الحاجة.بهذه الطريقة، بدلًا من وجود ملف بناء تقول فيه ما تحتاجه، يكون لديك بالفعل تطبيقات حقيقية تستورد الوحدات.
نصائح أخرى
أنا شخصياً أعتقد أن الدافع لكتابة كود جانب الخادم في جافا سكريبت أو كوفي سكريبت يمتد إلى سلسلة أدوات البناء الخاصة بك أيضًا:لذا التزم باستخدام جافا سكريبت/القهوة سكريبت هناك أيضًا.سيسمح لك هذا بأتمتة مهام الخادم/العميل بسهولة من أداة الإنشاء الخاصة بك - أشك في أنه سيكون ممكنًا بشكل مجدي باستخدام أداة أخرى مثل make (ستكتب فقط أغلفة حول مكالمات أوامر Node.js).الاقتراحات مرتبة حسب التنظيم:
- Node.js :ما عليك سوى لف نصوص البناء الخاصة بك في جافا سكريبت واستدعائها باستخدام العقدة.أشبه بنصوص شل، على ما أعتقد.لا أوصي بهذا الطريق.
- جيك أو كيك :أنا من عالم جافا، لذا ليس من المستغرب أن يذكرني هذا نوعًا ما بالنملة.أنا أفضل القهوة، وبالتالي أفضل الكعكة.
- الناخر :لم أسمع بهذا من قبل لذلك لا أستطيع تقديم الكثير من النصائح.إنه يذكرني بـ maven، بالطبع... ويمكنني فقط أن أقول... كلما زادت بنية أداة البناء التي تميل إلى فرضها، أصبحت أقل مرونة.إنه شيء من المقايضة.وطالما أنك تفعل ذلك بطريقة "أداة البناء"، يمكنك توفير الكثير من الوقت.ولكن إذا كانت لديك مشكلات خاصة بالتطبيق، فقد يكون من الصعب حلها.
بالطبع، يمكنك استخدام بعض أدوات البناء الأخرى التي تعرفها بالفعل من لغة أخرى:أشعل النار، مخضرم، النمل، غرادل، الخ الخ.
لقد فعلت هذا الشيء بالضبط تقريبًا في ملف Cakefile باستخدام وحدات العقدة حسب الحاجة.
قم بتعيين بعض المتغيرات العامة التي تكون بمثابة صفائف مع مسار كل ملف، وقم بتسلسل تلك الملفات في ملف في الدليل المترجم الذي تحدده، ثم قم بتجميع هذا الملف في 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 وكان لدي وظائف أخرى قبل أن تصل إلى الوظيفة المصغرة، ولكن أعتقد أنك فهمت الفكرة.