Plone 5 frontend development plugin for webpack

Just curious, do you think there's value in ditching RequireJS in favour of a webpack driven approach?

@pigeonflight @datakurre if we did we'd need to do it soon before too many start upgrading plugins etc and we'd better be darn sure webpack is not just another stepping stone to something else.

1 Like

But they are not completely comparable.

RequireJS is both a module / dependency definition syntax and a bundler. And RequireJS is (AFAIK) the only bundler, which can do the bundling in browser (and work TTW without NodeJS backend server).

Webpack is only a bundler. Webpack works just fine with RequireJS-style definitions. Currently I even rely on our ResourceRegistry definitions when bundling with Webpack.

And webpack may not work at all for pre-building additive bundles in add-ons. @djay asked about, if and how Webpack could be used to build add-on bundle for Plomino. Yes, webpack could be used to build a bundle, which includes all the required Plone JS and Plomino JS.

But I don't know, if it's even possible to build a bundle, which expect Plone logged-in-bundle to be loaded before it (and not duplicate anything in it). And it probably breaks if one tries to include two independently built webpack bundles on the same page.

I prefer Webpack, because it helps me to get work done, but does add an another complex buildout-like tool to learn.

1 Like

well said! that' s exactly what we have to start discussing.

@datakurre IMO, we're trying to solve the wrong problem: resource bundling is a thing of the past as HTTP/2 is multiplexed and makes it less desirable, so TTW bundling makes absolutely no sense neither.

I returned from Boston with the idea that JS is finally maturing and things are not going to change so much in the future.

if you were to ask me, I'll vote to remove all the complexity on our current implementation of bundling as it has been proven buggy and not future proof; I'll love to read what others think.

so, what we need? I'm not pretty sure of the whole picture but, IMO, in Plone we should be using RequireJS only and a module bundler like webpack for core development,(defined by the framework team after some discussion.

add-on developers could use the module bundler of their choice on their projects, and best practices must define what Plone is expecting from the resources of an add-on.

1 Like

I still image, even with http2 spec, we'll want bundling. Considering modern framework can build hundreds of files together--even if the client is able to maintain one connection, it'll be many more hits on the server and I also wonder if the client will be less performant.

Also, FWIW, I did an attempt to package all of plone's resources with webpack automatically by reading the registry dynamically: https://github.com/castlecms/castle.cms/blob/master/castle/cms/_scripts/generate-webpack.py

I wasn't impressed with the results. I could never get the LESS/CSS to work completely correctly and it was difficult to control how you manage the bundled files--wanted to split into chunks that it seemed difficult to control. In the end, I didn't think it was worth it. I still use webpack for other development(angular/react) though.

My webpack plugin does read RequireJS configuration and LESS configuration from Plone (config.js and less-variables.js), and I do have LESS/CSS working completely correctly (as far as I know). But I do define bundles manually. I use webpack-level bundles (common chunk, default, logged-in and add-on-specific bundles), include them all as separate link/script-tags in theme/site-layout, and enable/disable them with Diazo.

The most difficult part has been shimming. I decided to not trust shim definitions in Plone registry, but manage shims for core patterns in the plugin using webpack loaders and plugins. For example, making dynamic requires in structure pattern to work with webpack was not trivial. For add-ons, I mostly just use webpack's inline loader syntax (in require/import lines of JS files defining bundles).

Some reasons why I chose and keep using webpack with Plone 5:

  • Managing and optimizing final bundles with Webpack
  • Webpack devevelopment server with auto-reload and hot module reload
  • Easy pattern overrides (by overriding RequireJS alias path)
  • ES6 transpilation with Babel
  • Using both LESS and SASS (Plone is LESS, all the rest SASS)
  • Inlining icons as data-uris in CSS
  • Distributing final bundles outside Plone (we have several sites sharing the same theme)

I'm still on Webpack 1.x. I will only start porting my plugin to Webpack 2.x once it has a final release and all plugins, which I'm depending on, have been updated.

@datakurre I suspect I'm not going to be able to take your webpacktemplate and plugin and integrate them into this angular 2 plugin (plomino). I suspect your plugin is using react, and making assumptions about this being for a theme rather than a plugin. But given I don't know angular, react or even really plones bundling system I think I'm really out of my depth.

Here is my attempt to merge it so far https://github.com/plomino/Plomino/commit/b33516eb350b28bf5a097b5135237daf52192966.

Any help @ebrehault @datakurre or anyone who knows angular 2 or webpack, it would be greatly appreciated.

Lines about React are just examples for overriding requirejs aliases.

@djay How much of Plone do you need exactly? That really affects the complexity.

@datakurre I think we mostly need patterns and tinymce integration. We also need patterns that have been written in the plomino bundle. Mainly we are trying to handle several DX forms by loading and POSTing them via ajax. And they use patterns.

@datakure we don't need the toolbar or contents or any of that stuff.

@djay As I said, I'd try my first approach (without plonetheme-webpack-plugin) at first. So, instead of merging that, I merged parts from plonetheme.webpack:

