public inbox for [email protected]  
help / color / mirror / Atom feed
From: Surinder Kumar <[email protected]>
To: Dave Page <[email protected]>
Cc: Joao Pedro De Almeida Pereira <[email protected]>
Cc: pgadmin-hackers <[email protected]>
Subject: Re: [pgAdmin4][Patch]: Load module's JS files only when required
Date: Mon, 5 Jun 2017 14:52:36 +0530
Message-ID: <CAM5-9D9UGqvoYkTmfjC+zEfD1WkdqGp8mi4Lk9+8X2EBD8x8LA@mail.gmail.com> (raw)
In-Reply-To: <CA+OCxozps=GgHvXKJNJx3r9KUsn_g71jY4pRqR24gwP8cW-9ug@mail.gmail.com>
References: <CAM5-9D92zW=qJqKT_HFjtMQvOAXuz5a5DJuABnz9fWWLKeZZrw@mail.gmail.com>
	<CA+OCxoz3Y7aR0JJ0mq-YnnZnztML-Hkv3Trt3hf74GvW0-0Urw@mail.gmail.com>
	<CAM5-9D-EayFdbqNQN-E5znYRf8PSk-DNxswB-ctb8Nmi6xHnkg@mail.gmail.com>
	<CA+OCxozaTaaj_mEQRK=N14S=Q8FuepeY2SqPyW5cz8hw6f+pVg@mail.gmail.com>
	<CAE+jjamWHkMkzh8AcSoLR-sezdgVMUBF1qCHthJzc863ppVdCw@mail.gmail.com>
	<CA+OCxoyT_mxi=1Mf07w-qdS95wsd0ako=z7YN=7wotiQd4b7=g@mail.gmail.com>
	<CA+OCxoyJ2wWLeOaFBtac247Bkij5e-X4MQ6EtAKy2dsK18Le2g@mail.gmail.com>
	<CAM5-9D-h0ojZmZgeq-Df+3_JLnbURZo2qmhmLKgi-LZQhEHjcw@mail.gmail.com>
	<CA+OCxozps=GgHvXKJNJx3r9KUsn_g71jY4pRqR24gwP8cW-9ug@mail.gmail.com>
List-Unsubscribe:  <mailto:[email protected]?body=unsub%20pgadmin-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;


view thread (13+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected]
  Subject: Re: [pgAdmin4][Patch]: Load module's JS files only when required
  In-Reply-To: <CAM5-9D9UGqvoYkTmfjC+zEfD1WkdqGp8mi4Lk9+8X2EBD8x8LA@mail.gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

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