gulpfile.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. // Gulp Tools
  2. var gulp = require("gulp");
  3. var uglify = require("gulp-uglify");
  4. var typescript = require("gulp-typescript");
  5. var sourcemaps = require("gulp-sourcemaps");
  6. var srcToVariable = require("gulp-content-to-variable");
  7. var merge2 = require("merge2");
  8. var concat = require("gulp-concat");
  9. var rename = require("gulp-rename");
  10. var cleants = require("gulp-clean-ts-extends");
  11. var replace = require("gulp-replace");
  12. var expect = require("gulp-expect-file");
  13. var optimisejs = require("gulp-optimize-js");
  14. var filter = require('gulp-filter');
  15. var path = require("path");
  16. var webpack = require('webpack');
  17. var webpackStream = require("webpack-stream");
  18. var fs = require("fs");
  19. var dtsBundle = require('dts-bundle');
  20. var through = require('through2');
  21. // Gulp Helpers
  22. var addDtsExport = require("./helpers/gulp-addDtsExport");
  23. var addDecorateAndExtends = require("./helpers/gulp-decorateAndExtends");
  24. var addModuleExports = require("./helpers/gulp-addModuleExports");
  25. var addES6Exports = require("./helpers/gulp-addES6Exports");
  26. var uncommentShader = require("./helpers/gulp-removeShaderComments");
  27. var processDeclaration = require('./helpers/gulp-processTypescriptDeclaration');
  28. // Import Gulp Tasks
  29. require("./tasks/gulpTasks-tsLint");
  30. require("./tasks/gulpTasks-netlify");
  31. require("./tasks/gulpTasks-whatsNew");
  32. require("./tasks/gulpTasks-localRun");
  33. require("./tasks/gulpTasks-watch");
  34. require("./tasks/gulpTasks-typedoc");
  35. require("./tasks/gulpTasks-intellisense");
  36. require("./tasks/gulpTasks-tests");
  37. // Import Build Config
  38. var config = require("./config.json");
  39. var includeShadersStream;
  40. var shadersStream;
  41. var workersStream;
  42. var extendsSearchRegex = /var\s__extends[\s\S]+?\}\)\(\);/g;
  43. var decorateSearchRegex = /var\s__decorate[\s\S]+?\};/g;
  44. /**
  45. * TS configurations shared in the gulp file.
  46. */
  47. var tsConfig = {
  48. noResolve: true,
  49. target: "ES5",
  50. declarationFiles: true,
  51. typescript: require("typescript"),
  52. experimentalDecorators: true,
  53. isolatedModules: false,
  54. noImplicitAny: true,
  55. noImplicitReturns: true,
  56. noImplicitThis: true,
  57. noUnusedLocals: true,
  58. strictNullChecks: true,
  59. strictFunctionTypes: true,
  60. types: [],
  61. lib: [
  62. "dom",
  63. "es2015.promise",
  64. "es5"
  65. ]
  66. };
  67. var tsProject = typescript.createProject(tsConfig);
  68. function processDependency(kind, dependency, filesToLoad, firstLevelOnly) {
  69. if (!firstLevelOnly && dependency.dependUpon) {
  70. for (var i = 0; i < dependency.dependUpon.length; i++) {
  71. var dependencyName = dependency.dependUpon[i];
  72. var parent = config.workloads[dependencyName];
  73. processDependency(kind, parent, filesToLoad);
  74. }
  75. }
  76. var content = dependency[kind];
  77. if (!content) {
  78. return;
  79. }
  80. for (var i = 0; i < content.length; i++) {
  81. var file = content[i];
  82. if (filesToLoad.indexOf(file) === -1) {
  83. filesToLoad.push(file);
  84. }
  85. }
  86. }
  87. function determineFilesToProcess(kind) {
  88. var currentConfig = config.build.currentConfig;
  89. var buildConfiguration = config.buildConfigurations[currentConfig];
  90. var filesToLoad = [];
  91. for (var index = 0; index < buildConfiguration.length; index++) {
  92. var dependencyName = buildConfiguration[index];
  93. var dependency = config.workloads[dependencyName];
  94. if (kind === "directFiles" && !dependency) {
  95. filesToLoad.push("../../dist/preview release/" + dependencyName);
  96. }
  97. else if (dependency) {
  98. processDependency(kind, dependency, filesToLoad);
  99. }
  100. }
  101. if (kind === "shaderIncludes") {
  102. for (var index = 0; index < filesToLoad.length; index++) {
  103. filesToLoad[index] = "../../src/Shaders/ShadersInclude/" + filesToLoad[index] + ".fx";
  104. }
  105. } else if (kind === "shaders") {
  106. for (var index = 0; index < filesToLoad.length; index++) {
  107. var name = filesToLoad[index];
  108. filesToLoad[index] = "../../src/Shaders/" + filesToLoad[index] + ".fx";
  109. }
  110. }
  111. return filesToLoad;
  112. }
  113. /*
  114. * Shader Management.
  115. */
  116. function shadersName(filename) {
  117. return path.basename(filename)
  118. .replace(".fragment", "Pixel")
  119. .replace(".vertex", "Vertex")
  120. .replace(".fx", "Shader");
  121. }
  122. function includeShadersName(filename) {
  123. return path.basename(filename).replace(".fx", "");
  124. }
  125. /*
  126. * Main necessary files stream Management.
  127. */
  128. gulp.task("includeShaders", function(cb) {
  129. var filesToProcess = determineFilesToProcess("shaderIncludes");
  130. includeShadersStream = gulp.src(filesToProcess).
  131. pipe(expect.real({ errorOnFailure: true }, filesToProcess)).
  132. pipe(uncommentShader()).
  133. pipe(srcToVariable({
  134. variableName: "BABYLON.Effect.IncludesShadersStore", asMap: true, namingCallback: includeShadersName
  135. }));
  136. cb();
  137. });
  138. gulp.task("shaders", gulp.series("includeShaders", function(cb) {
  139. var filesToProcess = determineFilesToProcess("shaders");
  140. shadersStream = gulp.src(filesToProcess).
  141. pipe(expect.real({ errorOnFailure: true }, filesToProcess)).
  142. pipe(uncommentShader()).
  143. pipe(srcToVariable({
  144. variableName: "BABYLON.Effect.ShadersStore", asMap: true, namingCallback: shadersName
  145. }));
  146. cb();
  147. }));
  148. gulp.task("workers", function(cb) {
  149. workersStream = config.workers.map(function(workerDef) {
  150. return gulp.src(workerDef.files).
  151. pipe(expect.real({ errorOnFailure: true }, workerDef.files)).
  152. pipe(uglify()).
  153. pipe(srcToVariable({
  154. variableName: workerDef.variable
  155. }));
  156. });
  157. cb();
  158. });
  159. /**
  160. * Build tasks to concat minify uflify optimise the BJS js in different flavor (workers...).
  161. */
  162. gulp.task("buildWorker", gulp.series(gulp.parallel("workers", "shaders"), function() {
  163. var filesToProcess = determineFilesToProcess("files");
  164. return merge2(
  165. gulp.src(filesToProcess).
  166. pipe(expect.real({ errorOnFailure: true }, filesToProcess)),
  167. shadersStream,
  168. includeShadersStream,
  169. workersStream
  170. )
  171. .pipe(concat(config.build.minWorkerFilename))
  172. .pipe(cleants())
  173. .pipe(replace(extendsSearchRegex, ""))
  174. .pipe(replace(decorateSearchRegex, ""))
  175. .pipe(addDecorateAndExtends())
  176. .pipe(addModuleExports("BABYLON", {
  177. dependencies: config.build.dependencies
  178. }))
  179. .pipe(uglify())
  180. .pipe(optimisejs())
  181. .pipe(gulp.dest(config.build.outputDirectory));
  182. }));
  183. gulp.task("build", gulp.series("shaders", function build() {
  184. var filesToProcess = determineFilesToProcess("files");
  185. var directFilesToProcess = determineFilesToProcess("directFiles");
  186. let mergedStreams = merge2(gulp.src(filesToProcess)
  187. .pipe(expect.real({ errorOnFailure: true }, filesToProcess)),
  188. shadersStream,
  189. includeShadersStream);
  190. if (directFilesToProcess.length) {
  191. mergedStreams.add(gulp.src(directFilesToProcess));
  192. }
  193. return merge2(
  194. mergedStreams
  195. .pipe(concat(config.build.noModuleFilename))
  196. .pipe(cleants())
  197. .pipe(replace(extendsSearchRegex, ""))
  198. .pipe(replace(decorateSearchRegex, ""))
  199. .pipe(addDecorateAndExtends())
  200. .pipe(gulp.dest(config.build.outputDirectory))
  201. .pipe(rename(config.build.filename))
  202. .pipe(addModuleExports("BABYLON", {
  203. dependencies: config.build.dependencies
  204. }))
  205. .pipe(gulp.dest(config.build.outputDirectory))
  206. .pipe(rename(config.build.minFilename))
  207. .pipe(uglify())
  208. .pipe(optimisejs())
  209. .pipe(gulp.dest(config.build.outputDirectory)),
  210. mergedStreams
  211. .pipe(concat("es6.js"))
  212. .pipe(cleants())
  213. .pipe(replace(extendsSearchRegex, ""))
  214. .pipe(replace(decorateSearchRegex, ""))
  215. .pipe(addES6Exports("BABYLON"))
  216. .pipe(gulp.dest(config.build.outputDirectory))
  217. );
  218. }));
  219. /*
  220. * Compiles all typescript files and creating a js and a declaration file.
  221. */
  222. gulp.task("typescript-compile", function() {
  223. const dtsFilter = filter(['**', '!**/*.d.ts'], {restore: false});
  224. var tsResult = gulp.src(config.typescript)
  225. .pipe(dtsFilter)
  226. .pipe(sourcemaps.init())
  227. .pipe(tsProject({
  228. summarizeFailureOutput: true
  229. }));
  230. //If this gulp task is running on travis, file the build!
  231. if (process.env.TRAVIS) {
  232. tsResult.once("error", function() {
  233. tsResult.once("finish", function() {
  234. console.log("Typescript compile failed");
  235. process.exit(1);
  236. });
  237. });
  238. }
  239. return merge2([
  240. tsResult.dts
  241. .pipe(concat(config.build.declarationFilename))
  242. .pipe(addDtsExport("BABYLON", "babylonjs"))
  243. .pipe(gulp.dest(config.build.outputDirectory)),
  244. tsResult.js
  245. .pipe(sourcemaps.write("./",
  246. {
  247. includeContent: false,
  248. sourceRoot: (filePath) => {
  249. return "";
  250. }
  251. }))
  252. .pipe(gulp.dest(config.build.srcOutputDirectory))
  253. ])
  254. });
  255. /**
  256. * Build the releasable files.
  257. */
  258. gulp.task("typescript", gulp.series("typescript-compile", "buildWorker", "build"));
  259. var buildExternalLibrary = function(library, settings) {
  260. var outputDirectory = config.build.outputDirectory + settings.build.distOutputDirectory;
  261. if (!library.webpack) {
  262. throw "Missing Webpack configuration in " + library;
  263. }
  264. const sequence = [];
  265. if (settings.build.outputs) {
  266. settings.build.outputs.forEach(out => {
  267. let wpConfig = require(library.webpack);
  268. if (!out.minified) {
  269. wpConfig.mode = "development";
  270. }
  271. let wpBuild = webpackStream(wpConfig, require("webpack"));
  272. //shoud dtsBundle create the declaration?
  273. if (settings.build.dtsBundle) {
  274. let event = wpBuild
  275. .pipe(through.obj(function(file, enc, cb) {
  276. // only declaration files
  277. const isdts = /\.d\.ts$/.test(file.path);
  278. if (isdts) this.push(file);
  279. cb();
  280. }))
  281. .pipe(gulp.dest(outputDirectory));
  282. // dts-bundle does NOT support (gulp) streams, so files have to be saved and reloaded,
  283. // until I fix it
  284. event.on("end", function() {
  285. // create the file
  286. dtsBundle.bundle(settings.build.dtsBundle);
  287. // prepend the needed reference
  288. let fileLocation = path.join(path.dirname(settings.build.dtsBundle.main), settings.build.dtsBundle.out);
  289. fs.readFile(fileLocation, function(err, data) {
  290. if (err) throw err;
  291. data = (settings.build.dtsBundle.prependText || "") + '\n' + data.toString();
  292. fs.writeFileSync(fileLocation, data);
  293. if (settings.build.processDeclaration) {
  294. var newData = processDeclaration(data, settings.build.processDeclaration);
  295. fs.writeFileSync(fileLocation.replace('.module', ''), newData);
  296. }
  297. });
  298. });
  299. }
  300. let build = wpBuild
  301. .pipe(through.obj(function(file, enc, cb) {
  302. // only pipe js files
  303. const isJs = /\.js$/.test(file.path);
  304. if (isJs) this.push(file);
  305. cb();
  306. }))
  307. .pipe(addModuleExports(library.moduleDeclaration, { subModule: false, extendsRoot: false, externalUsingBabylon: true, noBabylonInit: library.babylonIncluded }));
  308. function processDestination(dest) {
  309. var outputDirectory = config.build.outputDirectory + dest.outputDirectory;
  310. build = build
  311. .pipe(rename(dest.filename.replace(".js", library.noBundleInName ? '.js' : ".bundle.js")))
  312. .pipe(gulp.dest(outputDirectory));
  313. if (library.babylonIncluded && dest.addBabylonDeclaration) {
  314. // include the babylon declaration
  315. if (dest.addBabylonDeclaration === true) {
  316. dest.addBabylonDeclaration = [config.build.declarationFilename];
  317. }
  318. var decsToAdd = dest.addBabylonDeclaration.map(function(dec) {
  319. return config.build.outputDirectory + '/' + dec;
  320. });
  321. sequence.unshift(gulp.src(decsToAdd)
  322. .pipe(rename(function(path) {
  323. path.dirname = '';
  324. }))
  325. .pipe(gulp.dest(outputDirectory)))
  326. }
  327. }
  328. out.destinations.forEach(dest => {
  329. processDestination(dest);
  330. });
  331. sequence.push(build);
  332. });
  333. } else {
  334. var wpConfig;
  335. if (library.entry) {
  336. wpConfig = require(settings.build.webpack);
  337. wpConfig.entry = {
  338. 'main': path.resolve(wpConfig.context, library.entry),
  339. };
  340. wpConfig.output.filename = library.output;
  341. }
  342. else {
  343. wpConfig = require(library.webpack);
  344. }
  345. let wpBuild = webpackStream(wpConfig, webpack);
  346. let buildEvent = wpBuild.pipe(gulp.dest(outputDirectory));
  347. sequence.push(buildEvent);
  348. // Generate unminified
  349. wpConfig.mode = "development";
  350. wpConfig.output.filename = wpConfig.output.filename.replace(".min", "");
  351. wpBuild = webpackStream(wpConfig, webpack);
  352. let buildEvent2 = wpBuild.pipe(gulp.dest(outputDirectory));
  353. sequence.push(buildEvent2);
  354. if (library.isMain) {
  355. if (settings.build.dtsBundle || settings.build.processDeclaration) {
  356. buildEvent.on("end", function() {
  357. if (settings.build.dtsBundle) {
  358. dtsBundle.bundle(settings.build.dtsBundle);
  359. }
  360. if (settings.build.processDeclaration) {
  361. let fileLocation = path.join(outputDirectory, settings.build.processDeclaration.filename);
  362. fs.readFile(fileLocation, function(err, data) {
  363. if (err) throw err;
  364. // For Raanan, litteral import hack TO BETTER INTEGRATE
  365. data = data + "";
  366. data = data.replace('import "../sass/main.scss";', "");
  367. var newData = processDeclaration(data, settings.build.processDeclaration);
  368. fs.writeFileSync(fileLocation.replace('.module', ''), newData);
  369. //legacy module support
  370. fs.writeFileSync(fileLocation, data + "\n" + newData);
  371. });
  372. }
  373. });
  374. }
  375. }
  376. }
  377. return merge2(sequence);
  378. }
  379. /**
  380. * Dynamic module creation In Serie for WebPack leaks.
  381. */
  382. function buildExternalLibraries(settings) {
  383. var tasks = settings.libraries.map(function(library) {
  384. var build = function(cb) {
  385. return buildExternalLibrary(library, settings);
  386. }
  387. return build;
  388. });
  389. return gulp.series.apply(this, tasks);
  390. }
  391. /**
  392. * Dynamic module creation.
  393. */
  394. config.modules.map(function(module) {
  395. gulp.task(module, buildExternalLibraries(config[module]));
  396. });
  397. /**
  398. * Build all libs.
  399. */
  400. gulp.task("typescript-libraries", gulp.series(config.modules));
  401. /**
  402. * Custom build with full path file control; used by profile.html
  403. */
  404. gulp.task("build-custom", gulp.series("typescript-compile", "build"));
  405. /**
  406. * Validate compile the code and check the comments and style case convention through typedoc
  407. */
  408. gulp.task("typedoc-check", gulp.series("typescript-compile", "gui", "loaders", "serializers", "typedoc-generate", "typedoc-validate"));
  409. /**
  410. * Combine Webserver and Watch as long as vscode does not handle multi tasks.
  411. */
  412. gulp.task("run", gulp.series("watch", "webserver"));
  413. /**
  414. * Do it all (Build).
  415. */
  416. gulp.task("typescript-all", gulp.series("typescript", "typescript-libraries", "netlify-cleanup"));
  417. /**
  418. * Do it all (tests).
  419. */
  420. gulp.task("tests-all", gulp.series("tests-unit", "tests-modules", "tests-validation-virtualscreen", "tests-validation-browserstack"));
  421. /**
  422. * The default task, concat and min the main BJS files.
  423. */
  424. gulp.task("default", gulp.series("tsLint", "typescript-all", "intellisense", "typedoc-all", "tests-all"));