It builds, at least. I have not tested further. Another twists are that typescript will complain when you import non-ts-modules (and because it does not know about webpack aliases) and if you don't use those modules, typescript seem to drop them and they won't get bundled. Also, as you can see from the required tweaks (lot of git checkouts with npm), we are far from being proper JS citizens.

Although I think that bundle could never disappear completely, recently I read a lot of articles by some "front-end guys". What seems clear is that HTTP2 remove the need of bundling. Full stop. Somebody says that "bundling will be an anti-pattern". Also: HTTP2 support today is really high so I find the webpack approach outside Zope every day more interesting.

This take me to another question:

(...five secs of dramatic drum sound...)

Will Zope ever support HTTP2? Or it makes no sense?

I think, that can be achieved via an external WSGI server.

@datakurre sorry I missed where you said to not use plonetheme-webpack-plugin. I've had a look at your code. I can see it tries to bring in patterns so now I will try calling the scan and see if I can get that working. I will also have to work out how to modify this to bring in the patterns defined in plomino but I think this will give me the start I need. Thanks very much for you help

I've finally updated plonetheme.webpacktemplate for Webpack 2.x. I should be using it myself for the next few weeks, so I expect to solve any issues.

I'm also experimenting the related webpack plugin (one that loads resources from Plone RR for webpack) with add-on development https://github.com/plone/plone.app.theming/pull/130 Not sure yet, if it's really that useful outside theming.

4 Likes

do you mind to share those readings? it could be interesting for people still hooked on the past, using old fashioned technologies like bundling (pun intended).

that's not the case; here are some good reasons against bundling (from a Stack Overflow post):

  • Bundling can lead to trivial cache misses. Any change to any part of your app invalidates the browser cache.
  • Bundling can make it harder to leverage a cache of common libraries. If you're using the same version of jquery from the same cdn as everyone else there's a good chance your users will never have to even hit your servers for it.
  • Bundling means that you generally are loading all of your JavaScript at once. There are exceptions like webpack code splitting but this complicates your build pipeline versus cating files.
  • Bundling means missing out on HTTP/2's ability to handle multiple asset requests in parallel.

here are some real life numbers from the CloudFlare website:

Access via HTTP Protocol Version 	Average Page Load time
HTTP 1.x 				9.07 sec.
SPDY/3.1 				7.06 sec.
HTTP/2 					4.27 sec.

yes, we may still need bundling, but for some totally different reasons than performance.

UPDATE: here are other interesting numbers showing latency in the biggest player here: if you expect a high latency then you gain almost nothing by concatenating: but, if you expect low latency concatenating could be in fact much better:

having said that, my initial proposal to bundle on a add-on base makes a lot of sense.

for Plone, bundling for anonymous and authenticated users, leaving the common libraries out, sounds like the best approach.

1 Like

I've finally updated plonetheme.webpacktemplate for Webpack 4.x for building a TTW uploadable Diazo them with Webpack bundled resources. I have not yet updated my projects to use it, so it is possible that there are still some rough edges.

Travis has smoketest builds for the latest Plone 5.0 and 5.1 Travis CI - Test and Deploy with Confidence

There are a few major changes to fix things and make the template simpler to use:

  • The resulting theme now loads Plone require.js configuration after Webpack bundles. This fixes issues with non-patternized scripts like search page and Dexterity schema editor drag and drop. It also allows to write TTW scripts with require.js even when the base bundle is Webpack based.

  • There is only one Webpack bundle entry-point by default. Resources for logged-in-users are loaded lazily using Webpack dynamic imports when the user looks like being logged-in. Previous versions created separate bundles for anymous and logged-in users (and e.g. for large add-ons) and unnecessary bundles were filtered using Diazo rules. This is still possible, but I wanted to support dynamic imports by default (with a polyfill for IE 11) and include example of using those. Technically this would allow e.g. include certain patterns only when "pat-something" is present (if lazy loading does not affect the user experience).

  • jQuery is not exposed by default (but can be exposed with uncommenting a single line)

  • I removed SVG-icons option and Vagrant support. Also, thanks to upstream fixes, it was also no longer required to include a customized copy of barceloneta.plone.less. These all reduced number of files and hopefully simplified the template.

3 Likes

I had chance to do some maintenance for plonetheme.webpacktemplate with the following results:

  • Latest webpack 4.x is supported.

  • Plone 5.0.x is currently supported only up to 5.0.8, because Plone 5.0.9 and 5.0.10 seem to ship with source versions of TinyMCE and Mockup incompatible with each other (the pattern requires resources not available in the shipped TinyMCE version).

  • Plone 5.1.5 seems to work fine.

  • Plone 5.2.0 is now supported. Minor change (dynamic require) in moment-pattern required upgrade to the webpack plugin. Also because of some change between Plone 5.1 and 5.2, pattern registry scan was no longer triggered automatically with webpack bundles, but must be called from the bundle (included in template).

1 Like