public inbox for [email protected]  
help / color / mirror / Atom feed
[pgAdmin4][Patch]: Load module's JS files only when required
13+ messages / 3 participants
[nested] [flat]

* [pgAdmin4][Patch]: Load module's JS files only when required
@ 2017-05-22 05:50  Surinder Kumar <[email protected]>
  0 siblings, 1 reply; 13+ messages in thread

From: Surinder Kumar @ 2017-05-22 05:50 UTC (permalink / raw)
  To: pgadmin-hackers

Hi

As per pgAdmin4 design, template JS files can either be preloaded or load
when a specific node expands (by adding for e.g.: when: 'server').

The JS files of several modules found to be loaded when pgAdmin4 loads
which results in increasing:

   - the number of http requests
   - latency(greater request time)
   - pgAdmin4 load time

*Tested on Firefox:*

Before applying patch

   - http requests - 143
   - Content size - 3.4 MB
   - Load time: 4.1s (onload: 524ms)

After applying patch

   - http requests: 68
   - Content size: 2.1 MB
   - Load time: 2.84s (onload: 481ms)


Also, I found the http request for gravtar takes much time(depending on
internet speed) to load which increases load time.
https://secure.gravatar.com/avatar/d30aea269994f01256a99a8e7154a328?s=100&d=retro&r=g

Shouldn't the gravatar image be replaced with custom image ? I don't see
its any use except displaying for user.

*Patch changes:*

1) Load following modules JS when 'servers' node expands:

   -  Roles
   -  FileManager
   -  Backup
   -  Datagrid
   -  Grant wizard
   -  Import/Export, Maintenance & restore
   -  Sqleditor

2) Load Debugger JS when database node expands

3) Load Flotr2 when render function is called in dashboard.js

4) Load BigNumber library when sorting is performed on Statistics tab in
backgrid.pgadmin.js

5) Remove 'backgrid.select.all' from dependency list(user_management.js) as
it had no use.

After applying this patch, Menu items such "Query tool", "Grant wizard"
don't appear in Tools menu.
I have logged an RM2424 <https://redmine.postgresql.org/issues/2424; to
track this.

Please find attached patch and review.

Thanks
Surinder


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers


Attachments:

  [application/octet-stream] load_module_js_when_required.patch (16.5K, 3-load_module_js_when_required.patch)
  download | inline diff:
diff --git a/web/pgadmin/browser/server_groups/servers/roles/__init__.py b/web/pgadmin/browser/server_groups/servers/roles/__init__.py
index da8d06a..7cdbe39 100644
--- a/web/pgadmin/browser/server_groups/servers/roles/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/roles/__init__.py
@@ -9,7 +9,7 @@
 import re
 from functools import wraps
 
-import pgadmin.browser.server_groups as sg
+import pgadmin.browser.server_groups.servers as servers
 import simplejson as json
 from flask import render_template, request, jsonify, current_app
 from flask_babel import gettext as _
