public inbox for [email protected]  
help / color / mirror / Atom feed
From: Dave Page <[email protected]>
To: Joao Pedro De Almeida Pereira <[email protected]>
Cc: Surinder Kumar <[email protected]>
Cc: pgadmin-hackers <[email protected]>
Subject: Re: [pgAdmin4][Patch]: Load module's JS files only when required
Date: Thu, 8 Jun 2017 12:43:59 +0100
Message-ID: <CA+OCxoyfUB6=Vd2RMymadVt_vkYCBPB1pj5PCecJGW=cXk8GjA@mail.gmail.com> (raw)
In-Reply-To: <CAE+jjamex0O2bRH2Yrn7XPcqZVsrQN9jJtuH1taeLQDD4gvcgQ@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>
	<CAM5-9D9UGqvoYkTmfjC+zEfD1WkdqGp8mi4Lk9+8X2EBD8x8LA@mail.gmail.com>
	<CA+OCxozXC2vsUJzsZ8nKHHza51QXou3S1PKKunCt5_5TUMXJxA@mail.gmail.com>
	<CAE+jjamex0O2bRH2Yrn7XPcqZVsrQN9jJtuH1taeLQDD4gvcgQ@mail.gmail.com>
List-Unsubscribe:  <mailto:[email protected]?body=unsub%20pgadmin-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;


view thread (13+ messages)

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: <CA+OCxoyfUB6=Vd2RMymadVt_vkYCBPB1pj5PCecJGW=cXk8GjA@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