CB-11194 Improve cordova load time
authorNikhil Khandelwal <nikhilkh@microsoft.com>
Thu, 5 May 2016 21:38:26 +0000 (14:38 -0700)
committerNikhil Khandelwal <nikhilkh@microsoft.com>
Thu, 5 May 2016 22:28:07 +0000 (15:28 -0700)
 This closes #434

cordova-common.js
src/ConfigChanges/ConfigFile.js
src/util/addProperty.js [new file with mode: 0644]

index e85a701..dcaf7a4 100644 (file)
     under the License.
 */
 
-exports = module.exports = {
-    events: require('./src/events'),
-    superspawn: require('./src/superspawn'),
-
-    ActionStack: require('./src/ActionStack'),
-    CordovaError: require('./src/CordovaError/CordovaError'),
-    CordovaLogger: require('./src/CordovaLogger'),
-    CordovaExternalToolErrorContext: require('./src/CordovaError/CordovaExternalToolErrorContext'),
-    PlatformJson: require('./src/PlatformJson'),
-    ConfigParser: require('./src/ConfigParser/ConfigParser.js'),
-    FileUpdater: require('./src/FileUpdater'),
-
-    PluginInfo: require('./src/PluginInfo/PluginInfo.js'),
-    PluginInfoProvider: require('./src/PluginInfo/PluginInfoProvider.js'),
-
-    PluginManager: require('./src/PluginManager'),
-
-    ConfigChanges: require('./src/ConfigChanges/ConfigChanges.js'),
-    ConfigKeeper: require('./src/ConfigChanges/ConfigKeeper.js'),
-    ConfigFile: require('./src/ConfigChanges/ConfigFile.js'),
-    mungeUtil: require('./src/ConfigChanges/munge-util.js'),
-
-    xmlHelpers: require('./src/util/xml-helpers')
-};
+var addProperty = require('./src/util/addProperty');
+
+module.exports = { };
+
+addProperty(module, 'events', './src/events');
+addProperty(module, 'superspawn', './src/superspawn');
+
+addProperty(module, 'ActionStack', './src/ActionStack');
+addProperty(module, 'CordovaError', './src/CordovaError/CordovaError');
+addProperty(module, 'CordovaLogger', './src/CordovaLogger');
+addProperty(module, 'CordovaExternalToolErrorContext', './src/CordovaError/CordovaExternalToolErrorContext');
+addProperty(module, 'PlatformJson', './src/PlatformJson');
+addProperty(module, 'ConfigParser', './src/ConfigParser/ConfigParser');
+addProperty(module, 'FileUpdater', './src/FileUpdater');
+
+addProperty(module, 'PluginInfo', './src/PluginInfo/PluginInfo');
+addProperty(module, 'PluginInfoProvider', './src/PluginInfo/PluginInfoProvider');
+
+addProperty(module, 'PluginManager', './src/PluginManager');
+
+addProperty(module, 'ConfigChanges', './src/ConfigChanges/ConfigChanges');
+addProperty(module, 'ConfigKeeper', './src/ConfigChanges/ConfigKeeper');
+addProperty(module, 'ConfigFile', './src/ConfigChanges/ConfigFile');
+addProperty(module, 'mungeUtil', './src/ConfigChanges/munge-util');
+
+addProperty(module, 'xmlHelpers', './src/util/xml-helpers');
+
index dd9ebbc..ad12f38 100644 (file)
 var fs = require('fs');
 var path = require('path');
 