@@ -55,7 +55,7 @@ class RoleModule(CollectionNodeModule):
         Load the module script for server, when any of the server-group node is
         initialized.
         """
-        return sg.ServerGroupModule.NODE_TYPE
+        return servers.ServerModule.NODE_TYPE
 
     @property
     def csssnippets(self):
diff --git a/web/pgadmin/dashboard/templates/dashboard/js/dashboard.js b/web/pgadmin/dashboard/templates/dashboard/js/dashboard.js
index 35ed102..291029c 100644
--- a/web/pgadmin/dashboard/templates/dashboard/js/dashboard.js
+++ b/web/pgadmin/dashboard/templates/dashboard/js/dashboard.js
@@ -1,6 +1,6 @@
 define([
-    'require', 'jquery', 'pgadmin', 'underscore', 'backbone', 'sources/gettext', 'flotr2', 'wcdocker',
-    'pgadmin.browser', 'bootstrap'
+    'require', 'jquery', 'pgadmin', 'underscore', 'backbone',
+    'sources/gettext', 'wcdocker', 'pgadmin.browser', 'bootstrap'
     ],
 function(r, $, pgAdmin, _, Backbone, gettext) {
 
@@ -181,7 +181,11 @@ function(r, $, pgAdmin, _, Backbone, gettext) {
             var div = dashboardPanel.layout().scene().find('.pg-panel-content');
             if ($(div).find(container).length) { // Exists?
                 if (container.clientHeight > 0 && container.clientWidth > 0) { // Not hidden?
+                  // Load flotr2 only when required
+                  var Flotr2 = 'flotr2';
+                  require([Flotr2], function(Flotr){
                     Flotr.draw(container, dataset, options);
+                  })
                 }
             } else {
                 return;
diff --git a/web/pgadmin/misc/file_manager/__init__.py b/web/pgadmin/misc/file_manager/__init__.py
index 85d7fb4..2505b79 100644
--- a/web/pgadmin/misc/file_manager/__init__.py
+++ b/web/pgadmin/misc/file_manager/__init__.py
@@ -125,7 +125,7 @@ class FileManagerModule(PgAdminModule):
             {
                 'name': 'pgadmin.file_manager',
                 'path': url_for('file_manager.index') + 'file_manager',
-                'when': None
+                'when': 'server'
             },
         ]
 
diff --git a/web/pgadmin/static/js/backgrid.pgadmin.js b/web/pgadmin/static/js/backgrid.pgadmin.js
index 64f0cb6..da5057e 100644
--- a/web/pgadmin/static/js/backgrid.pgadmin.js
+++ b/web/pgadmin/static/js/backgrid.pgadmin.js
@@ -2,13 +2,13 @@
   // Set up Backform appropriately for the environment. Start with AMD.
   if (typeof define === 'function' && define.amd) {
     define([
-      'underscore', 'jquery', 'backbone', 'backform', 'backgrid', 'alertify',
-      'moment', 'bignumber', 'bootstrap.datetimepicker'
+      'require', 'underscore', 'jquery', 'backbone', 'backform', 'backgrid',
+      'alertify', 'moment', 'bootstrap.datetimepicker'
     ],
-     function(_, $, Backbone, Backform, Backgrid, Alertify, moment, BigNumber) {
+     function(require, _, $, Backbone, Backform, Backgrid, Alertify, moment) {
       // Export global even in AMD case in case this script is loaded with
       // others that may still expect a global Backform.
-      return factory(root, _, $, Backbone, Backform, Alertify, moment, BigNumber);
+      return factory(root, require, _, $, Backbone, Backform, Alertify, moment);
     });
 
   // Next for Node.js or CommonJS. jQuery may not be needed as a module.
@@ -25,7 +25,7 @@
   } else {
     factory(root, root._, (root.jQuery || root.Zepto || root.ender || root.$), root.Backbone, root.Backform);
   }
-} (this, function(root, _, $, Backbone, Backform, Alertify, moment, BigNumber) {
+} (this, function(root, require, _, $, Backbone, Backform, Alertify, moment) {
   /*
      * Add mechanism in backgrid to render different types of cells in
      * same column;
@@ -56,106 +56,112 @@
    * convert it into BigNumber object and make comparison to perform sorting.
    */
 
-  _.extend(Backgrid.Body.prototype, {
-    sort: function (column, direction) {
-
-      if (!_.contains(["ascending", "descending", null], direction)) {
-        throw new RangeError('direction must be one of "ascending", "descending" or `null`');
-      }
+    _.extend(Backgrid.Body.prototype, {
+      BigNumber: undefined,
+      sort: function (column, direction) {
+            // Load bignumber only when required
+        var Bignumber = 'bignumber',
+          self = this;
+
+        require([Bignumber], function(BigNumber){
+          BigNumber = BigNumber;
+          if (!_.contains(["ascending", "descending", null], direction)) {
+            throw new RangeError('direction must be one of "ascending", "descending" or `null`');
+          }
 
-      if (_.isString(column)) column = this.columns.findWhere({name: column});
+          if (_.isString(column)) column = self.columns.findWhere({name: column});
 
-      var collection = this.collection;
+          var collection = self.collection;
 
-      var order;
-      if (direction === "ascending") order = -1;
-      else if (direction === "descending") order = 1;
-      else order = null;
+          var order;
+          if (direction === "ascending") order = -1;
+          else if (direction === "descending") order = 1;
+          else order = null;
 
-      // Get column type and pass it to comparator.
-      var col_type = column.get('cell').prototype.className || 'string-cell',
-          comparator = this.makeComparator(column.get("name"), order,
-                                          order ?
-                                          column.sortValue() :
-                                          function (model) {
-                                            return model.cid.replace('c', '') * 1;
-                                          }, col_type);
+          // Get column type and pass it to comparator.
+          var col_type = column.get('cell').prototype.className || 'string-cell',
+              comparator = self.makeComparator(column.get("name"), order,
+                                              order ?
+                                              column.sortValue() :
+                                              function (model) {
+                                                return model.cid.replace('c', '') * 1;
+                                              }, col_type);
 
-      if (Backbone.PageableCollection &&
-          collection instanceof Backbone.PageableCollection) {
+          if (Backbone.PageableCollection &&
+              collection instanceof Backbone.PageableCollection) {
 
-        collection.setSorting(order && column.get("name"), order,
-                              {sortValue: column.sortValue()});
+            collection.setSorting(order && column.get("name"), order,
+                                  {sortValue: column.sortValue()});
 
-        if (collection.fullCollection) {
-          // If order is null, pageable will remove the comparator on both sides,
-          // in this case the default insertion order comparator needs to be
-          // attached to get back to the order before sorting.
-          if (collection.fullCollection.comparator == null) {
-            collection.fullCollection.comparator = comparator;
+            if (collection.fullCollection) {
+              // If order is null, pageable will remove the comparator on both sides,
+              // in this case the default insertion order comparator needs to be
+              // attached to get back to the order before sorting.
+              if (collection.fullCollection.comparator == null) {
+                collection.fullCollection.comparator = comparator;
+              }
+              collection.fullCollection.sort();
+              collection.trigger("backgrid:sorted", column, direction, collection);
+            }
+            else collection.fetch({reset: true, success: function () {
+              collection.trigger("backgrid:sorted", column, direction, collection);
+            }});
+          }
+          else {
+            collection.comparator = comparator;
+            collection.sort();
+            collection.trigger("backgrid:sorted", column, direction, collection);
           }
-          collection.fullCollection.sort();
-          collection.trigger("backgrid:sorted", column, direction, collection);
-        }
-        else collection.fetch({reset: true, success: function () {
-          collection.trigger("backgrid:sorted", column, direction, collection);
-        }});
-      }
-      else {
-        collection.comparator = comparator;
-        collection.sort();
-        collection.trigger("backgrid:sorted", column, direction, collection);
-      }
-
-      column.set("direction", direction);
 
-      return this;
-    },
-    makeComparator: function (attr, order, func, type) {
+          column.set("direction", direction);
 
-      return function (left, right) {
-        // extract the values from the models
+          return self;
+        });
+      },
+      makeComparator: function (attr, order, func, type) {
+        return function (left, right) {
+          // extract the values from the models
+
+          var l = func(left, attr), r = func(right, attr), t;
+
+          var types = ['number-cell', 'integer-cell'];
+            if (_.include(types, type)) {
+            var _l, _r;
+            // NaN if invalid number
+            try {
+              _l = new BigNumber(l);
+            } catch(err) {
+              _l = NaN;
+            }
 
-        var l = func(left, attr), r = func(right, attr), t;
+            try {
+              _r = new BigNumber(r);
+            } catch(err) {
+              _r = NaN;
+            }
 
-        var types = ['number-cell', 'integer-cell'];
-        if (_.include(types, type)) {
-          var _l, _r;
-          // NaN if invalid number
-          try {
-            _l = new BigNumber(l);
-          } catch(err) {
-            _l = NaN;
-          }
+            // if descending order, swap left and right
+            if (order === 1) t = _l, _l = _r, _r = t;
 
-          try {
-            _r = new BigNumber(r);
-          } catch(err) {
-            _r = NaN;
+            if (_l.eq(_r))  // If both are equals
+              return 0;
+            else if (_l.lt(_r)) // If left is less than right
+              return -1;
+            else
+              return 1;
           }
+            else {
+            // if descending order, swap left and right
+            if (order === 1) t = l, l = r, r = t;
 
-          // if descending order, swap left and right
-          if (order === 1) t = _l, _l = _r, _r = t;
-
-          if (_l.eq(_r))  // If both are equals
-            return 0;
-          else if (_l.lt(_r)) // If left is less than right
-            return -1;
-          else
+             // compare as usual
+            if (l === r) return 0;
+            else if (l < r) return -1;
             return 1;
-        }
-        else {
-          // if descending order, swap left and right
-          if (order === 1) t = l, l = r, r = t;
-
-           // compare as usual
-          if (l === r) return 0;
-          else if (l < r) return -1;
-          return 1;
-        }
-      };
-    }
-  });
+          }
+        };
+      }
+    });
 
   _.extend(Backgrid.Row.prototype, {
     makeCell: function (column) {
diff --git a/web/pgadmin/tools/backup/__init__.py b/web/pgadmin/tools/backup/__init__.py
index 9c0537a..e45a5ce 100644
--- a/web/pgadmin/tools/backup/__init__.py
+++ b/web/pgadmin/tools/backup/__init__.py
@@ -49,7 +49,7 @@ class BackupModule(PgAdminModule):
         return [{
             'name': 'pgadmin.tools.backup',
             'path': url_for('backup.index') + 'backup',
-            'when': None
+            'when': 'server'
         }]
 
     def show_system_objects(self):
diff --git a/web/pgadmin/tools/datagrid/__init__.py b/web/pgadmin/tools/datagrid/__init__.py
index f4629fc..8da4de3 100644
--- a/web/pgadmin/tools/datagrid/__init__.py
+++ b/web/pgadmin/tools/datagrid/__init__.py
@@ -43,7 +43,7 @@ class DataGridModule(PgAdminModule):
         return [{
             'name': 'pgadmin.datagrid',
             'path': url_for('datagrid.index') + "datagrid",
-            'when': None
+            'when': 'server'
         }]
 
     def get_panels(self):
diff --git a/web/pgadmin/tools/debugger/__init__.py b/web/pgadmin/tools/debugger/__init__.py
index 2c0dbc4..e6288b1 100644
--- a/web/pgadmin/tools/debugger/__init__.py
+++ b/web/pgadmin/tools/debugger/__init__.py
@@ -55,7 +55,7 @@ class DebuggerModule(PgAdminModule):
             scripts.append({
                 'name': name,
                 'path': url_for('debugger.index') + script,
-                'when': None
+                'when': 'database'
             })
 
         return scripts
diff --git a/web/pgadmin/tools/grant_wizard/__init__.py b/web/pgadmin/tools/grant_wizard/__init__.py
index 9c6f47e..661c9ff 100644
--- a/web/pgadmin/tools/grant_wizard/__init__.py
+++ b/web/pgadmin/tools/grant_wizard/__init__.py
@@ -66,12 +66,12 @@ class GrantWizardModule(PgAdminModule):
         scripts.append({
             'name': 'pgadmin.tools.grant_wizard',
             'path': url_for('grant_wizard.index') + 'grant_wizard',
-            'when': None
+            'when': 'server'
         })
         scripts.append({
             'name': 'pgadmin.browser.wizard',
             'path': url_for('browser.static', filename='js/wizard'),
-            'when': None
+            'when': 'server'
         })
         return scripts
 
@@ -150,7 +150,6 @@ def script():
         status=200,
         mimetype="application/javascript")
 
-
 @blueprint.route(
     '/acl/<int:gid>/<int:sid>/<int:did>/', methods=('GET', 'POST'))
 @login_required
diff --git a/web/pgadmin/tools/import_export/__init__.py b/web/pgadmin/tools/import_export/__init__.py
index 4c1ac04..4bbfde8 100644
--- a/web/pgadmin/tools/import_export/__init__.py
+++ b/web/pgadmin/tools/import_export/__init__.py
@@ -48,7 +48,7 @@ class ImportExportModule(PgAdminModule):
             scripts.append({
                 'name': name,
                 'path': url_for('import_export.index') + script,
-                'when': None
+                'when': 'database'
             })
 
         return scripts
diff --git a/web/pgadmin/tools/maintenance/__init__.py b/web/pgadmin/tools/maintenance/__init__.py
index c12906e..a4586d4 100644
--- a/web/pgadmin/tools/maintenance/__init__.py
+++ b/web/pgadmin/tools/maintenance/__init__.py
@@ -50,7 +50,7 @@ class MaintenanceModule(PgAdminModule):
             scripts.append({
                 'name': name,
                 'path': url_for('maintenance.index') + script,
-                'when': None
+                'when': 'database'
             })
 
         return scripts
diff --git a/web/pgadmin/tools/restore/__init__.py b/web/pgadmin/tools/restore/__init__.py
index b6bf564..12d6777 100644
--- a/web/pgadmin/tools/restore/__init__.py
+++ b/web/pgadmin/tools/restore/__init__.py
@@ -48,7 +48,7 @@ class RestoreModule(PgAdminModule):
         return [{
             'name': 'pgadmin.tools.restore',
             'path': url_for('restore.index') + 'restore',
-            'when': None
+            'when': 'database'
         }]
 
 
diff --git a/web/pgadmin/tools/sqleditor/__init__.py b/web/pgadmin/tools/sqleditor/__init__.py
index 828cb99..f5a8937 100644
--- a/web/pgadmin/tools/sqleditor/__init__.py
+++ b/web/pgadmin/tools/sqleditor/__init__.py
@@ -67,7 +67,7 @@ class SqlEditorModule(PgAdminModule):
         return [{
             'name': 'pgadmin.sqleditor',
             'path': url_for('sqleditor.index') + "sqleditor",
-            'when': None
+            'when': 'server'
         }]
 
     def get_panels(self):
diff --git a/web/pgadmin/tools/user_management/templates/user_management/js/user_management.js b/web/pgadmin/tools/user_management/templates/user_management/js/user_management.js
index c8c91c7..251a6c8 100644
--- a/web/pgadmin/tools/user_management/templates/user_management/js/user_management.js
+++ b/web/pgadmin/tools/user_management/templates/user_management/js/user_management.js
@@ -1,7 +1,7 @@
 define([
       'jquery', 'underscore', 'underscore.string', 'alertify',
       'pgadmin.browser', 'backbone', 'backgrid', 'backform', 'pgadmin.browser.node',
-      'backgrid.select.all', 'backgrid.filter'
+      'backgrid.filter'
       ],
 
   // This defines Backup dialog


^ permalink  raw  reply  [nested|flat] 13+ messages in thread

* [pgAdmin4][Patch]: Load module's JS files only when required
@ 2017-05-22 10:52  Dave Page <[email protected]>
  parent: Surinder Kumar <[email protected]>
  0 siblings, 1 reply; 13+ messages in thread

From: Dave Page @ 2017-05-22 10:52 UTC (permalink / raw)
  To: Surinder Kumar <[email protected]>; +Cc: pgadmin-hackers

Hi

On Monday, May 22, 2017, Surinder Kumar <[email protected]
<javascript:_e(%7B%7D,'cvml','[email protected]');>> wrote:

> Hi
>
> As per pgAdmin4 design, template JS files can either be preloaded or load
> when a specific node expands (by adding for e.g.: when: 'server').
>
> The JS files of several modules found to be loaded when pgAdmin4 loads
> which results in increasing:
>
>    - the number of http requests
>    - latency(greater request time)
>    - pgAdmin4 load time
>
> *Tested on Firefox:*
>
> Before applying patch
>
>    - http requests - 143
>    - Content size - 3.4 MB
>    - Load time: 4.1s (onload: 524ms)
>
> After applying patch
>
>    - http requests: 68
>    - Content size: 2.1 MB
>    - Load time: 2.84s (onload: 481ms)
>
> This is great work!

However (sorry!) - I'm planning on working on an alternative change on my
flight in a couple of hours. Joao has broken the Grunt code out of the
History tab patch for me to work with - the idea is something like:

- We continue to migrate all the JS out of templates and into static files
whereever possible, using the client-side translation.

- We then have a set of Grunt tasks that will collect all the static JS,
minimise it, and pack it into a single file to load at startup.

I'm currently thinking that non-debug/package builds will pre-pack
everything for installation. The aim is to have JS HTTP requests be down in
single figures to maximise loading time.

The are various issues to work through however; at least, how do we handle
debug builds, and how do we re-pack everything if a user installs a new
module (or updates something).

We'd also need to get rid of requirejs.



>
> Also, I found the http request for gravtar takes much time(depending on
> internet speed) to load which increases load time.
> https://secure.gravatar.com/avatar/d30aea269994f01256a99a8e7
> 154a328?s=100&d=retro&r=g
>
> Shouldn't the gravatar image be replaced with custom image ? I don't see
> its any use except displaying for user.
>

Maybe. Doesn't it load asynchronously though?


>
> *Patch changes:*
>
> 1) Load following modules JS when 'servers' node expands:
>
>    -  Roles
>    -  FileManager
>    -  Backup
>    -  Datagrid
>    -  Grant wizard
>    -  Import/Export, Maintenance & restore
>    -  Sqleditor
>
> 2) Load Debugger JS when database node expands
>
> 3) Load Flotr2 when render function is called in dashboard.js
>
> 4) Load BigNumber library when sorting is performed on Statistics tab in
> backgrid.pgadmin.js
>
> 5) Remove 'backgrid.select.all' from dependency list(user_management.js)
> as it had no use.
>
> After applying this patch, Menu items such "Query tool", "Grant wizard"
> don't appear in Tools menu.
> I have logged an RM2424 <https://redmine.postgresql.org/issues/2424; to
> track this.
>

OK. Lets hold fire on this for now though, until I can PoC the work above.

Of course, any thoughts or comments are welcome.


-- 
Dave Page
Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake

EnterpriseDB UK: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


^ permalink  raw  reply  [nested|flat] 13+ messages in thread

* Re: [pgAdmin4][Patch]: Load module's JS files only when required
@ 2017-05-22 12:39  Surinder Kumar <[email protected]>
  parent: Dave Page <[email protected]>
  0 siblings, 1 reply; 13+ messages in thread

From: Surinder Kumar @ 2017-05-22 12:39 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: pgadmin-hackers

Hi

On Mon, May 22, 2017 at 4:22 PM, Dave Page <[email protected]> wrote:

> Hi
>
> On Monday, May 22, 2017, Surinder Kumar <[email protected]>
> wrote:
>
>> Hi
>>
>> As per pgAdmin4 design, template JS files can either be preloaded or load
>> when a specific node expands (by adding for e.g.: when: 'server').
>>
>> The JS files of several modules found to be loaded when pgAdmin4 loads
>> which results in increasing:
>>
>>    - the number of http requests
>>    - latency(greater request time)
>>    - pgAdmin4 load time
>>
>> *Tested on Firefox:*
>>
>> Before applying patch
>>
>>    - http requests - 143
>>    - Content size - 3.4 MB
>>    - Load time: 4.1s (onload: 524ms)
>>
>> After applying patch
>>
>>    - http requests: 68
>>    - Content size: 2.1 MB
>>    - Load time: 2.84s (onload: 481ms)
>>
>> This is great work!
>
> However (sorry!) - I'm planning on working on an alternative change on my
> flight in a couple of hours. Joao has broken the Grunt code out of the
> History tab patch for me to work with - the idea is something like:
>
> - We continue to migrate all the JS out of templates and into static files
> whereever possible, using the client-side translation.
>
​Yes. It will be then easier to cover most of the JS code for minify if
client side ​translation is used.

>
> - We then have a set of Grunt tasks that will collect all the static JS,
> minimise it, and pack it into a single file to load at startup.
>
​I wrote few grunt tasks using r.js optimizer this weekend which:

1. Finds all static JS file recursively into the modules using regex
pattern and then creates the tasks to minify each JS file and store its
'min.js' in same directory and loads min.js when current_app.debug is False
else returns JS file.

2. A task to merge given list of CSS files into a single file and then
minify using 'grunt-contrib-cssmin' task and then insert that file with
<script> tags in base.html file.

>
> I'm currently thinking that non-debug/package builds will pre-pack
> everything for installation. The aim is to have JS HTTP requests be down in
> single figures to maximise loading time.
>
​That will make pgAdmin4 much faster.

>
> The are various issues to work through however; at least, how do we handle
> debug builds, and how do we re-pack everything if a user installs a new
> module (or updates something).
>
​I don't know much about builds but the debug/package builds can be
switched using 'current_app.debug' config parameter.
Using Regex Pattern will help to search JS files throughout the App
directory to perform minify task.

>
> We'd also need to get rid of requirejs.
>
​Any alternative to requirejs ?​

>
>
>
>>
>> Also, I found the http request for gravtar takes much time(depending on
>> internet speed) to load which increases load time.
>> https://secure.gravatar.com/avatar/d30aea269994f01256a99a8e7
>> 154a328?s=100&d=retro&r=g
>>
>> Shouldn't the gravatar image be replaced with custom image ? I don't see
>> its any use except displaying for user.
>>
>
> Maybe. Doesn't it load asynchronously though?
>

>
>>
>> *Patch changes:*
>>
>> 1) Load following modules JS when 'servers' node expands:
>>
>>    -  Roles
>>    -  FileManager
>>    -  Backup
>>    -  Datagrid
>>    -  Grant wizard
>>    -  Import/Export, Maintenance & restore
>>    -  Sqleditor
>>
>> 2) Load Debugger JS when database node expands
>>
>> 3) Load Flotr2 when render function is called in dashboard.js
>>
>> 4) Load BigNumber library when sorting is performed on Statistics tab in
>> backgrid.pgadmin.js
>>
>> 5) Remove 'backgrid.select.all' from dependency list(user_management.js)
>> as it had no use.
>>
>> After applying this patch, Menu items such "Query tool", "Grant wizard"
>> don't appear in Tools menu.
>> I have logged an RM2424 <https://redmine.postgresql.org/issues/2424; to
>> track this.
>>
>
> OK. Lets hold fire on this for now though, until I can PoC the work above.
>
> Of course, any thoughts or comments are welcome.
>
>
> --
> Dave Page
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>
> EnterpriseDB UK: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
>


^ permalink  raw  reply  [nested|flat] 13+ messages in thread

* Re: [pgAdmin4][Patch]: Load module's JS files only when required
@ 2017-05-22 21:33  Dave Page <[email protected]>
  parent: Surinder Kumar <[email protected]>
  0 siblings, 1 reply; 13+ messages in thread

From: Dave Page @ 2017-05-22 21:33 UTC (permalink / raw)
  To: Surinder Kumar <[email protected]>; +Cc: pgadmin-hackers

Hi

On Monday, May 22, 2017, Surinder Kumar <[email protected]>
wrote:

> Hi
>
> On Mon, May 22, 2017 at 4:22 PM, Dave Page <[email protected]
> <javascript:_e(%7B%7D,'cvml','[email protected]');>> wrote:
>
>> Hi
>>
>> On Monday, May 22, 2017, Surinder Kumar <[email protected]>
>> wrote:
>>
>>> Hi
>>>
>>> As per pgAdmin4 design, template JS files can either be preloaded or
>>> load when a specific node expands (by adding for e.g.: when: 'server').
>>>
>>> The JS files of several modules found to be loaded when pgAdmin4 loads
>>> which results in increasing:
>>>
>>>    - the number of http requests
>>>    - latency(greater request time)
>>>    - pgAdmin4 load time
>>>
>>> *Tested on Firefox:*
>>>
>>> Before applying patch
>>>
>>>    - http requests - 143
>>>    - Content size - 3.4 MB
>>>    - Load time: 4.1s (onload: 524ms)
>>>
>>> After applying patch
>>>
>>>    - http requests: 68
>>>    - Content size: 2.1 MB
>>>    - Load time: 2.84s (onload: 481ms)
>>>
>>> This is great work!
>>
>> However (sorry!) - I'm planning on working on an alternative change on my
>> flight in a couple of hours. Joao has broken the Grunt code out of the
>> History tab patch for me to work with - the idea is something like:
>>
>> - We continue to migrate all the JS out of templates and into static
>> files whereever possible, using the client-side translation.
>>
> ​Yes. It will be then easier to cover most of the JS code for minify if
> client side ​translation is used.
>

Unfortunately, I looked at this on my flight and it looks like it'll be a
mammoth task. Many/most JS files also currently use the url_for template
function - so we need to figure out how to replace that with JS code first.


>
>> - We then have a set of Grunt tasks that will collect all the static JS,
>> minimise it, and pack it into a single file to load at startup.
>>
> ​I wrote few grunt tasks using r.js optimizer this weekend which:
>
> 1. Finds all static JS file recursively into the modules using regex
> pattern and then creates the tasks to minify each JS file and store its
> 'min.js' in same directory and loads min.js when current_app.debug is False
> else returns JS file.
>

> 2. A task to merge given list of CSS files into a single file and then
> minify using 'grunt-contrib-cssmin' task and then insert that file with
> <script> tags in base.html file.
>

There's a script in the tools directory to do something similar already.

I am already starting to wonder if Grunt is the best way to do this though.
It might be easier (though not quite as efficient) to have the Python
module all return their static/template JS code at initialisation,
effectively dynamically building a single packed file containing nearly
everything.


>
>> I'm currently thinking that non-debug/package builds will pre-pack
>> everything for installation. The aim is to have JS HTTP requests be down in
>> single figures to maximise loading time.
>>
> ​That will make pgAdmin4 much faster.
>
>>
>> The are various issues to work through however; at least, how do we
>> handle debug builds, and how do we re-pack everything if a user installs a
>> new module (or updates something).
>>
> ​I don't know much about builds but the debug/package builds can be
> switched using 'current_app.debug' config parameter.
> Using Regex Pattern will help to search JS files throughout the App
> directory to perform minify task.
>

Yeah, though I think there are more considerations we haven't yet thought
of.


>
>> We'd also need to get rid of requirejs.
>>
> ​Any alternative to requirejs ?​
>

If everything is packed together, then we don't need anything like it.

I think this needs more discussion.


>
>>
>>
>>>
>>> Also, I found the http request for gravtar takes much time(depending on
>>> internet speed) to load which increases load time.
>>> https://secure.gravatar.com/avatar/d30aea269994f01256a99a8e7
>>> 154a328?s=100&d=retro&r=g
>>>
>>> Shouldn't the gravatar image be replaced with custom image ? I don't see
>>> its any use except displaying for user.
>>>
>>
>> Maybe. Doesn't it load asynchronously though?
>>
>
>>
>>>
>>> *Patch changes:*
>>>
>>> 1) Load following modules JS when 'servers' node expands:
>>>
>>>    -  Roles
>>>    -  FileManager
>>>    -  Backup
>>>    -  Datagrid
>>>    -  Grant wizard
>>>    -  Import/Export, Maintenance & restore
>>>    -  Sqleditor
>>>
>>> 2) Load Debugger JS when database node expands
>>>
>>> 3) Load Flotr2 when render function is called in dashboard.js
>>>
>>> 4) Load BigNumber library when sorting is performed on Statistics tab in
>>> backgrid.pgadmin.js
>>>
>>> 5) Remove 'backgrid.select.all' from dependency list(user_management.js)
>>> as it had no use.
>>>
>>> After applying this patch, Menu items such "Query tool", "Grant wizard"
>>> don't appear in Tools menu.
>>> I have logged an RM2424 <https://redmine.postgresql.org/issues/2424; to
>>> track this.
>>>
>>
>> OK. Lets hold fire on this for now though, until I can PoC the work above.
>>
>> Of course, any thoughts or comments are welcome.
>>
>>
>> --
>> Dave Page
>> Blog: http://pgsnake.blogspot.com
>> Twitter: @pgsnake
>>
>> EnterpriseDB UK: http://www.enterprisedb.com
>> The Enterprise PostgreSQL Company
>>
>>
>

-- 
Dave Page
Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake

EnterpriseDB UK: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


^ permalink  raw  reply  [nested|flat] 13+ messages in thread

* Re: [pgAdmin4][Patch]: Load module's JS files only when required
@ 2017-05-23 18:45  Joao Pedro De Almeida Pereira <[email protected]>
  parent: Dave Page <[email protected]>
  0 siblings, 1 reply; 13+ messages in thread

From: Joao Pedro De Almeida Pereira @ 2017-05-23 18:45 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: Surinder Kumar <[email protected]>; pgadmin-hackers

Hello


​I wrote few grunt tasks using r.js optimizer this weekend
>
>  How did it compare to webpack?

I am already starting to wonder if Grunt is the best way to do this though.
> It might be easier (though not quite as efficient) to have the Python
> module all return their static/template JS code at initialisation,
> effectively dynamically building a single packed file containing nearly
> everything.

We could. Are you saying that the app should bundle js every run? To be
fair, this is what we're currently doing with Grunt, but it feels like we
should change this for non-development use.

Yeah, though I think there are more considerations we haven't yet thought
> of.

Something we aren't clear on is the end-user use case of dropping modules
into existing installations. Is this achieved via installer?


George & Joao


On Mon, May 22, 2017 at 5:33 PM, Dave Page <[email protected]> wrote:

> Hi
>
> On Monday, May 22, 2017, Surinder Kumar <[email protected]>
> wrote:
>
>> Hi
>>
>> On Mon, May 22, 2017 at 4:22 PM, Dave Page <[email protected]> wrote:
>>
>>> Hi
>>>
>>> On Monday, May 22, 2017, Surinder Kumar <[email protected]>
>>> wrote:
>>>
>>>> Hi
>>>>
>>>> As per pgAdmin4 design, template JS files can either be preloaded or
>>>> load when a specific node expands (by adding for e.g.: when: 'server').
>>>>
>>>> The JS files of several modules found to be loaded when pgAdmin4 loads
>>>> which results in increasing:
>>>>
>>>>    - the number of http requests
>>>>    - latency(greater request time)
>>>>    - pgAdmin4 load time
>>>>
>>>> *Tested on Firefox:*
>>>>
>>>> Before applying patch
>>>>
>>>>    - http requests - 143
>>>>    - Content size - 3.4 MB
>>>>    - Load time: 4.1s (onload: 524ms)
>>>>
>>>> After applying patch
>>>>
>>>>    - http requests: 68
>>>>    - Content size: 2.1 MB
>>>>    - Load time: 2.84s (onload: 481ms)
>>>>
>>>> This is great work!
>>>
>>> However (sorry!) - I'm planning on working on an alternative change on
>>> my flight in a couple of hours. Joao has broken the Grunt code out of the
>>> History tab patch for me to work with - the idea is something like:
>>>
>>> - We continue to migrate all the JS out of templates and into static
>>> files whereever possible, using the client-side translation.
>>>
>> ​Yes. It will be then easier to cover most of the JS code for minify if
>> client side ​translation is used.
>>
>
> Unfortunately, I looked at this on my flight and it looks like it'll be a
> mammoth task. Many/most JS files also currently use the url_for template
> function - so we need to figure out how to replace that with JS code first.
>
>
>>
>>> - We then have a set of Grunt tasks that will collect all the static JS,
>>> minimise it, and pack it into a single file to load at startup.
>>>
>> ​I wrote few grunt tasks using r.js optimizer this weekend which:
>>
>> 1. Finds all static JS file recursively into the modules using regex
>> pattern and then creates the tasks to minify each JS file and store its
>> 'min.js' in same directory and loads min.js when current_app.debug is False
>> else returns JS file.
>>
>
>> 2. A task to merge given list of CSS files into a single file and then
>> minify using 'grunt-contrib-cssmin' task and then insert that file with
>> <script> tags in base.html file.
>>
>
> There's a script in the tools directory to do something similar already.
>
> I am already starting to wonder if Grunt is the best way to do this
> though. It might be easier (though not quite as efficient) to have the
> Python module all return their static/template JS code at initialisation,
> effectively dynamically building a single packed file containing nearly
> everything.
>
>
>>
>>> I'm currently thinking that non-debug/package builds will pre-pack
>>> everything for installation. The aim is to have JS HTTP requests be down in
>>> single figures to maximise loading time.
>>>
>> ​That will make pgAdmin4 much faster.
>>
>>>
>>> The are various issues to work through however; at least, how do we
>>> handle debug builds, and how do we re-pack everything if a user installs a
>>> new module (or updates something).
>>>
>> ​I don't know much about builds but the debug/package builds can be
>> switched using 'current_app.debug' config parameter.
>> Using Regex Pattern will help to search JS files throughout the App
>> directory to perform minify task.
>>
>
> Yeah, though I think there are more considerations we haven't yet thought
> of.
>
>
>>
>>> We'd also need to get rid of requirejs.
>>>
>> ​Any alternative to requirejs ?​
>>
>
> If everything is packed together, then we don't need anything like it.
>
> I think this needs more discussion.
>
>
>>
>>>
>>>
>>>>
>>>> Also, I found the http request for gravtar takes much time(depending on
>>>> internet speed) to load which increases load time.
>>>> https://secure.gravatar.com/avatar/d30aea269994f01256a99a8e7
>>>> 154a328?s=100&d=retro&r=g
>>>>
>>>> Shouldn't the gravatar image be replaced with custom image ? I don't
>>>> see its any use except displaying for user.
>>>>
>>>
>>> Maybe. Doesn't it load asynchronously though?
>>>
>>
>>>
>>>>
>>>> *Patch changes:*
>>>>
>>>> 1) Load following modules JS when 'servers' node expands:
>>>>
>>>>    -  Roles
>>>>    -  FileManager
>>>>    -  Backup
>>>>    -  Datagrid
>>>>    -  Grant wizard
>>>>    -  Import/Export, Maintenance & restore
>>>>    -  Sqleditor
>>>>
>>>> 2) Load Debugger JS when database node expands
>>>>
>>>> 3) Load Flotr2 when render function is called in dashboard.js
>>>>
>>>> 4) Load BigNumber library when sorting is performed on Statistics tab
>>>> in backgrid.pgadmin.js
>>>>
>>>> 5) Remove 'backgrid.select.all' from dependency
>>>> list(user_management.js) as it had no use.
>>>>
>>>> After applying this patch, Menu items such "Query tool", "Grant wizard"
>>>> don't appear in Tools menu.
>>>> I have logged an RM2424 <https://redmine.postgresql.org/issues/2424;
>>>> to track this.
>>>>
>>>
>>> OK. Lets hold fire on this for now though, until I can PoC the work
>>> above.
>>>
>>> Of course, any thoughts or comments are welcome.
>>>
>>>
>>> --
>>> Dave Page
>>> Blog: http://pgsnake.blogspot.com
>>> Twitter: @pgsnake
>>>
>>> EnterpriseDB UK: http://www.enterprisedb.com
>>> The Enterprise PostgreSQL Company
>>>
>>>
>>
>
> --
> Dave Page
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>
> EnterpriseDB UK: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
>


^ permalink  raw  reply  [nested|flat] 13+ messages in thread

* Re: [pgAdmin4][Patch]: Load module's JS files only when required
@ 2017-05-23 20:21  Dave Page <[email protected]>
  parent: Joao Pedro De Almeida Pereira <[email protected]>
  0 siblings, 1 reply; 13+ messages in thread

From: Dave Page @ 2017-05-23 20:21 UTC (permalink / raw)
  To: Joao Pedro De Almeida Pereira <[email protected]>; +Cc: Surinder Kumar <[email protected]>; pgadmin-hackers

Hi

On Tue, May 23, 2017 at 2:45 PM, Joao Pedro De Almeida Pereira
<[email protected]> wrote:
> Hello
>
>
>>> I wrote few grunt tasks using r.js optimizer this weekend
>
>  How did it compare to webpack?
>
>> I am already starting to wonder if Grunt is the best way to do this
>> though. It might be easier (though not quite as efficient) to have the
>> Python module all return their static/template JS code at initialisation,
>> effectively dynamically building a single packed file containing nearly
>> everything.
>
> We could. Are you saying that the app should bundle js every run? To be
> fair, this is what we're currently doing with Grunt, but it feels like we
> should change this for non-development use.

For every non-debug run, it should check for changes in files, perhaps
by comparing the mtime of the packed file against all of the files it
would contain. However, that begs the question of what happens in an
installed instance, where the user running it likely doesn't have
permissions to re-pack the files if they're in the installation
directory. Perhaps packing should be done into a temp directory for
each user?

For debug runs, it should use the unpacked files in each module.

>> Yeah, though I think there are more considerations we haven't yet thought
>> of.
>
> Something we aren't clear on is the end-user use case of dropping modules
> into existing installations. Is this achieved via installer?

That's the intention, yes. It could be that the installer would
re-pack everything by calling a script we can supply, or the mechanism
I suggested above could handle it on next launch.

I'm actually thinking that maybe it would be easier to start with the
CSS files....

-- 
Dave Page
Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake

EnterpriseDB UK: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers



^ permalink  raw  reply  [nested|flat] 13+ messages in thread

* Re: [pgAdmin4][Patch]: Load module's JS files only when required
@ 2017-05-25 21:32  Dave Page <[email protected]>
  parent: Dave Page <[email protected]>
  0 siblings, 1 reply; 13+ messages in thread

From: Dave Page @ 2017-05-25 21:32 UTC (permalink / raw)
  To: Joao Pedro De Almeida Pereira <[email protected]>; +Cc: Surinder Kumar <[email protected]>; pgadmin-hackers

On Tue, May 23, 2017 at 4:21 PM, Dave Page <[email protected]> wrote:
>
> I'm actually thinking that maybe it would be easier to start with the
> CSS files....

Which i did yesterday. However, it soon became obvious that that isn't
so easy either, as the CSS files contain url references which need to
be adjusted, which isn't trivial.

However, I did find a flask-webpack module, which looks interesting:

https://github.com/nickjj/flask-webpack
https://nickjanetakis.com/blog/manage-your-assets-with-flask-webpack

Surinder; when you have some free time, could you look into a simple
PoC with the CSS files using that please?

-- 
Dave Page
Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake

EnterpriseDB UK: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers



^ permalink  raw  reply  [nested|flat] 13+ messages in thread

* Re: [pgAdmin4][Patch]: Load module's JS files only when required
@ 2017-05-26 04:01  Surinder Kumar <[email protected]>
  parent: Dave Page <[email protected]>
  0 siblings, 1 reply; 13+ messages in thread

From: Surinder Kumar @ 2017-05-26 04:01 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: Joao Pedro De Almeida Pereira <[email protected]>; pgadmin-hackers

On Fri, May 26, 2017 at 3:02 AM, Dave Page <[email protected]> wrote:

> On Tue, May 23, 2017 at 4:21 PM, Dave Page <[email protected]> wrote:
> >
> > I'm actually thinking that maybe it would be easier to start with the
> > CSS files....
>
> Which i did yesterday. However, it soon became obvious that that isn't
> so easy either, as the CSS files contain url references which need to
> be adjusted, which isn't trivial.
>
> However, I did find a flask-webpack module, which looks interesting:
>
> https://github.com/nickjj/flask-webpack
> https://nickjanetakis.com/blog/manage-your-assets-with-flask-webpack
>
> Surinder; when you have some free time, could you look into a simple
> PoC with the CSS files using that please?
>
​Ok. I will look

>
> --
> Dave Page
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>
> EnterpriseDB UK: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>


^ permalink  raw  reply  [nested|flat] 13+ messages in thread

* Re: [pgAdmin4][Patch]: Load module's JS files only when required
@ 2017-05-29 00:15  Dave Page <[email protected]>
  parent: Surinder Kumar <[email protected]>
  0 siblings, 1 reply; 13+ messages in thread

From: Dave Page @ 2017-05-29 00:15 UTC (permalink / raw)
  To: Surinder Kumar <[email protected]>; +Cc: Joao Pedro De Almeida Pereira <[email protected]>; pgadmin-hackers

On Fri, May 26, 2017 at 12:01 AM, Surinder Kumar
<[email protected]> wrote:
> On Fri, May 26, 2017 at 3:02 AM, Dave Page <[email protected]> wrote:
>>
>> On Tue, May 23, 2017 at 4:21 PM, Dave Page <[email protected]> wrote:
>> >
>> > I'm actually thinking that maybe it would be easier to start with the
>> > CSS files....
>>
>> Which i did yesterday. However, it soon became obvious that that isn't
>> so easy either, as the CSS files contain url references which need to
>> be adjusted, which isn't trivial.
>>
>> However, I did find a flask-webpack module, which looks interesting:
>>
>> https://github.com/nickjj/flask-webpack
>> https://nickjanetakis.com/blog/manage-your-assets-with-flask-webpack
>>
>> Surinder; when you have some free time, could you look into a simple
>> PoC with the CSS files using that please?
>
> Ok. I will look

BTW; if it looks like it will take a while to implement (as I
suspect), we should consider polishing off your initial patch as an
interim step. Any thoughts on how long RM2424 would take to resolve?


-- 
Dave Page
Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake

EnterpriseDB UK: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers



^ permalink  raw  reply  [nested|flat] 13+ messages in thread

* Re: [pgAdmin4][Patch]: Load module's JS files only when required
@ 2017-06-05 09:22  Surinder Kumar <[email protected]>
  parent: Dave Page <[email protected]>
  0 siblings, 1 reply; 13+ messages in thread

From: Surinder Kumar @ 2017-06-05 09:22 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: Joao Pedro De Almeida Pereira <[email protected]>; pgadmin-hackers

Hi Dave,

Please find attached patch for minifying CSS files and optimize images
using Webpack.

*Steps to run:*

1) After applying patch, go to web directory and run npm install on
terminal to install packages which are used to parse/minify CSS files.

2) Run npm run build which creates dist folder inside web/pgadmin/static/
directory to store processed images, fonts and css files.

3. Set DEBUG = False in config_local.py and then run python pgAdmin.py to
start server.
I kept generated main.css and overrides.css conditional in base.html to
load them only when debug mode is False


After running "npm run build", following files/directories are generated:

1) main.css -  about 20 vendor CSS files are packed into this file and more
importantly the paths to images are preserved.

2) overrides.css - it contains bootstrap.overrides.css and pgadmin.css,
they has to be packed separately and loaded after all CSS files are loaded
because the purpose of these files is to override the vendor or modules css.

3) img - it contains the images used in CSS files. The name of image files
can also be hashed names for caching purpose which we can use.

4) fonts - it contains the fonts used in fontawesome.css and other css
files.

This is a simple patch to demonstrate how CSS files will be minified with
Webpack.

For now it minifies only vendor CSS files, I will add modules static files
in the list later on.

Any thoughts on minifying template CSS files which are built dynamically
and loaded with dependency on other modules?

Also, I looked into Flask-webpack which generates bundled assets using
Webpack(webpack.config.js) and provide additionally global template tags to
use in Jinja templates.

But it might not work with latest version of Webpack as this repo is not
updated since last 2 years. I need to check with latest version and I will
update on this.


Thanks
Surinder


On Mon, May 29, 2017 at 5:45 AM, Dave Page <[email protected]> wrote:

> On Fri, May 26, 2017 at 12:01 AM, Surinder Kumar
> <[email protected]> wrote:
> > On Fri, May 26, 2017 at 3:02 AM, Dave Page <[email protected]> wrote:
> >>
> >> On Tue, May 23, 2017 at 4:21 PM, Dave Page <[email protected]> wrote:
> >> >
> >> > I'm actually thinking that maybe it would be easier to start with the
> >> > CSS files....
> >>
> >> Which i did yesterday. However, it soon became obvious that that isn't
> >> so easy either, as the CSS files contain url references which need to
> >> be adjusted, which isn't trivial.
> >>
> >> However, I did find a flask-webpack module, which looks interesting:
> >>
> >> https://github.com/nickjj/flask-webpack
> >> https://nickjanetakis.com/blog/manage-your-assets-with-flask-webpack
> >>
> >> Surinder; when you have some free time, could you look into a simple
> >> PoC with the CSS files using that please?
> >
> > Ok. I will look
>
> BTW; if it looks like it will take a while to implement (as I
> suspect), we should consider polishing off your initial patch as an
> interim step. Any thoughts on how long RM2424 would take to resolve?
>
>
> --
> Dave Page
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>
> EnterpriseDB UK: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers


Attachments:

  [application/octet-stream] bundle_css_using_webpack.patch (5.9K, 3-bundle_css_using_webpack.patch)
  download | inline diff:
diff --git a/web/package.json b/web/package.json
index 80e4e5a..6b79154 100644
--- a/web/package.json
+++ b/web/package.json
@@ -1,10 +1,24 @@
 {
+  "dependencies": {
+    "webpack": "^2.6.1"
+  },
   "devDependencies": {
     "jasmine-core": "^2.5.2",
     "karma": "^1.5.0",
     "karma-jasmine": "^1.1.0",
     "karma-phantomjs-launcher": "^1.0.2",
     "karma-requirejs": "^1.1.0",
-    "requirejs": "^2.3.3"
+    "requirejs": "^2.3.3",
+    "grunt": "^1.0.1",
+    "css-loader": "^0.28.3",
+    "style-loader": "^0.18.1",
+    "extract-text-webpack-plugin": "^2.1.0",
+    "file-loader": "^0.11.1",
+    "image-webpack-loader": "^3.3.1",
+    "optimize-css-assets-webpack-plugin": "^1.3.2",
+    "clean-webpack-plugin": "^0.1.16"
+  },
+  "scripts": {
+    "build": "webpack --hide-modules"
   }
 }
diff --git a/web/pgadmin/templates/base.html b/web/pgadmin/templates/base.html
index 375b39d..3789b1a 100755
--- a/web/pgadmin/templates/base.html
+++ b/web/pgadmin/templates/base.html
@@ -18,6 +18,7 @@
     <!-- To set pgAdmin4 shortcut icon in browser -->
     <link rel="shortcut icon" href="{{ url_for('redirects.favicon') }}"/>
 
+    {% if config.DEBUG %}
     <!-- Base template stylesheets -->
     <link type="text/css" rel="stylesheet"
           href="{{ url_for('static', filename='vendor/bootstrap/css/bootstrap.css' if config.DEBUG else 'vendor/bootstrap/css/bootstrap.min.css')}}"/>
@@ -54,13 +55,20 @@
     <link type="text/css" rel="stylesheet"
           href="{{ url_for('static', filename='vendor/codemirror/addon/scroll/simplescrollbars.css')}}"/>
 
+    {% else %}
+        <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='dist/main.css')}}"/>
+    {% endif %}
     <!-- View specified stylesheets -->
     {% for stylesheet in current_app.stylesheets %}
     <link type="text/css" rel="stylesheet" href="{{ stylesheet }}">
     {% endfor %}
 
+    {% if config.DEBUG %}
     <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.overrides.css') }}"/>
     <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/pgadmin.css') }}"/>
+    {% else %}
+        <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='dist/overrides.css')}}"/>
+    {% endif %}
     {% block css_link %}{% endblock %}
 
     <!-- Base template scripts -->
diff --git a/web/webpack.config.js b/web/webpack.config.js
new file mode 100644
index 0000000..01b1365
--- /dev/null
+++ b/web/webpack.config.js
@@ -0,0 +1,111 @@
+const path = require('path'),
+   grunt = require('grunt'),
+   cleanWebpackPlugin = require('clean-webpack-plugin'),
+   ExtractTextPlugin = require('extract-text-webpack-plugin'),
+   OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
+
+const baseDir = './pgadmin/static/',
+  vendorDir = baseDir + 'vendor/';
+
+let cssResources = [],
+  excludes = [
+      'merge.css', 'dropzone.css', 'slick.headerbuttons.css',
+      'slick.headermenu.css', 'semantic.css', 'default.css',
+      'dialog.css', 'fullscreen.css', 'foldgutter.css',
+      'show-hint.css', 'lint.css', 'merge.css', 'matchesonscrollbar.css',
+      'tern.css', 'slick.columnpicker.css', 'slick.pager.css',
+      'bootstrap-datetimepicker.min.css', 'bootstrap-theme.css'
+  ];
+
+// Path(s) that should be cleaned
+let pathsToClean = ['dist'];
+
+// Clean options to use
+let cleanOptions = {
+  root: path.resolve(__dirname, './pgadmin/static/'),
+  verbose: true,
+  dry: false
+};
+
+// extract vendor css files in cssResources
+grunt.file.expand({ cwd: vendorDir }, "**/*.css").forEach(function(page) {
+    file_name = path.basename(page).replace('.min', '').replace('.rtl', '');
+    if (excludes.indexOf(file_name) === -1) {
+      excludes.push(file_name);
+      cssResources.push((vendorDir +  page));
+    }
+});
+
+// Add css files explicitly
+cssResources.push(vendorDir + 'bootstrap/css/bootstrap.min.css');
+cssResources.push(vendorDir + 'bootstrap/css/bootstrap-theme.min.css');
+cssResources.push('./pgadmin/browser/static/vendor/aciTree/css/aciTree.css');
+
+// Main webpack configurations starts here
+const config = {
+  // Create two files main.css and overrides.css
+  entry: {
+    main: cssResources,
+    overrides: [
+      baseDir + 'css/bootstrap.overrides.css',
+      baseDir + 'css/pgadmin.css',
+    ]
+  },
+  output: {
+    path: path.resolve(__dirname, './pgadmin/static/dist/'), // path to dist directory
+    filename: '[name].css' // output js file name is identical to css file name
+  },
+  module: {
+    rules: [
+      {
+        test: /\.css$/,
+        use: ExtractTextPlugin.extract({
+          fallback: 'style-loader',
+          use: 'css-loader'
+        }),
+        exclude: /node_modules/
+      },
+      {
+        test: /\.(jpe?g|png|gif|svg)$/i,
+        loaders: [
+            'file-loader?hash=sha512&digest=hex&name=img/[name].[ext]', {
+            loader: 'image-webpack-loader',
+            query: {
+              bypassOnDebug: true,
+              mozjpeg: {
+                progressive: true,
+              },
+              gifsicle: {
+                interlaced: false,
+              },
+              optipng: {
+                optimizationLevel: 7,
+              },
+              pngquant: {
+                quality: '75-90',
+                speed: 3
+              },
+            }
+          }
+        ],
+        exclude: /node_modules/
+     },
+     {
+        test: /\.(eot|svg|ttf|woff|woff2)$/,
+        loader: 'file-loader?name=fonts/[name].[ext]',
+        exclude: /node_modules/
+     }
+    ]
+  },
+  plugins: [
+    new cleanWebpackPlugin(pathsToClean, cleanOptions), // clean dist directory
+    new ExtractTextPlugin('[name].css'),
+    new OptimizeCssAssetsPlugin({
+      assetNameRegExp: /\.css$/g,
+      cssProcessor: require('cssnano'),
+      cssProcessorOptions: { discardComments: {removeAll: true } },
+      canPrint: true
+    })
+  ]
+};
+module.exports = config;


^ permalink  raw  reply  [nested|flat] 13+ messages in thread

* Re: [pgAdmin4][Patch]: Load module's JS files only when required
@ 2017-06-06 13:39  Dave Page <[email protected]>
  parent: Surinder Kumar <[email protected]>
  0 siblings, 1 reply; 13+ messages in thread

From: Dave Page @ 2017-06-06 13:39 UTC (permalink / raw)
  To: Surinder Kumar <[email protected]>; +Cc: Joao Pedro De Almeida Pereira <[email protected]>; pgadmin-hackers

Hi

On Mon, Jun 5, 2017 at 10:22 AM, Surinder Kumar
<[email protected]> wrote:
> Hi Dave,
>
> Please find attached patch for minifying CSS files and optimize images using
> Webpack.
>
> Steps to run:
>
> 1) After applying patch, go to web directory and run npm install on terminal
> to install packages which are used to parse/minify CSS files.
>
> 2) Run npm run build which creates dist folder inside web/pgadmin/static/
> directory to store processed images, fonts and css files.
>
> 3. Set DEBUG = False in config_local.py and then run python pgAdmin.py to
> start server.
> I kept generated main.css and overrides.css conditional in base.html to load
> them only when debug mode is False
>
>
> After running "npm run build", following files/directories are generated:
>
> 1) main.css -  about 20 vendor CSS files are packed into this file and more
> importantly the paths to images are preserved.
>
> 2) overrides.css - it contains bootstrap.overrides.css and pgadmin.css, they
> has to be packed separately and loaded after all CSS files are loaded
> because the purpose of these files is to override the vendor or modules css.
>
> 3) img - it contains the images used in CSS files. The name of image files
> can also be hashed names for caching purpose which we can use.
>
> 4) fonts - it contains the fonts used in fontawesome.css and other css
> files.
>
> This is a simple patch to demonstrate how CSS files will be minified with
> Webpack.

I think this is a good, simple method. It handles debug v.s release,
and of course, any plugin modules can include their own images/CSS
without even having to worry about webpacking if installed later.

> For now it minifies only vendor CSS files, I will add modules static files
> in the list later on.

I think we need to do that to get a better idea of the benefits. We
also need to get some of the JS code in there as well (Ashesh should
be able to help with that - he told me he's de-templatised a lot of
that now).

> Any thoughts on minifying template CSS files which are built dynamically and
> loaded with dependency on other modules?

Let's look at why they are templates. Is that required, or could they
be made static?

> Also, I looked into Flask-webpack which generates bundled assets using
> Webpack(webpack.config.js) and provide additionally global template tags to
> use in Jinja templates.
>
> But it might not work with latest version of Webpack as this repo is not
> updated since last 2 years. I need to check with latest version and I will
> update on this.

Given how straightforward this seems to be, I'm not sure it's needed.

Joao, any comments?

Nice work - thanks!

-- 
Dave Page
Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake

EnterpriseDB UK: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers



^ permalink  raw  reply  [nested|flat] 13+ messages in thread

* Re: [pgAdmin4][Patch]: Load module's JS files only when required
@ 2017-06-07 18:10  Joao Pedro De Almeida Pereira <[email protected]>
  parent: Dave Page <[email protected]>
  0 siblings, 1 reply; 13+ messages in thread

From: Joao Pedro De Almeida Pereira @ 2017-06-07 18:10 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: Surinder Kumar <[email protected]>; pgadmin-hackers

Hello Dave,
By the description on the email, it looks like the process is very similar
to the Grunt process that we were talking about, but without the patch, it
is a bit hard to get more specifics.
Can you forward the patch so we can take a look at it.

We believe that every effort done to eliminate templated Javascript and CSS
files is well worth it, and should be followed.

Thanks
Joao & Sarah

On Tue, Jun 6, 2017 at 9:39 AM, Dave Page <[email protected]> wrote:

> Hi
>
> On Mon, Jun 5, 2017 at 10:22 AM, Surinder Kumar
> <[email protected]> wrote:
> > Hi Dave,
> >
> > Please find attached patch for minifying CSS files and optimize images
> using
> > Webpack.
> >
> > Steps to run:
> >
> > 1) After applying patch, go to web directory and run npm install on
> terminal
> > to install packages which are used to parse/minify CSS files.
> >
> > 2) Run npm run build which creates dist folder inside web/pgadmin/static/
> > directory to store processed images, fonts and css files.
> >
> > 3. Set DEBUG = False in config_local.py and then run python pgAdmin.py to
> > start server.
> > I kept generated main.css and overrides.css conditional in base.html to
> load
> > them only when debug mode is False
> >
> >
> > After running "npm run build", following files/directories are generated:
> >
> > 1) main.css -  about 20 vendor CSS files are packed into this file and
> more
> > importantly the paths to images are preserved.
> >
> > 2) overrides.css - it contains bootstrap.overrides.css and pgadmin.css,
> they
> > has to be packed separately and loaded after all CSS files are loaded
> > because the purpose of these files is to override the vendor or modules
> css.
> >
> > 3) img - it contains the images used in CSS files. The name of image
> files
> > can also be hashed names for caching purpose which we can use.
> >
> > 4) fonts - it contains the fonts used in fontawesome.css and other css
> > files.
> >
> > This is a simple patch to demonstrate how CSS files will be minified with
> > Webpack.
>
> I think this is a good, simple method. It handles debug v.s release,
> and of course, any plugin modules can include their own images/CSS
> without even having to worry about webpacking if installed later.
>
> > For now it minifies only vendor CSS files, I will add modules static
> files
> > in the list later on.
>
> I think we need to do that to get a better idea of the benefits. We
> also need to get some of the JS code in there as well (Ashesh should
> be able to help with that - he told me he's de-templatised a lot of
> that now).
>
> > Any thoughts on minifying template CSS files which are built dynamically
> and
> > loaded with dependency on other modules?
>
> Let's look at why they are templates. Is that required, or could they
> be made static?
>
> > Also, I looked into Flask-webpack which generates bundled assets using
> > Webpack(webpack.config.js) and provide additionally global template tags
> to
> > use in Jinja templates.
> >
> > But it might not work with latest version of Webpack as this repo is not
> > updated since last 2 years. I need to check with latest version and I
> will
> > update on this.
>
> Given how straightforward this seems to be, I'm not sure it's needed.
>
> Joao, any comments?
>
> Nice work - thanks!
>
> --
> Dave Page
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>
> EnterpriseDB UK: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>


^ permalink  raw  reply  [nested|flat] 13+ messages in thread

* Re: [pgAdmin4][Patch]: Load module's JS files only when required
@ 2017-06-08 11:43  Dave Page <[email protected]>
  parent: Joao Pedro De Almeida Pereira <[email protected]>
  0 siblings, 0 replies; 13+ messages in thread

From: Dave Page @ 2017-06-08 11:43 UTC (permalink / raw)
  To: Joao Pedro De Almeida Pereira <[email protected]>; +Cc: Surinder Kumar <[email protected]>; pgadmin-hackers

Hi

On Wed, Jun 7, 2017 at 7:10 PM, Joao Pedro De Almeida Pereira
<[email protected]> wrote:
> Hello Dave,
> By the description on the email, it looks like the process is very similar
> to the Grunt process that we were talking about, but without the patch, it
> is a bit hard to get more specifics.
> Can you forward the patch so we can take a look at it.
>
> We believe that every effort done to eliminate templated Javascript and CSS
> files is well worth it, and should be followed.

Odd - the patch was sent to you as well. Oh well, here it is.

> On Tue, Jun 6, 2017 at 9:39 AM, Dave Page <[email protected]> wrote:
>>
>> Hi
>>
>> On Mon, Jun 5, 2017 at 10:22 AM, Surinder Kumar
>> <[email protected]> wrote:
>> > Hi Dave,
>> >
>> > Please find attached patch for minifying CSS files and optimize images
>> > using
>> > Webpack.
>> >
>> > Steps to run:
>> >
>> > 1) After applying patch, go to web directory and run npm install on
>> > terminal
>> > to install packages which are used to parse/minify CSS files.
>> >
>> > 2) Run npm run build which creates dist folder inside
>> > web/pgadmin/static/
>> > directory to store processed images, fonts and css files.
>> >
>> > 3. Set DEBUG = False in config_local.py and then run python pgAdmin.py
>> > to
>> > start server.
>> > I kept generated main.css and overrides.css conditional in base.html to
>> > load
>> > them only when debug mode is False
>> >
>> >
>> > After running "npm run build", following files/directories are
>> > generated:
>> >
>> > 1) main.css -  about 20 vendor CSS files are packed into this file and
>> > more
>> > importantly the paths to images are preserved.
>> >
>> > 2) overrides.css - it contains bootstrap.overrides.css and pgadmin.css,
>> > they
>> > has to be packed separately and loaded after all CSS files are loaded
>> > because the purpose of these files is to override the vendor or modules
>> > css.
>> >
>> > 3) img - it contains the images used in CSS files. The name of image
>> > files
>> > can also be hashed names for caching purpose which we can use.
>> >
>> > 4) fonts - it contains the fonts used in fontawesome.css and other css
>> > files.
>> >
>> > This is a simple patch to demonstrate how CSS files will be minified
>> > with
>> > Webpack.
>>
>> I think this is a good, simple method. It handles debug v.s release,
>> and of course, any plugin modules can include their own images/CSS
>> without even having to worry about webpacking if installed later.
>>
>> > For now it minifies only vendor CSS files, I will add modules static
>> > files
>> > in the list later on.
>>
>> I think we need to do that to get a better idea of the benefits. We
>> also need to get some of the JS code in there as well (Ashesh should
>> be able to help with that - he told me he's de-templatised a lot of
>> that now).
>>
>> > Any thoughts on minifying template CSS files which are built dynamically
>> > and
>> > loaded with dependency on other modules?
>>
>> Let's look at why they are templates. Is that required, or could they
>> be made static?
>>
>> > Also, I looked into Flask-webpack which generates bundled assets using
>> > Webpack(webpack.config.js) and provide additionally global template tags
>> > to
>> > use in Jinja templates.
>> >
>> > But it might not work with latest version of Webpack as this repo is not
>> > updated since last 2 years. I need to check with latest version and I
>> > will
>> > update on this.
>>
>> Given how straightforward this seems to be, I'm not sure it's needed.
>>
>> Joao, any comments?
>>
>> Nice work - thanks!
>>
>> --
>> Dave Page
>> Blog: http://pgsnake.blogspot.com
>> Twitter: @pgsnake
>>
>> EnterpriseDB UK: http://www.enterprisedb.com
>> The Enterprise PostgreSQL Company
>
>



-- 
Dave Page
Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake

EnterpriseDB UK: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers


Attachments:

  [application/octet-stream] bundle_css_using_webpack.patch (5.9K, 2-bundle_css_using_webpack.patch)
  download | inline diff:
diff --git a/web/package.json b/web/package.json
index 80e4e5a..6b79154 100644
--- a/web/package.json
+++ b/web/package.json
@@ -1,10 +1,24 @@
 {
+  "dependencies": {
+    "webpack": "^2.6.1"
+  },
   "devDependencies": {
     "jasmine-core": "^2.5.2",
     "karma": "^1.5.0",
     "karma-jasmine": "^1.1.0",
     "karma-phantomjs-launcher": "^1.0.2",
     "karma-requirejs": "^1.1.0",
-    "requirejs": "^2.3.3"
+    "requirejs": "^2.3.3",
+    "grunt": "^1.0.1",
+    "css-loader": "^0.28.3",
+    "style-loader": "^0.18.1",
+    "extract-text-webpack-plugin": "^2.1.0",
+    "file-loader": "^0.11.1",
+    "image-webpack-loader": "^3.3.1",
+    "optimize-css-assets-webpack-plugin": "^1.3.2",
+    "clean-webpack-plugin": "^0.1.16"
+  },
+  "scripts": {
+    "build": "webpack --hide-modules"
   }
 }
diff --git a/web/pgadmin/templates/base.html b/web/pgadmin/templates/base.html
index 375b39d..3789b1a 100755
--- a/web/pgadmin/templates/base.html
+++ b/web/pgadmin/templates/base.html
@@ -18,6 +18,7 @@
     <!-- To set pgAdmin4 shortcut icon in browser -->
     <link rel="shortcut icon" href="{{ url_for('redirects.favicon') }}"/>
 
+    {% if config.DEBUG %}
     <!-- Base template stylesheets -->
     <link type="text/css" rel="stylesheet"
           href="{{ url_for('static', filename='vendor/bootstrap/css/bootstrap.css' if config.DEBUG else 'vendor/bootstrap/css/bootstrap.min.css')}}"/>
@@ -54,13 +55,20 @@
     <link type="text/css" rel="stylesheet"
           href="{{ url_for('static', filename='vendor/codemirror/addon/scroll/simplescrollbars.css')}}"/>
 
+    {% else %}
+        <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='dist/main.css')}}"/>
+    {% endif %}
     <!-- View specified stylesheets -->
     {% for stylesheet in current_app.stylesheets %}
     <link type="text/css" rel="stylesheet" href="{{ stylesheet }}">
     {% endfor %}
 
+    {% if config.DEBUG %}
     <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.overrides.css') }}"/>
     <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/pgadmin.css') }}"/>
+    {% else %}
+        <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='dist/overrides.css')}}"/>
+    {% endif %}
     {% block css_link %}{% endblock %}
 
     <!-- Base template scripts -->
diff --git a/web/webpack.config.js b/web/webpack.config.js
new file mode 100644
index 0000000..01b1365
--- /dev/null
+++ b/web/webpack.config.js
@@ -0,0 +1,111 @@
+const path = require('path'),
+   grunt = require('grunt'),
+   cleanWebpackPlugin = require('clean-webpack-plugin'),
+   ExtractTextPlugin = require('extract-text-webpack-plugin'),
+   OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
+
+const baseDir = './pgadmin/static/',
+  vendorDir = baseDir + 'vendor/';
+
+let cssResources = [],
+  excludes = [
+      'merge.css', 'dropzone.css', 'slick.headerbuttons.css',
+      'slick.headermenu.css', 'semantic.css', 'default.css',
+      'dialog.css', 'fullscreen.css', 'foldgutter.css',
+      'show-hint.css', 'lint.css', 'merge.css', 'matchesonscrollbar.css',
+      'tern.css', 'slick.columnpicker.css', 'slick.pager.css',
+      'bootstrap-datetimepicker.min.css', 'bootstrap-theme.css'
+  ];
+
+// Path(s) that should be cleaned
+let pathsToClean = ['dist'];
+
+// Clean options to use
+let cleanOptions = {
+  root: path.resolve(__dirname, './pgadmin/static/'),
+  verbose: true,
+  dry: false
+};
+
+// extract vendor css files in cssResources
+grunt.file.expand({ cwd: vendorDir }, "**/*.css").forEach(function(page) {
+    file_name = path.basename(page).replace('.min', '').replace('.rtl', '');
+    if (excludes.indexOf(file_name) === -1) {
+      excludes.push(file_name);
+      cssResources.push((vendorDir +  page));
+    }
+});
+
+// Add css files explicitly
+cssResources.push(vendorDir + 'bootstrap/css/bootstrap.min.css');
+cssResources.push(vendorDir + 'bootstrap/css/bootstrap-theme.min.css');
+cssResources.push('./pgadmin/browser/static/vendor/aciTree/css/aciTree.css');
+
+// Main webpack configurations starts here
+const config = {
+  // Create two files main.css and overrides.css
+  entry: {
+    main: cssResources,
+    overrides: [
+      baseDir + 'css/bootstrap.overrides.css',
+      baseDir + 'css/pgadmin.css',
+    ]
+  },
+  output: {
+    path: path.resolve(__dirname, './pgadmin/static/dist/'), // path to dist directory
+    filename: '[name].css' // output js file name is identical to css file name
+  },
+  module: {
+    rules: [
+      {
+        test: /\.css$/,
+        use: ExtractTextPlugin.extract({
+          fallback: 'style-loader',
+          use: 'css-loader'
+        }),
+        exclude: /node_modules/
+      },
+      {
+        test: /\.(jpe?g|png|gif|svg)$/i,
+        loaders: [
+            'file-loader?hash=sha512&digest=hex&name=img/[name].[ext]', {
+            loader: 'image-webpack-loader',
+            query: {
+              bypassOnDebug: true,
+              mozjpeg: {
+                progressive: true,
+              },
+              gifsicle: {
+                interlaced: false,
+              },
+              optipng: {
+                optimizationLevel: 7,
+              },
+              pngquant: {
+                quality: '75-90',
+                speed: 3
+              },
+            }
+          }
+        ],
+        exclude: /node_modules/
+     },
+     {
+        test: /\.(eot|svg|ttf|woff|woff2)$/,
+        loader: 'file-loader?name=fonts/[name].[ext]',
+        exclude: /node_modules/
+     }
+    ]
+  },
+  plugins: [
+    new cleanWebpackPlugin(pathsToClean, cleanOptions), // clean dist directory
+    new ExtractTextPlugin('[name].css'),
+    new OptimizeCssAssetsPlugin({
+      assetNameRegExp: /\.css$/g,
+      cssProcessor: require('cssnano'),
+      cssProcessorOptions: { discardComments: {removeAll: true } },
+      canPrint: true
+    })
+  ]
+};
+module.exports = config;


^ permalink  raw  reply  [nested|flat] 13+ messages in thread


end of thread, other threads:[~2017-06-08 11:43 UTC | newest]

Thread overview: 13+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2017-05-22 05:50 [pgAdmin4][Patch]: Load module's JS files only when required Surinder Kumar <[email protected]>
2017-05-22 10:52 ` Dave Page <[email protected]>
2017-05-22 12:39   ` Surinder Kumar <[email protected]>
2017-05-22 21:33     ` Dave Page <[email protected]>
2017-05-23 18:45       ` Joao Pedro De Almeida Pereira <[email protected]>
2017-05-23 20:21         ` Dave Page <[email protected]>
2017-05-25 21:32           ` Dave Page <[email protected]>
2017-05-26 04:01             ` Surinder Kumar <[email protected]>
2017-05-29 00:15               ` Dave Page <[email protected]>
2017-06-05 09:22                 ` Surinder Kumar <[email protected]>
2017-06-06 13:39                   ` Dave Page <[email protected]>
2017-06-07 18:10                     ` Joao Pedro De Almeida Pereira <[email protected]>
2017-06-08 11:43                       ` Dave Page <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox