1 | 'use strict';
|
2 | var processPath = process.cwd().replace(/\\/g, "/")
|
3 | , fsExtra = require('../../../fs-extra')
|
4 | , del = require('../../../del');
|
5 |
|
6 | fsExtra.copySync('node_modules/@omnia/foundation/task/external/node_modules/webpack/lib/FunctionModuleTemplatePlugin.js', 'node_modules/webpack/lib/FunctionModuleTemplatePlugin.js');
|
7 |
|
8 | del.sync('node_modules/@omnia/foundation/node_modules');
|
9 |
|
10 | var gulp = require('gulp')
|
11 | , glob = require('../../../glob')
|
12 | , globby = require('../../../globby')
|
13 | , chokidar = require('../../../chokidar')
|
14 | , fs = require('fs')
|
15 | , $ = require('../../../gulp-load-plugins')({
|
16 | pattern: [
|
17 | 'gulp-*'
|
18 | ],
|
19 | rename: {
|
20 | }
|
21 | })
|
22 | , timestamp = require('../../../console-timestamp')
|
23 | , webpack = require("../../../webpack")
|
24 | , namedModulesPlugin = require('../../../webpack/lib/NamedModulesPlugin')
|
25 | , gutil = require("../../../gulp-util")
|
26 | , merge = require('../../../webpack-merge')
|
27 | , exec = require('child_process').exec
|
28 | , jsonfile = require('../../../jsonfile')
|
29 | , extend = require('../../../deep-extend')
|
30 | , path = require('path')
|
31 | , omfWebpackPlugins = require('./services/omf.webpack.plugins')
|
32 | , utils = require('@omnia/tooling/shared/omf.utils.js')
|
33 | , core = require('@omnia/tooling/shared/omf.core.js');
|
34 |
|
35 | var appConfig = {};
|
36 | mergeConfig();
|
37 | core.registerBuildTask({ type: core.BuildType.BeforeBuild, order: 9, task: beforeBuild });
|
38 | core.registerBuildTask({ type: core.BuildType.AfterBuild, order: 1, task: afterBuild });
|
39 |
|
40 | gulp.task('omf-webpack-bundle', function (cb) {
|
41 | var files, i = process.argv.indexOf("--files");
|
42 | if (i > -1 && process.argv.length - 1 > i) {
|
43 | files = process.argv[i + 1];
|
44 | webpackBundle(true, files.split(','));
|
45 | }
|
46 | else {
|
47 | webpackBundle(true).then(cb);
|
48 | }
|
49 | });
|
50 |
|
51 |
|
52 | gulp.task('omf-webpack-bundle-libs', function (cb) {
|
53 | if (appConfig.angular.webpack.bundleLibs && appConfig.angular.webpack.bundleLibs.configFile
|
54 | && appConfig.angular.webpack.bundleLibs.configFile.length > 0 && appConfig.angular.webpack.bundleLibs.outputFile && appConfig.angular.webpack.bundleLibs.outputFile.length > 0) {
|
55 | let stream = fs.readFileSync(appConfig.angular.webpack.bundleLibs.configFile, 'utf8');
|
56 | if (stream.indexOf("//webpack-eof") === -1)
|
57 | fs.appendFileSync(appConfig.angular.webpack.bundleLibs.configFile, '\r\n //webpack-eof');
|
58 | var basePaths = ["node_modules"];
|
59 | webpack(merge(require("./config/webpack.config.js"), {
|
60 | entry: {
|
61 | 'vendor': './task/config/external.js',
|
62 | 'app': processPath + '/' + appConfig.angular.webpack.bundleLibs.configFile
|
63 | },
|
64 | target: "web",
|
65 | output: {
|
66 | pathinfo: true,
|
67 | filename: appConfig.angular.webpack.bundleLibs.outputFile,
|
68 | },
|
69 | externals: [
|
70 | function (context, request, callback) {
|
71 | if (request.toLowerCase().indexOf("@angular") === 0 || request.toLowerCase().indexOf("rxjs") === 0) {
|
72 | return callback(null, "__webpack_require__('" + request.toLowerCase() + "')");
|
73 | }
|
74 | else {
|
75 | callback();
|
76 | }
|
77 | }
|
78 | ],
|
79 | module: {
|
80 | loaders: [
|
81 | {
|
82 | test: /\.js$/,
|
83 | loader: 'babel-loader',
|
84 | query: {
|
85 | compact: false,
|
86 | presets: ['es2015'],
|
87 | ignore: [
|
88 | ]
|
89 | }
|
90 | }
|
91 | ]
|
92 | },
|
93 | plugins: [
|
94 | new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: 'node_modules/@omnia/foundation/task/temp/external.bundle.js' }),
|
95 | new omfWebpackPlugins.NamedModulesPlugin({
|
96 | replacements: [
|
97 | {
|
98 | pattern: /\/node_modules/g,
|
99 | replace: ""
|
100 | }
|
101 | ]
|
102 | }),
|
103 | new omfWebpackPlugins.ReplaceBundlePlugin([
|
104 | {
|
105 | pattern: /\/\/webpack-eof[\s\S]+}\,\[(.*?)\]/g,
|
106 | replacement: function (match) {
|
107 | return '})},[]'
|
108 | }
|
109 | },
|
110 | {
|
111 | pattern: new RegExp("__webpack_require__\\(\/\\*(.*)\\)", 'g'),
|
112 | replacement: function (match) {
|
113 | return match
|
114 | .replace(/\/\*!(.*?)\/(.*?)"/i, '"')
|
115 | .replace(/\/\*!(.*?)\/(.*?)\)/i, function (requireModulePath) {
|
116 | return requireModulePath
|
117 | .replace("/*!", '"')
|
118 | .replace(/\*\/(.*?)\)/i, '")')
|
119 | .replace(/ /g, "")
|
120 | })
|
121 | }
|
122 | }
|
123 | ])
|
124 | ]
|
125 | }),
|
126 | function (err, stats) {
|
127 | if (err) throw new gutil.PluginError("webpack", err);
|
128 | })
|
129 | .plugin("done", function () {
|
130 | let stream = fs.readFileSync(appConfig.angular.webpack.bundleLibs.configFile, 'utf8');
|
131 | stream.replace(/\/\/webpack-eof/g, "")
|
132 | fs.writeFileSync(appConfig.angular.webpack.bundleLibs.configFile, stream);
|
133 | if (appConfig.angular.webpack.bundleLibs.concatToOutPut
|
134 | && appConfig.angular.webpack.bundleLibs.concatToOutPut.files
|
135 | && appConfig.angular.webpack.bundleLibs.concatToOutPut.files.length > 0
|
136 | ) {
|
137 | var temFilePath = appConfig.angular.webpack.bundleLibs.outputFile.replace(/\\/g, "/");
|
138 | var outFileName = temFilePath.substring(temFilePath.lastIndexOf('/'));
|
139 | var folderPath = ".";
|
140 | if (temFilePath.lastIndexOf('/') > 0)
|
141 | folderPath = temFilePath.substring(0, temFilePath.lastIndexOf('/'))
|
142 | gulp.src([appConfig.angular.webpack.bundleLibs.outputFile].concat(appConfig.angular.webpack.bundleLibs.concatToOutPut.files))
|
143 | .pipe($.concat(outFileName))
|
144 | .pipe(gulp.dest(folderPath))
|
145 | .on('end', function () {
|
146 | console.log('bundle completed');
|
147 | cb();
|
148 | });
|
149 | }
|
150 | else {
|
151 | console.log('bundle completed');
|
152 | cb();
|
153 | }
|
154 | });
|
155 | }
|
156 | else {
|
157 | console.log('Not found configs angular.webpack.bundleLibs.configFile or appConfig.angular.webpack.bundleLibs.outputFile');
|
158 | }
|
159 |
|
160 | });
|
161 |
|
162 | function beforeBuild() {
|
163 | return new Promise(function (resolve, reject) {
|
164 | fsExtra.copySync('node_modules/@omnia/foundation/task/external/node_modules/bin', processPath + '/node_modules/.bin');
|
165 | del.sync('node_modules/@types/node');
|
166 | del.sync('node_modules/@omnia/foundation/node_modules');
|
167 | resolve();
|
168 | });
|
169 | }
|
170 |
|
171 | function afterBuild() {
|
172 | return new Promise(function (resolve, reject) {
|
173 | aotCompile()
|
174 | .then(webpackBundle)
|
175 | .then(resolve)
|
176 | });
|
177 | }
|
178 |
|
179 | function aotCompile() {
|
180 | return new Promise(function (resolve, reject) {
|
181 | console.log(timestamp('[hh:mm:ss]') + ' Aot compile running...');
|
182 |
|
183 | if (!enableRunAot() && (process.argv.length === 0 || process.argv[process.argv.length - 1] !== '--force-aot')) {
|
184 | console.warn('Aot compile disabled in environment.json');
|
185 | resolve();
|
186 | return;
|
187 | }
|
188 | if (appConfig.angular.aot.cleanBefore && appConfig.angular.aot.cleanBefore.length > 0) {
|
189 | del.sync(appConfig.angular.aot.cleanBefore);
|
190 | }
|
191 | fsExtra.copySync('node_modules/@omnia/foundation/task/external/node_modules/gulp-tsc/lib/compiler.js', processPath + '/node_modules/gulp-tsc/lib/compiler.js');
|
192 |
|
193 | jsonfile.writeFileSync('./omf.tsconfig.aot.json', appConfig.angular.aot.ngc);
|
194 | exec('"node_modules/.bin/ngc" -p ./omf.tsconfig.aot.json', function (err, stdout, stderr) {
|
195 | if (stdout)
|
196 | console.log(stdout);
|
197 | if (stderr)
|
198 | console.log(stderr);
|
199 | if (err !== null) {
|
200 | console.log(err);
|
201 | throw "have an exception when aot compiling";
|
202 | }
|
203 | else {
|
204 | if (appConfig.angular.aot.compileAotTsFiles && appConfig.angular.aot.compileAotTsFiles.length > 0) {
|
205 | del.sync('node_modules/@types/node');
|
206 | gulp.src(appConfig.angular.aot.typesForCompileAotTsFiles.concat(appConfig.angular.aot.compileAotTsFiles))
|
207 | .pipe($.tsc({
|
208 | "target": "es5",
|
209 | "module": "commonjs",
|
210 | "moduleResolution": "node",
|
211 | "lib": ["es2015", "dom"],
|
212 | "declaration": false,
|
213 | "sourceMap": false,
|
214 | "removeComments": false,
|
215 | "noImplicitAny": false,
|
216 | "emitDecoratorMetadata": true,
|
217 | "experimentalDecorators": true,
|
218 | "skipLibCheck": true
|
219 | }))
|
220 | .pipe(gulp.dest(appConfig.angular.aot.outDir))
|
221 | .on('end', function () {
|
222 | doWebpackCompile(resolve);
|
223 | });
|
224 | }
|
225 | else {
|
226 | doWebpackCompile(resolve);
|
227 | }
|
228 | }
|
229 | });
|
230 | })
|
231 |
|
232 | function doWebpackCompile(resolve) {
|
233 | if (appConfig.angular.aot.webpackBundleFiles && appConfig.angular.aot.webpackBundleFiles.length > 0) {
|
234 | var totalFiles = 0;
|
235 | var countLoop = 0;
|
236 | for (var i = 0; i < appConfig.angular.aot.webpackBundleFiles.length; i++) {
|
237 | glob(appConfig.angular.aot.webpackBundleFiles[i], function (err, files) {
|
238 | countLoop++;
|
239 | totalFiles = totalFiles + files.length;
|
240 | if (totalFiles === 0 && countLoop === appConfig.angular.aot.webpackBundleFiles.length) {
|
241 | console.log(timestamp('[hh:mm:ss]') + ' Aot compile finished');
|
242 | resolve();
|
243 | }
|
244 | for (var k = 0; k < files.length; k++) {
|
245 | webpackCompile(appConfig.angular.webpack.basePaths, appConfig.angular.webpack.flatModules, appConfig.angular.webpack.ignoreFiles, files[k], function () {
|
246 | totalFiles = totalFiles - 1;
|
247 | if (totalFiles === 0) {
|
248 | if (appConfig.angular.aot.copyOutputAotFilesToTenantResources && appConfig.angular.aot.copyOutputAotFilesToTenantResources.length > 0) {
|
249 | var count = 0;
|
250 | for (var j = 0; j < appConfig.angular.aot.copyOutputAotFilesToTenantResources.length; j++) {
|
251 | gulp.src(appConfig.angular.aot.copyOutputAotFilesToTenantResources[j].source)
|
252 | .pipe(gulp.dest(appConfig.angular.aot.copyOutputAotFilesToTenantResources[j].target))
|
253 | .on('end', function () {
|
254 | count++;
|
255 | if (count === appConfig.angular.aot.copyOutputAotFilesToTenantResources.length) {
|
256 | if (appConfig.angular.aot.cleanAfter && appConfig.angular.aot.cleanAfter.length > 0) {
|
257 | del.sync(appConfig.angular.aot.cleanAfter);
|
258 | }
|
259 | console.log(timestamp('[hh:mm:ss]') + ' Aot compile finished');
|
260 | resolve();
|
261 | }
|
262 | });
|
263 | }
|
264 | }
|
265 | else {
|
266 | if (appConfig.angular.aot.cleanAfter && appConfig.angular.aot.cleanAfter.length > 0) {
|
267 | del.sync(appConfig.angular.aot.cleanAfter);
|
268 | }
|
269 | console.log(timestamp('[hh:mm:ss]') + ' Aot compile finished');
|
270 | resolve();
|
271 | }
|
272 | }
|
273 | });
|
274 | }
|
275 | });
|
276 | }
|
277 | }
|
278 | else {
|
279 | if (appConfig.angular.aot.cleanAfter && appConfig.angular.aot.cleanAfter.length > 0) {
|
280 | del.sync(appConfig.angular.aot.cleanAfter);
|
281 | }
|
282 | console.log(timestamp('[hh:mm:ss]') + ' Aot compile finished');
|
283 | resolve();
|
284 | }
|
285 | }
|
286 | }
|
287 |
|
288 | function webpackBundle(allowLog, files) {
|
289 | return new Promise(function (resolve, reject) {
|
290 | console.log(timestamp('[hh:mm:ss]') + ' Webpack bundle running...');
|
291 | var srcfiles = files || appConfig.angular.webpack.compileFiles;
|
292 | var thresholdThread = appConfig.angular.webpack.thresholdThread || 100;
|
293 | var totalFiles = 0;
|
294 | var countCompletes = 0;
|
295 | if (srcfiles.length === 0) {
|
296 | console.log(timestamp('[hh:mm:ss]') + ' Webpack bundle finished');
|
297 | resolve();
|
298 | }
|
299 | else {
|
300 | globby(srcfiles).then(function (files) {
|
301 | if (files.length < thresholdThread)
|
302 | thresholdThread = files.length;
|
303 |
|
304 | totalFiles = totalFiles + files.length;
|
305 | var countThread = 0;
|
306 |
|
307 | for (var k = 0; k < thresholdThread; k++) {
|
308 | if (files.length > 0) {
|
309 | countThread++;
|
310 | webpackCompile(appConfig.angular.webpack.basePaths, appConfig.angular.webpack.flatModules, appConfig.angular.webpack.ignoreFiles, files.shift(), recursiveCompile, allowLog);
|
311 | }
|
312 |
|
313 | }
|
314 | function recursiveCompile() {
|
315 | countThread--;
|
316 | countCompletes++;
|
317 | if (totalFiles === countCompletes) {
|
318 | console.log(timestamp('[hh:mm:ss]') + ' Webpack bundle finished');
|
319 | resolve();
|
320 | }
|
321 | else if (countThread < thresholdThread && files.length > 0) {
|
322 | countThread++;
|
323 | webpackCompile(appConfig.angular.webpack.basePaths, appConfig.angular.webpack.flatModules, appConfig.angular.webpack.ignoreFiles,
|
324 | files.shift(), recursiveCompile, allowLog);
|
325 | }
|
326 | }
|
327 |
|
328 | })
|
329 | }
|
330 | })
|
331 | }
|
332 |
|
333 |
|
334 |
|
335 |
|
336 | function webpackCompile(basePaths, flatModules, ignoreFiles, filePath, callBack, allowLog) {
|
337 | var isSelfResolveModule = false;
|
338 | var isCompile = false;
|
339 | var destPath = filePath.replace(/\\/g, "/").replace(utils.root('.').replace(/\\/g, "/") + "/", "");
|
340 | if (!isMatchIgnoreFiles(ignoreFiles, destPath)) {
|
341 | let stream = fs.readFileSync(destPath, 'utf8');
|
342 | isCompile = stream.indexOf('webpackJsonp([0],{') !== 0;
|
343 | if (isCompile) {
|
344 | isSelfResolveModule = checkResolveSelfModule(stream);
|
345 | }
|
346 | }
|
347 | if (isCompile) {
|
348 | var namedModulesReplacements = [];
|
349 | namedModulesReplacements.push({
|
350 | pattern: /(.*)/i,
|
351 | replace: function (match) {
|
352 | if (match.toLowerCase() === destPath.toLowerCase()) {
|
353 | return "webpack<<startcurrentmodule>>" + match;
|
354 | }
|
355 | return match;
|
356 | }
|
357 | });
|
358 | for (var i = 0; i < basePaths.length; i++) {
|
359 | namedModulesReplacements.push({
|
360 | pattern: new RegExp(basePaths[i].replace(/\//g, "\\/") + "\\/", 'g'),
|
361 | replace: ""
|
362 | });
|
363 | }
|
364 | namedModulesReplacements.push({
|
365 | pattern: /\/node_modules/g,
|
366 | replace: ""
|
367 | });
|
368 | fs.appendFileSync(destPath, '\r\n //webpack-eof');
|
369 | destPath = "./" + destPath.replace(/[/\\*]/g, "/");
|
370 | var fileName = destPath.substring(destPath.lastIndexOf('/'));
|
371 | webpack(merge(require("./config/webpack.config.js"), {
|
372 | entry: {
|
373 | 'external': './task/config/external.js',
|
374 | 'app': destPath
|
375 | },
|
376 | externals: [
|
377 | function (context, request, callback) {
|
378 | if (destPath.indexOf(request.replace("./", "")) === -1 || destPath.substring(destPath.indexOf(request.replace("./", "")), destPath.length) !== request.replace("./", "")) {
|
379 | return callback(null, "__webpack_require__('" + request.toLowerCase() + "')");
|
380 | }
|
381 | else {
|
382 | callback();
|
383 | }
|
384 | }
|
385 | ],
|
386 | cache: false,
|
387 | output: {
|
388 | pathinfo: true,
|
389 | filename: destPath.replace("./", ''),
|
390 | },
|
391 | plugins: [
|
392 | new webpack.optimize.CommonsChunkPlugin({ name: 'external', filename: 'node_modules/@omnia/foundation/task/temp/external.bundle.js' }),
|
393 | new omfWebpackPlugins.NamedModulesPlugin({
|
394 | replacements: namedModulesReplacements
|
395 | }),
|
396 | new omfWebpackPlugins.ReplaceBundlePlugin([
|
397 | {
|
398 | pattern: /\/\/# sourceMappingURL[\s\S]+\/\/webpack-eof/g,
|
399 | replacement: function (match) {
|
400 | return '//webpack-eof'
|
401 | }
|
402 | },
|
403 | {
|
404 | pattern: /\/\/webpack-eof[\s\S]+}\,\[(.*?)\]/g,
|
405 | replacement: function (match) {
|
406 | return '})},[]'
|
407 | }
|
408 | },
|
409 | {
|
410 | pattern: /webpackJsonp\(\[0\],{[\s\S]+webpack<<startcurrentmodule>>/i,
|
411 | replacement: function (match) {
|
412 | return 'webpackJsonp([0],{"'
|
413 | }
|
414 | },
|
415 | {
|
416 | pattern: /"use strict";[\s\S]+"use strict";/g,
|
417 | replacement: '"use strict";'
|
418 | },
|
419 | {
|
420 | pattern: new RegExp("__webpack_require__\\(\/\\*(.*)\\)", 'g'),
|
421 | replacement: function (match) {
|
422 | return match
|
423 | .replace("/*!", "'")
|
424 | .replace(/\*\/(.*?)\){1}/i, "')")
|
425 | .replace(/ /g, "")
|
426 | .replace(/'(.*?)'/i, function (requireModulePath) {
|
427 | requireModulePath = requireModulePath.replace(/'/g, "");
|
428 | if (requireModulePath.indexOf(".") === 0) {
|
429 | requireModulePath = path.resolve(path.dirname(destPath), requireModulePath);
|
430 | requireModulePath = requireModulePath.replace(/\\/g, "/");
|
431 | for (var i = 0; i < basePaths.length; i++) {
|
432 | requireModulePath = requireModulePath.replace(utils.root(basePaths[i]).replace(/\\/g, "/"), "");
|
433 | }
|
434 | requireModulePath = requireModulePath
|
435 | .replace(utils.root('TenantResources').replace(/\\/g, "/") + '/~/', "")
|
436 | .replace(utils.root('.').replace(/\\/g, "/") + '/~/', "")
|
437 | .replace(utils.root('.').replace(/\\/g, "/"), "")
|
438 | .trim("/");
|
439 | if (requireModulePath.indexOf("/") === 0)
|
440 | requireModulePath = requireModulePath.substring(1, requireModulePath.length);
|
441 | if (requireModulePath.indexOf("node_modules/") === 0)
|
442 | requireModulePath = requireModulePath.replace(/node_modules\//i, "");
|
443 | if (destPath.indexOf(requireModulePath + '.js') > -1) {
|
444 | console.log('have recursive import self : ' + destPath);
|
445 | }
|
446 | }
|
447 |
|
448 | return "'" + requireModulePath.toLowerCase().replace("@omnia/foundation/extensibility/typings/", "@omnia/foundation/extensibility/") + "'";
|
449 | });
|
450 | }
|
451 | },
|
452 | {
|
453 | skip: !isSelfResolveModule,
|
454 | pattern: /webpackJsonp\(\[0\],{[\s\S]+":/g,
|
455 | replacement: function (match) {
|
456 | var moduleId = match.match(/"(.*?)"/)[1]
|
457 | return "omfExecuteModules.push('" + moduleId + "'); ";
|
458 | },
|
459 | insertToEOF: true
|
460 | },
|
461 | {
|
462 | pattern: /;;/g,
|
463 | replacement: ';'
|
464 | },
|
465 | ])
|
466 | ]
|
467 | }), function (err, stats) {
|
468 | if (err) throw new gutil.PluginError("webpack", err);
|
469 | })
|
470 | .plugin("done", function () {
|
471 | if (allowLog)
|
472 | console.log('bundle completed - ' + filePath);
|
473 | if (callBack !== undefined)
|
474 | callBack();
|
475 | });
|
476 | }
|
477 | else {
|
478 | if (callBack !== undefined)
|
479 | callBack();
|
480 | }
|
481 |
|
482 | function checkResolveSelfModule(content) {
|
483 | return content.indexOf('.OmniaControl({') > -1
|
484 | || content.indexOf('.OmniaAdminControl({') > -1
|
485 | || content.indexOf('.OmniaControlTemplate({') > -1
|
486 | || content.indexOf('.TemplateId(') > -1
|
487 | || content.indexOf('.GlueToolbarItem(') > -1
|
488 | || content.indexOf('.GluePaneContent(') > -1
|
489 | || content.indexOf('.GlueTopbarItem(') > -1
|
490 | || content.indexOf('.GluePaneTab(') > -1
|
491 | || content.indexOf('Extensibility_1.TemplateId') > -1
|
492 | || content.indexOf('Extensibility_1.OmniaControl') > -1
|
493 | || content.indexOf('<<webpack-resolve-module>>') > -1
|
494 | }
|
495 | }
|
496 |
|
497 | function isMatchIgnoreFiles(ignoreFiles, filePath) {
|
498 | var isMatch = false
|
499 | for (var i = 0; i < ignoreFiles.length; i++) {
|
500 | if (filePath.indexOf(ignoreFiles[i]) > -1) {
|
501 | isMatch = true;
|
502 | return isMatch;
|
503 | }
|
504 | }
|
505 |
|
506 | return isMatch;
|
507 | }
|
508 |
|
509 | function enableRunAot() {
|
510 | var result = true;
|
511 | var processPath = process.cwd().replace(/\\/g, "/");
|
512 |
|
513 | if (fs.existsSync(processPath + '/environment.json')) {
|
514 | try {
|
515 | var config = require(processPath + '/environment.json');
|
516 | if (config.Angular && config.Angular && config.Angular.AOT && config.Angular.AOT.RunOnBuild === false)
|
517 | result = false
|
518 | }
|
519 | catch (err) {
|
520 | console.log(err);
|
521 | }
|
522 | }
|
523 |
|
524 | return result;
|
525 | }
|
526 |
|
527 | function mergeConfig() {
|
528 | appConfig = require('./config/app.json');
|
529 | var config = core.getConfig('/TaskRunner/Tasks/Angular/task.config.json');
|
530 | if (config !== null)
|
531 | utils.extend(appConfig, config)
|
532 | }
|