-var bplist = require('bplist-parser');
-var et   = require('elementtree');
-var glob = require('glob');
-var plist = require('plist');
-
-var plist_helpers = require('../util/plist-helpers');
-var xml_helpers = require('../util/xml-helpers');
+var modules = {};
+var addProperty = require('../util/addProperty');
+
+// Use delay loading to ensure plist and other node modules to not get loaded
+// on Android, Windows platforms
+addProperty(module, 'bplist', 'bplist-parser', modules);
+addProperty(module, 'et', 'elementtree', modules);
+addProperty(module, 'glob', 'glob', modules);
+addProperty(module, 'plist', 'plist', modules);
+addProperty(module, 'plist_helpers', '../util/plist-helpers', modules);
+addProperty(module, 'xml_helpers', '../util/xml-helpers', modules);
 
 /******************************************************************************
 * ConfigFile class
@@ -67,7 +71,7 @@ function ConfigFile_load() {
     // the same in a future release
     if (ext == '.xml' || ext == '.appxmanifest') {
         self.type = 'xml';
-        self.data = xml_helpers.parseElementtreeSync(filepath);
+        self.data = modules.xml_helpers.parseElementtreeSync(filepath);
     } else {
         // plist file
         self.type = 'plist';
@@ -76,8 +80,8 @@ function ConfigFile_load() {
         //       Do we still need to support binary plist?
         //       If yes, use plist.parseStringSync() and read the file once.
         self.data = isBinaryPlist(filepath) ?
-                bplist.parseBuffer(fs.readFileSync(filepath)) :
-                plist.parse(fs.readFileSync(filepath, 'utf8'));
+                modules.bplist.parseBuffer(fs.readFileSync(filepath)) :
+                modules.plist.parse(fs.readFileSync(filepath, 'utf8'));
     }
 }
 
@@ -88,7 +92,7 @@ ConfigFile.prototype.save = function ConfigFile_save() {
     } else {
         // plist
         var regExp = new RegExp('<string>[ \t\r\n]+?</string>', 'g');
-        fs.writeFileSync(self.filepath, plist.build(self.data).replace(regExp, '<string></string>'));
+        fs.writeFileSync(self.filepath, modules.plist.build(self.data).replace(regExp, '<string></string>'));
     }
     self.is_changed = false;
 };
@@ -98,14 +102,14 @@ ConfigFile.prototype.graft_child = function ConfigFile_graft_child(selector, xml
     var filepath = self.filepath;
     var result;
     if (self.type === 'xml') {
-        var xml_to_graft = [et.XML(xml_child.xml)];
-        result = xml_helpers.graftXML(self.data, xml_to_graft, selector, xml_child.after);
+        var xml_to_graft = [modules.et.XML(xml_child.xml)];
+        result = modules.xml_helpers.graftXML(self.data, xml_to_graft, selector, xml_child.after);
         if ( !result) {
             throw new Error('grafting xml at selector "' + selector + '" from "' + filepath + '" during config install went bad :(');
         }
     } else {
         // plist file
-        result = plist_helpers.graftPLIST(self.data, xml_child.xml, selector);
+        result = modules.plist_helpers.graftPLIST(self.data, xml_child.xml, selector);
         if ( !result ) {
             throw new Error('grafting to plist "' + filepath + '" during config install went bad :(');
         }
@@ -118,11 +122,11 @@ ConfigFile.prototype.prune_child = function ConfigFile_prune_child(selector, xml
     var filepath = self.filepath;
     var result;
     if (self.type === 'xml') {
-        var xml_to_graft = [et.XML(xml_child.xml)];
-        result = xml_helpers.pruneXML(self.data, xml_to_graft, selector);
+        var xml_to_graft = [modules.et.XML(xml_child.xml)];
+        result = modules.xml_helpers.pruneXML(self.data, xml_to_graft, selector);
     } else {
         // plist file
-        result = plist_helpers.prunePLIST(self.data, xml_child.xml, selector);
+        result = modules.plist_helpers.prunePLIST(self.data, xml_child.xml, selector);
     }
     if (!result) {
         var err_msg = 'Pruning at selector "' + selector + '" from "' + filepath + '" went bad.';
@@ -140,7 +144,7 @@ function resolveConfigFilePath(project_dir, platform, file) {
 
     if (file.indexOf('*') > -1) {
         // handle wildcards in targets using glob.
-        matches = glob.sync(path.join(project_dir, '**', file));
+        matches = modules.glob.sync(path.join(project_dir, '**', file));
         if (matches.length) filepath = matches[0];
 
         // [CB-5989] multiple Info.plist files may exist. default to $PROJECT_NAME-Info.plist
@@ -167,7 +171,7 @@ function resolveConfigFilePath(project_dir, platform, file) {
         } else if (platform == 'android') {
             filepath = path.join(project_dir, 'res', 'xml', 'config.xml');
         } else {
-            matches = glob.sync(path.join(project_dir, '**', 'config.xml'));
+            matches = modules.glob.sync(path.join(project_dir, '**', 'config.xml'));
             if (matches.length) filepath = matches[0];
         }
         return filepath;
@@ -180,7 +184,7 @@ function resolveConfigFilePath(project_dir, platform, file) {
 // Find out the real name of an iOS project
 // TODO: glob is slow, need a better way or caching, or avoid using more than once.
 function getIOSProjectname(project_dir) {
-    var matches = glob.sync(path.join(project_dir, '*.xcodeproj'));
+    var matches = modules.glob.sync(path.join(project_dir, '*.xcodeproj'));
     var iospath;
     if (matches.length === 1) {
         iospath = path.basename(matches[0],'.xcodeproj');
diff --git a/src/util/addProperty.js b/src/util/addProperty.js
new file mode 100644 (file)
index 0000000..5156a2b
--- /dev/null
@@ -0,0 +1,13 @@
+module.exports = function addProperty(module, property, modulePath, obj) {
+    
+    obj = obj || module.exports;
+    // Add properties as getter to delay load the modules on first invocation
+    Object.defineProperty(obj, property, {
+        configurable: true,
+        get: function () {
+            var delayLoadedModule = module.require(modulePath);
+            obj[property] = delayLoadedModule;
+            return delayLoadedModule;
+        }
+    });
+};