demos.prod.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. import { dirname, join, relative } from 'path';
  2. import * as glob from 'glob';
  3. import { task } from 'gulp';
  4. import * as del from 'del';
  5. import * as runSequence from 'run-sequence';
  6. import * as s3 from 's3';
  7. import { argv } from 'yargs';
  8. import { DEMOS_SRC_ROOT, ES_2015, ES5, PROJECT_ROOT } from '../constants';
  9. import { createTempTsConfig, getFolderInfo, runAppScriptsBuild, writePolyfills } from '../util';
  10. import * as pAll from 'p-all';
  11. import * as dotenv from 'dotenv';
  12. dotenv.config();
  13. task('demos.prepare', (done: Function) => {
  14. runSequence('demos.clean', 'demos.polyfill', 'demos.sass', (err: any) => done(err));
  15. });
  16. task('demos.prod', ['demos.prepare'], (done: Function) => {
  17. // okay, first find out all of the demos tests to run by finding all of the 'main.ts' files
  18. filterDemosEntryPoints().then((filePaths: string[]) => {
  19. return buildDemos(filePaths);
  20. }).then(() => {
  21. done();
  22. }).catch((err: Error) => {
  23. done(err);
  24. });
  25. });
  26. function filterDemosEntryPoints() {
  27. return getDemosEntryPoints().then((entryPoints: string[]) => {
  28. const folderInfo = getFolderInfo();
  29. if (folderInfo && folderInfo.componentName) {
  30. const filtered = entryPoints.filter(entryPoint => {
  31. return entryPoint.indexOf(folderInfo.componentName) >= 0;
  32. });
  33. return filtered;
  34. }
  35. return entryPoints;
  36. });
  37. }
  38. function getDemosEntryPoints() {
  39. return new Promise((resolve, reject) => {
  40. const mainGlob = join(DEMOS_SRC_ROOT, '**', 'main.ts');
  41. glob(mainGlob, (err: Error, matches: string[]) => {
  42. if (err) {
  43. return reject(err);
  44. }
  45. resolve(matches);
  46. });
  47. });
  48. }
  49. function buildDemos(filePaths: string[]) {
  50. const batches = chunkArrayInGroups(filePaths, argv.batches || 1);
  51. const batch = argv.batch || 0;
  52. if (batch >= batches.length) {
  53. throw new Error(`Batch number higher than total number of batches.`);
  54. }
  55. console.log(`Compiling ${batches[batch].length} of ${filePaths.length} Demos ...`);
  56. const functions = batches[batch].map(filePath => () => {
  57. return buildDemo(filePath);
  58. });
  59. let concurrentNumber = 2;
  60. if (argv.concurrency) {
  61. concurrentNumber = argv.concurrency;
  62. }
  63. return pAll(functions, {concurrency: concurrentNumber});
  64. }
  65. function buildDemo(filePath: string) {
  66. const start = Date.now();
  67. const ionicAngularDir = join(process.cwd(), 'src');
  68. const componentDir = dirname(dirname(filePath));
  69. const relativePathFromComponents = relative(dirname(DEMOS_SRC_ROOT), componentDir);
  70. const distTestRoot = join(process.cwd(), 'dist', 'demos', relativePathFromComponents);
  71. const includeGlob = [ join(ionicAngularDir, '**', '*.ts'), join(componentDir, '**', '*.ts')];
  72. const pathToWriteFile = join(distTestRoot, 'tsconfig.json');
  73. const pathToReadFile = join(PROJECT_ROOT, 'tsconfig.json');
  74. createTempTsConfig(includeGlob, ES5, ES_2015, pathToReadFile, pathToWriteFile, { removeComments: true});
  75. const sassConfigPath = join('scripts', 'demos', 'sass.config.js');
  76. const copyConfigPath = join('scripts', 'demos', 'copy.config.js');
  77. const appEntryPoint = filePath;
  78. const appNgModulePath = join(dirname(filePath), 'app.module.ts');
  79. const distDir = join(distTestRoot, 'www');
  80. const minifyCss = argv.noMinifyCss ? false : true;
  81. const minifyJs = argv.noMinifyJs ? false : true;
  82. const optimizeJs = argv.noOptimizeJs ? false : true;
  83. return runAppScriptsBuild(
  84. appEntryPoint,
  85. appNgModulePath,
  86. ionicAngularDir,
  87. distDir,
  88. pathToWriteFile,
  89. ionicAngularDir,
  90. sassConfigPath,
  91. copyConfigPath,
  92. false,
  93. minifyCss,
  94. minifyJs,
  95. optimizeJs
  96. ).then(() => {
  97. const end = Date.now();
  98. console.log(`${filePath} took a total of ${(end - start) / 1000} seconds to build`);
  99. uploadToS3(pathToWriteFile);
  100. });
  101. }
  102. function chunkArrayInGroups(arr, size) {
  103. const result = [];
  104. for (let i = 0; i < arr.length; i++) {
  105. if (!Array.isArray(result[i % size])) {
  106. result[i % size] = [];
  107. }
  108. result[i % size].push(arr[i]);
  109. }
  110. return result;
  111. }
  112. function uploadToS3(path) {
  113. // fail silently if envars not present
  114. if (!process.env.AWS_KEY || !process.env.AWS_SECRET) {
  115. return Promise.resolve();
  116. }
  117. let client = s3.createClient({
  118. s3Options: {
  119. accessKeyId: process.env.AWS_KEY,
  120. secretAccessKey: process.env.AWS_SECRET
  121. },
  122. });
  123. // get demo name from path
  124. let demo = path.split('/')[path.split('/').length - 2];
  125. let params = {
  126. localDir: path.replace('tsconfig.json', ''),
  127. deleteRemoved: true,
  128. s3Params: {
  129. Bucket: 'ionic-demos',
  130. Prefix: demo,
  131. },
  132. };
  133. const uploader = client.uploadDir(params);
  134. return new Promise((resolve, reject) => {
  135. uploader.on('error', function(err) {
  136. console.error('s3 Upload Error:', err.stack);
  137. reject();
  138. });
  139. uploader.on('end', function() {
  140. console.log(demo, ' demo uploaded to s3');
  141. resolve();
  142. });
  143. });
  144. }
  145. task('demos.download', (done: Function) => {
  146. if (!process.env.AWS_KEY || !process.env.AWS_SECRET) {
  147. return Promise.resolve();
  148. }
  149. let client = s3.createClient({
  150. s3Options: {
  151. accessKeyId: process.env.AWS_KEY,
  152. secretAccessKey: process.env.AWS_SECRET
  153. },
  154. });
  155. let params = {
  156. localDir: join(process.cwd(), 'dist', 'demos', 'src'),
  157. s3Params: {
  158. Bucket: 'ionic-demos',
  159. },
  160. };
  161. let uploader = client.downloadDir(params);
  162. return new Promise((resolve, reject) => {
  163. uploader.on('error', function(err) {
  164. console.error('s3 Download Error:', err.stack);
  165. reject();
  166. });
  167. uploader.on('end', function() {
  168. console.log('Demos downloaded from s3');
  169. resolve();
  170. });
  171. });
  172. });
  173. task('demos.clean', (done: Function) => {
  174. // this is a super hack, but it works for now
  175. if (argv.skipClean) {
  176. return done();
  177. }
  178. del(['dist/demos/**']).then(() => {
  179. done();
  180. }).catch(err => {
  181. done(err);
  182. });
  183. });
  184. task('demos.polyfill', (done: Function) => {
  185. if (argv.skipPolyfill) {
  186. return done();
  187. }
  188. writePolyfills('dist/demos/polyfills').then(() => {
  189. done();
  190. }).catch(err => {
  191. done(err);
  192. });
  193. });