@omnia/foundation
Version:
Provide omnia foundation typings and tooling work on client side for omnia extension.
533 lines (502 loc) • 24.9 kB
JavaScript
;
var processPath = process.cwd().replace(/\\/g, "/")
, fsExtra = require('../../../fs-extra')
, del = require('../../../del');
fsExtra.copySync('node_modules/@omnia/foundation/task/external/node_modules/webpack/lib/FunctionModuleTemplatePlugin.js', 'node_modules/webpack/lib/FunctionModuleTemplatePlugin.js');
// delete local node_modules
del.sync('node_modules/@omnia/foundation/node_modules');
var gulp = require('gulp')
, glob = require('../../../glob')
, globby = require('../../../globby')
, chokidar = require('../../../chokidar')
, fs = require('fs')
, $ = require('../../../gulp-load-plugins')({
pattern: [
'gulp-*'
],
rename: {
}
})
, timestamp = require('../../../console-timestamp')
, webpack = require("../../../webpack")
, namedModulesPlugin = require('../../../webpack/lib/NamedModulesPlugin')
, gutil = require("../../../gulp-util")
, merge = require('../../../webpack-merge')
, exec = require('child_process').exec
, jsonfile = require('../../../jsonfile')
, extend = require('../../../deep-extend')
, path = require('path')
, omfWebpackPlugins = require('./services/omf.webpack.plugins')
, utils = require('@omnia/tooling/shared/omf.utils.js')
, core = require('@omnia/tooling/shared/omf.core.js');
var appConfig = {};
mergeConfig();
core.registerBuildTask({ type: core.BuildType.BeforeBuild, order: 9, task: beforeBuild });
core.registerBuildTask({ type: core.BuildType.AfterBuild, order: 1, task: afterBuild });
gulp.task('omf-webpack-bundle', function (cb) {
var files, i = process.argv.indexOf("--files");
if (i > -1 && process.argv.length - 1 > i) {
files = process.argv[i + 1];
webpackBundle(true, files.split(','));
}
else {
webpackBundle(true).then(cb);
}
});
gulp.task('omf-webpack-bundle-libs', function (cb) {
if (appConfig.angular.webpack.bundleLibs && appConfig.angular.webpack.bundleLibs.configFile
&& appConfig.angular.webpack.bundleLibs.configFile.length > 0 && appConfig.angular.webpack.bundleLibs.outputFile && appConfig.angular.webpack.bundleLibs.outputFile.length > 0) {
let stream = fs.readFileSync(appConfig.angular.webpack.bundleLibs.configFile, 'utf8');
if (stream.indexOf("//webpack-eof") === -1)
fs.appendFileSync(appConfig.angular.webpack.bundleLibs.configFile, '\r\n //webpack-eof');
var basePaths = ["node_modules"];
webpack(merge(require("./config/webpack.config.js"), {
entry: {
'vendor': './task/config/external.js',
'app': processPath + '/' + appConfig.angular.webpack.bundleLibs.configFile
},
target: "web",
output: {
pathinfo: true,
filename: appConfig.angular.webpack.bundleLibs.outputFile,
},
externals: [
function (context, request, callback) {
if (request.toLowerCase().indexOf("@angular") === 0 || request.toLowerCase().indexOf("rxjs") === 0) {
return callback(null, "__webpack_require__('" + request.toLowerCase() + "')");
}
else {
callback();
}
}
],
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel-loader',
query: {
compact: false,
presets: ['es2015'],
ignore: [
]
}
}
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: 'node_modules/@omnia/foundation/task/temp/external.bundle.js' }),
new omfWebpackPlugins.NamedModulesPlugin({
replacements: [
{
pattern: /\/node_modules/g,
replace: ""
}
]
}),
new omfWebpackPlugins.ReplaceBundlePlugin([
{
pattern: /\/\/webpack-eof[\s\S]+}\,\[(.*?)\]/g,
replacement: function (match) {
return '})},[]'
}
},
{
pattern: new RegExp("__webpack_require__\\(\/\\*(.*)\\)", 'g'),
replacement: function (match) {
return match
.replace(/\/\*!(.*?)\/(.*?)"/i, '"')
.replace(/\/\*!(.*?)\/(.*?)\)/i, function (requireModulePath) {
return requireModulePath
.replace("/*!", '"')
.replace(/\*\/(.*?)\)/i, '")')
.replace(/ /g, "")
})
}
}
])
]
}),
function (err, stats) {
if (err) throw new gutil.PluginError("webpack", err);
})
.plugin("done", function () {
let stream = fs.readFileSync(appConfig.angular.webpack.bundleLibs.configFile, 'utf8');
stream.replace(/\/\/webpack-eof/g, "")
fs.writeFileSync(appConfig.angular.webpack.bundleLibs.configFile, stream);
if (appConfig.angular.webpack.bundleLibs.concatToOutPut
&& appConfig.angular.webpack.bundleLibs.concatToOutPut.files
&& appConfig.angular.webpack.bundleLibs.concatToOutPut.files.length > 0
) {
var temFilePath = appConfig.angular.webpack.bundleLibs.outputFile.replace(/\\/g, "/");
var outFileName = temFilePath.substring(temFilePath.lastIndexOf('/'));
var folderPath = ".";
if (temFilePath.lastIndexOf('/') > 0)
folderPath = temFilePath.substring(0, temFilePath.lastIndexOf('/'))
gulp.src([appConfig.angular.webpack.bundleLibs.outputFile].concat(appConfig.angular.webpack.bundleLibs.concatToOutPut.files))
.pipe($.concat(outFileName))
.pipe(gulp.dest(folderPath))
.on('end', function () {
console.log('bundle completed');
cb();
});
}
else {
console.log('bundle completed');
cb();
}
});
}
else {
console.log('Not found configs angular.webpack.bundleLibs.configFile or appConfig.angular.webpack.bundleLibs.outputFile');
}
});
function beforeBuild() {
return new Promise(function (resolve, reject) {
fsExtra.copySync('node_modules/@omnia/foundation/task/external/node_modules/bin', processPath + '/node_modules/.bin');
del.sync('node_modules/@types/node');
del.sync('node_modules/@omnia/foundation/node_modules');
resolve();
});
}
function afterBuild() {
return new Promise(function (resolve, reject) {
aotCompile()
.then(webpackBundle)
.then(resolve)
});
}
function aotCompile() {
return new Promise(function (resolve, reject) {
console.log(timestamp('[hh:mm:ss]') + ' Aot compile running...');
if (!enableRunAot() && (process.argv.length === 0 || process.argv[process.argv.length - 1] !== '--force-aot')) {
console.warn('Aot compile disabled in environment.json');
resolve();
return;
}
if (appConfig.angular.aot.cleanBefore && appConfig.angular.aot.cleanBefore.length > 0) {
del.sync(appConfig.angular.aot.cleanBefore);
}
fsExtra.copySync('node_modules/@omnia/foundation/task/external/node_modules/gulp-tsc/lib/compiler.js', processPath + '/node_modules/gulp-tsc/lib/compiler.js');
jsonfile.writeFileSync('./omf.tsconfig.aot.json', appConfig.angular.aot.ngc);
exec('"node_modules/.bin/ngc" -p ./omf.tsconfig.aot.json', function (err, stdout, stderr) {
if (stdout)
console.log(stdout);
if (stderr)
console.log(stderr);
if (err !== null) {
console.log(err);
throw "have an exception when aot compiling";
}
else {
if (appConfig.angular.aot.compileAotTsFiles && appConfig.angular.aot.compileAotTsFiles.length > 0) {
del.sync('node_modules/@types/node');
gulp.src(appConfig.angular.aot.typesForCompileAotTsFiles.concat(appConfig.angular.aot.compileAotTsFiles))
.pipe($.tsc({
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"lib": ["es2015", "dom"],
"declaration": false,
"sourceMap": false,
"removeComments": false,
"noImplicitAny": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"skipLibCheck": true
}))
.pipe(gulp.dest(appConfig.angular.aot.outDir))
.on('end', function () {
doWebpackCompile(resolve);
});
}
else {
doWebpackCompile(resolve);
}
}
});
})
function doWebpackCompile(resolve) {
if (appConfig.angular.aot.webpackBundleFiles && appConfig.angular.aot.webpackBundleFiles.length > 0) {
var totalFiles = 0;
var countLoop = 0;
for (var i = 0; i < appConfig.angular.aot.webpackBundleFiles.length; i++) {
glob(appConfig.angular.aot.webpackBundleFiles[i], function (err, files) {
countLoop++;
totalFiles = totalFiles + files.length;
if (totalFiles === 0 && countLoop === appConfig.angular.aot.webpackBundleFiles.length) {
console.log(timestamp('[hh:mm:ss]') + ' Aot compile finished');
resolve();
}
for (var k = 0; k < files.length; k++) {
webpackCompile(appConfig.angular.webpack.basePaths, appConfig.angular.webpack.flatModules, appConfig.angular.webpack.ignoreFiles, files[k], function () {
totalFiles = totalFiles - 1;
if (totalFiles === 0) {
if (appConfig.angular.aot.copyOutputAotFilesToTenantResources && appConfig.angular.aot.copyOutputAotFilesToTenantResources.length > 0) {
var count = 0;
for (var j = 0; j < appConfig.angular.aot.copyOutputAotFilesToTenantResources.length; j++) {
gulp.src(appConfig.angular.aot.copyOutputAotFilesToTenantResources[j].source)
.pipe(gulp.dest(appConfig.angular.aot.copyOutputAotFilesToTenantResources[j].target))
.on('end', function () {
count++;
if (count === appConfig.angular.aot.copyOutputAotFilesToTenantResources.length) {
if (appConfig.angular.aot.cleanAfter && appConfig.angular.aot.cleanAfter.length > 0) {
del.sync(appConfig.angular.aot.cleanAfter);
}
console.log(timestamp('[hh:mm:ss]') + ' Aot compile finished');
resolve();
}
});
}
}
else {
if (appConfig.angular.aot.cleanAfter && appConfig.angular.aot.cleanAfter.length > 0) {
del.sync(appConfig.angular.aot.cleanAfter);
}
console.log(timestamp('[hh:mm:ss]') + ' Aot compile finished');
resolve();
}
}
});
}
});
}
}
else {
if (appConfig.angular.aot.cleanAfter && appConfig.angular.aot.cleanAfter.length > 0) {
del.sync(appConfig.angular.aot.cleanAfter);
}
console.log(timestamp('[hh:mm:ss]') + ' Aot compile finished');
resolve();
}
}
}
function webpackBundle(allowLog, files) {
return new Promise(function (resolve, reject) {
console.log(timestamp('[hh:mm:ss]') + ' Webpack bundle running...');
var srcfiles = files || appConfig.angular.webpack.compileFiles;
var thresholdThread = appConfig.angular.webpack.thresholdThread || 100;
var totalFiles = 0;
var countCompletes = 0;
if (srcfiles.length === 0) {
console.log(timestamp('[hh:mm:ss]') + ' Webpack bundle finished');
resolve();
}
else {
globby(srcfiles).then(function (files) {
if (files.length < thresholdThread)
thresholdThread = files.length;
totalFiles = totalFiles + files.length;
var countThread = 0;
for (var k = 0; k < thresholdThread; k++) {
if (files.length > 0) {
countThread++;
webpackCompile(appConfig.angular.webpack.basePaths, appConfig.angular.webpack.flatModules, appConfig.angular.webpack.ignoreFiles, files.shift(), recursiveCompile, allowLog);
}
}
function recursiveCompile() {
countThread--;
countCompletes++;
if (totalFiles === countCompletes) {
console.log(timestamp('[hh:mm:ss]') + ' Webpack bundle finished');
resolve();
}
else if (countThread < thresholdThread && files.length > 0) {
countThread++;
webpackCompile(appConfig.angular.webpack.basePaths, appConfig.angular.webpack.flatModules, appConfig.angular.webpack.ignoreFiles,
files.shift(), recursiveCompile, allowLog);
}
}
})
}
})
}
function webpackCompile(basePaths, flatModules, ignoreFiles, filePath, callBack, allowLog) {
var isSelfResolveModule = false;
var isCompile = false;
var destPath = filePath.replace(/\\/g, "/").replace(utils.root('.').replace(/\\/g, "/") + "/", "");
if (!isMatchIgnoreFiles(ignoreFiles, destPath)) {
let stream = fs.readFileSync(destPath, 'utf8');
isCompile = stream.indexOf('webpackJsonp([0],{') !== 0;
if (isCompile) {
isSelfResolveModule = checkResolveSelfModule(stream);
}
}
if (isCompile) {
var namedModulesReplacements = [];
namedModulesReplacements.push({
pattern: /(.*)/i,
replace: function (match) {
if (match.toLowerCase() === destPath.toLowerCase()) {
return "webpack<<startcurrentmodule>>" + match;
}
return match;
}
});
for (var i = 0; i < basePaths.length; i++) {
namedModulesReplacements.push({
pattern: new RegExp(basePaths[i].replace(/\//g, "\\/") + "\\/", 'g'),
replace: ""
});
}
namedModulesReplacements.push({
pattern: /\/node_modules/g,
replace: ""
});
fs.appendFileSync(destPath, '\r\n //webpack-eof');
destPath = "./" + destPath.replace(/[/\\*]/g, "/");
var fileName = destPath.substring(destPath.lastIndexOf('/'));
webpack(merge(require("./config/webpack.config.js"), {
entry: {
'external': './task/config/external.js',
'app': destPath
},
externals: [
function (context, request, callback) {
if (destPath.indexOf(request.replace("./", "")) === -1 || destPath.substring(destPath.indexOf(request.replace("./", "")), destPath.length) !== request.replace("./", "")) {
return callback(null, "__webpack_require__('" + request.toLowerCase() + "')");
}
else {
callback();
}
}
],
cache: false,
output: {
pathinfo: true,
filename: destPath.replace("./", ''),
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({ name: 'external', filename: 'node_modules/@omnia/foundation/task/temp/external.bundle.js' }),
new omfWebpackPlugins.NamedModulesPlugin({
replacements: namedModulesReplacements
}),
new omfWebpackPlugins.ReplaceBundlePlugin([
{
pattern: /\/\/# sourceMappingURL[\s\S]+\/\/webpack-eof/g,
replacement: function (match) {
return '//webpack-eof'
}
},
{
pattern: /\/\/webpack-eof[\s\S]+}\,\[(.*?)\]/g,
replacement: function (match) {
return '})},[]'
}
},
{
pattern: /webpackJsonp\(\[0\],{[\s\S]+webpack<<startcurrentmodule>>/i,
replacement: function (match) {
return 'webpackJsonp([0],{"'
}
},
{
pattern: /"use strict";[\s\S]+"use strict";/g,
replacement: '"use strict";'
},
{
pattern: new RegExp("__webpack_require__\\(\/\\*(.*)\\)", 'g'),
replacement: function (match) {
return match
.replace("/*!", "'")
.replace(/\*\/(.*?)\){1}/i, "')")
.replace(/ /g, "")
.replace(/'(.*?)'/i, function (requireModulePath) {
requireModulePath = requireModulePath.replace(/'/g, "");
if (requireModulePath.indexOf(".") === 0) {
requireModulePath = path.resolve(path.dirname(destPath), requireModulePath);
requireModulePath = requireModulePath.replace(/\\/g, "/");
for (var i = 0; i < basePaths.length; i++) {
requireModulePath = requireModulePath.replace(utils.root(basePaths[i]).replace(/\\/g, "/"), "");
}
requireModulePath = requireModulePath
.replace(utils.root('TenantResources').replace(/\\/g, "/") + '/~/', "")
.replace(utils.root('.').replace(/\\/g, "/") + '/~/', "")
.replace(utils.root('.').replace(/\\/g, "/"), "")
.trim("/");
if (requireModulePath.indexOf("/") === 0)
requireModulePath = requireModulePath.substring(1, requireModulePath.length);
if (requireModulePath.indexOf("node_modules/") === 0)
requireModulePath = requireModulePath.replace(/node_modules\//i, "");
if (destPath.indexOf(requireModulePath + '.js') > -1) {
console.log('have recursive import self : ' + destPath);
}
}
return "'" + requireModulePath.toLowerCase().replace("@omnia/foundation/extensibility/typings/", "@omnia/foundation/extensibility/") + "'";
});
}
},
{
skip: !isSelfResolveModule,
pattern: /webpackJsonp\(\[0\],{[\s\S]+":/g,
replacement: function (match) {
var moduleId = match.match(/"(.*?)"/)[1]
return "omfExecuteModules.push('" + moduleId + "'); ";
},
insertToEOF: true
},
{
pattern: /;;/g,
replacement: ';'
},
])
]
}), function (err, stats) {
if (err) throw new gutil.PluginError("webpack", err);
})
.plugin("done", function () {
if (allowLog)
console.log('bundle completed - ' + filePath);
if (callBack !== undefined)
callBack();
});
}
else {
if (callBack !== undefined)
callBack();
}
function checkResolveSelfModule(content) {
return content.indexOf('.OmniaControl({') > -1
|| content.indexOf('.OmniaAdminControl({') > -1
|| content.indexOf('.OmniaControlTemplate({') > -1
|| content.indexOf('.TemplateId(') > -1
|| content.indexOf('.GlueToolbarItem(') > -1
|| content.indexOf('.GluePaneContent(') > -1
|| content.indexOf('.GlueTopbarItem(') > -1
|| content.indexOf('.GluePaneTab(') > -1
|| content.indexOf('Extensibility_1.TemplateId') > -1
|| content.indexOf('Extensibility_1.OmniaControl') > -1
|| content.indexOf('<<webpack-resolve-module>>') > -1
}
}
function isMatchIgnoreFiles(ignoreFiles, filePath) {
var isMatch = false
for (var i = 0; i < ignoreFiles.length; i++) {
if (filePath.indexOf(ignoreFiles[i]) > -1) {
isMatch = true;
return isMatch;
}
}
return isMatch;
}
function enableRunAot() {
var result = true;
var processPath = process.cwd().replace(/\\/g, "/");
if (fs.existsSync(processPath + '/environment.json')) {
try {
var config = require(processPath + '/environment.json');
if (config.Angular && config.Angular && config.Angular.AOT && config.Angular.AOT.RunOnBuild === false)
result = false
}
catch (err) {
console.log(err);
}
}
return result;
}
function mergeConfig() {
appConfig = require('./config/app.json');
var config = core.getConfig('/TaskRunner/Tasks/Angular/task.config.json');
if (config !== null)
utils.extend(appConfig, config)
}