build-examples.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /**
  2. * build-examples.js
  3. * --------
  4. * Searches for each example's `js/app.es6` file.
  5. * Creates a new watchify instance for each `app.es6`.
  6. * Changes to Uppy's source will trigger rebundling.
  7. *
  8. * Run as:
  9. *
  10. * build-examples.js # to build all examples one-off
  11. * build-examples.js watch # to keep rebuilding examples with an internal watchify
  12. * build-examples.js <path> # to build just one example app.es6
  13. *
  14. * Note:
  15. * Since each example is dependent on Uppy's source,
  16. * changing one source file causes the 'file changed'
  17. * notification to fire multiple times. To stop this,
  18. * files are added to a 'muted' array that is checked
  19. * before announcing a changed file. It's removed from
  20. * the array when it has been bundled.
  21. */
  22. var createStream = require('fs').createWriteStream;
  23. var glob = require('multi-glob').glob;
  24. var chalk = require('chalk');
  25. var path = require('path');
  26. var mkdirp = require('mkdirp');
  27. var notifier = require('node-notifier');
  28. var babelify = require('babelify');
  29. var browserify = require('browserify');
  30. var watchify = require('watchify');
  31. var webRoot = __dirname;
  32. var uppyRoot = path.dirname(webRoot);
  33. var srcPattern = webRoot + '/src/examples/**/js/app.es6';
  34. var dstPattern = webRoot + '/public/examples/**/js/app.js';
  35. var watchifyEnabled = process.argv[2] === 'watch';
  36. var browserifyPlugins = [];
  37. if (watchifyEnabled) {
  38. browserifyPlugins.push(watchify);
  39. }
  40. // Instead of 'watch', build-examples.js can also take a path as cli argument.
  41. // In this case we'll only bundle the specified path/pattern
  42. if (!watchifyEnabled && process.argv[2]) {
  43. srcPattern = process.argv[2];
  44. }
  45. // Find each app.es6 file with glob.
  46. glob(srcPattern, function(err, files) {
  47. if (err) throw new Error(err);
  48. if (watchifyEnabled) {
  49. console.log('--> Watching examples..');
  50. }
  51. var muted = [];
  52. // Create a new watchify instance for each file.
  53. files.forEach(function(file) {
  54. var browseFy = browserify(file, {
  55. cache : {},
  56. packageCache: {},
  57. plugin : browserifyPlugins
  58. })
  59. // Aliasing for using `require('uppy')`, etc.
  60. browseFy
  61. .require(uppyRoot + '/src/index.js', { expose: 'uppy' })
  62. .require(uppyRoot + '/src/core/index.js', { expose: 'uppy/core' })
  63. .require(uppyRoot + '/src/plugins/index.js', { expose: 'uppy/plugins' })
  64. .transform(babelify);
  65. // Listeners for changes, errors, and completion.
  66. browseFy
  67. .on('update', bundle)
  68. .on('error', onError)
  69. .on('file', function(file, id, parent) {
  70. // When file completes, unmute it.
  71. muted = muted.filter(function(mutedId) {
  72. return id !== mutedId;
  73. });
  74. });
  75. // Call bundle() manually to start watch processes.
  76. bundle();
  77. /**
  78. * Creates bundle and writes it to static and public folders.
  79. * Changes to
  80. * @param {[type]} ids [description]
  81. * @return {[type]} [description]
  82. */
  83. function bundle(ids) {
  84. ids = ids || [];
  85. ids.forEach(function(id) {
  86. if (!isMuted(id, muted)) {
  87. console.info(chalk.cyan('change:'), id);
  88. muted.push(id);
  89. }
  90. });
  91. var exampleName = path.basename(path.dirname(path.dirname(file)));
  92. var output = dstPattern.replace('**', exampleName);
  93. var parentDir = path.dirname(output);
  94. mkdirp.sync(parentDir);
  95. console.info(chalk.green('✓ building:'), chalk.green(path.relative(process.cwd(), output)));
  96. var bundle = browseFy.bundle()
  97. .on('error', onError)
  98. bundle.pipe(createStream(output));
  99. }
  100. });
  101. });
  102. /**
  103. * Logs to console and shows desktop notification on error.
  104. * Calls `this.emit(end)` to stop bundling.
  105. * @param {object} err Error object
  106. */
  107. function onError(err) {
  108. console.error(chalk.red('✗ error:'), chalk.red(err.message));
  109. notifier.notify({
  110. 'title': 'Build failed:',
  111. 'message': err.message
  112. })
  113. this.emit('end');
  114. }
  115. /**
  116. * Checks if a file has been added to muted list.
  117. * This stops single changes from logging multiple times.
  118. * @param {string} id Name of changed file
  119. * @param {Array<string>} list Muted files array
  120. * @return {Boolean} True if file is muted
  121. */
  122. function isMuted(id, list) {
  123. return list.reduce(function(prev, curr) {
  124. return prev || (curr === id);
  125. }, false);
  126. }