Products.cmfplone: Merged bundles does not work when switching domains

Created on 14 Apr 2016  路  16Comments  路  Source: plone/Products.CMFPlone

Another issue I've encountered when using the merged bundle feature is that it includes generated requirejs configuration. Generated requirejs configuration includes a baseUrl setting which is specific to the url that you first created the site with.

Imagine you create the site, through a tunnel on localhost:8080, then switch the site over to production. The requirejs config has the baseUrl as http://localhost:8080/Plone and things start breaking.

cc @ebrehault

All 16 comments

And do you think we could set baseUrl to '/Plone' instead of 'http://localhost:8080/Plone' or does require really need a full url here?

An easy fix is to exclude this file from the merged bundles (so that will add another JS request when we load a Plone page, but at least it will work).

Or we just do something like $('body').attr('data-portal-url') || '/Plone'

I was also hit by this prob when I tried to upgrade a site some weeks ago. It worked without virtual hosting, but with nginx on the front, pointing to a virual host root, it didn't.

@thet fwiw, turning on dev mode and then off again in resource registries forces them to be re-cooked.

@thet you can also import the "Bundle combination" GenericSetup step

I did not know about the bundle combination setup step. sounds good!
unrelated - but IMO plone should withdraw old ++UNIQUE++ cachign urls and generate new ones on startup (that was also the behavior in Plone 4 and actually convenient). but that's unrelated.

related is: https://github.com/plone/Products.CMFPlone/issues/1433
this is the issue describing roughly what we encountered on a plone upgrade at the beginning of march.

@vangheem @thet here is the fixed https://github.com/plone/Products.CMFPlone/pull/1531

Notes:

  • I preferred to default to '/' instead of '/Plone' (assuming the plone site id is Plone seems weaker than assuming we are in prod),
  • I had to enclose the requirejs.config call into a $(document).ready because at the time the script is evaluated, the DOM is not parsed yet, so we cannot read data-portal-url. Do you think that's ok?

Ahh, I thought by /Plone you just meant /<site-id-generated-from>.

Enclosing it in the ready won't really work I don't think.

I know it might be frowned on but we may have to consider sending a global <script>PORTAL_URL = "http://foobar.com";</script> for every request or something similar...

Any other ideas? @bloodbare ?

I usally do not install Plone sites with the id Plone. IMO using the real id is a must. Binding on root can be problematic, if more Plone sites are installed within the same Zope server?

I was asking myself, if $(document).ready works for scripts loaded by RequireJS asynchronously, when RequreJS already consumes the ready event. But as https://api.jquery.com/ready/ implies, $(document).ready is not a event listener, so no prob with that. Don't know about other issues except that deferring JavaScript execution like that might make the site feel much slower (especially mosaic) - @vangheem ?

An alternative would also be to create a settings factory, which loads a JSON. Once it's loaded, subsequent calls to the factory just return cached results...

In main_template.pt we could do something like this...

<metal:page define-macro="master"
  tal:define="portal_state context/@@plone_portal_state;
              portal_url portal_state/portal_url;">
<tal:doctype tal:replace="structure string:&lt;!DOCTYPE html&gt;" />

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:tal="http://xml.zope.org/namespaces/tal"
      xmlns:metal="http://xml.zope.org/namespaces/metal"
      xmlns:i18n="http://xml.zope.org/namespaces/i18n"
      data-portal-url="${portal_url}"
      tal:define="
          context_state context/@@plone_context_state;
          plone_view context/@@plone;
          plone_layout context/@@plone_layout;
          lang portal_state/language;
          view nocall:view | nocall: plone_view;
          dummy python: plone_layout.mark_view(view);
          checkPermission nocall: context/portal_membership/checkPermission;
          site_properties context/portal_properties/site_properties;
          ajax_include_head request/ajax_include_head | nothing;
          ajax_load python:False;"
      i18n:domain="plone"
      tal:attributes="lang lang;">

THen, with js document.documentElement.getAttribute('data-portal-url') without jquery.

@thet Well, it's possible to have js that lazy loads some modules(by lazy load, I mean does not have it pre-compiled).. Here is a simple scenario where there could be an issue...

Load merged js files:

  • default.js
  • mybundle.js

My bundle.js contains a lazy load module that needs configuration; however, since mybundle.js initiates loading before $(document).ready, it does not have the requirejs config at the time it tries to load the module and will fail.

We need the proper url immediately unfortunately...

Or, just output a simple <script>PORTAL_URL = "http://foobar.com";</script>. I really don't think it's that big of a deal and is the least impacting change.

FYI $(document).ready seems to work (tests are passing http://jenkins.plone.org/job/pull-request-5.1/127/), but I do not like it much. Your last solution sounds more solid.

Sorry I've been missing, but why requirejs config.js is included in the bundle ?

In production mode we decided to put jquery / require.js and config.js as separate files to make sure its not interfering with any bundling. I thought that the bundling together idea was only joining bundles !

Sorry if I missed that information on any place !

Well, the principle of the bundle merging PLIP was to reduce the number of separated files we load. If we had to publish jquery, require and config as separate files, it would be 3 more files, so that's just better to merge them with the bundles.
The fix @vangheem sounds quite simple (just waiting for the tests to finish: http://jenkins.plone.org/job/pull-request-5.1/128/ ).

Was this page helpful?
0 / 5 - 0 ratings