From 557a24e4f43c49655e8f2b0ddd310f60c0de25cd Mon Sep 17 00:00:00 2001 From: Samuel Degueldre Date: Thu, 29 Apr 2021 08:28:07 +0000 Subject: [PATCH] [IMP] web: allow lazy-loading asset bundles' templates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, lazy-loading xml templates was only possible by fetching the xml file directly, this meant that it was impossible to lazy-load an entire bundle's templates with a single request. Additionally, requesting the xml files directly meant that no inheritance was applied, causing the need for a separate inheritance system using t-jquery on the client-side. This commit alters the /web/webclient/qweb route so that it now takes a bundle id, meaning that it is now possible to lazy-load the xml from arbitrary bundles. task-2497943 closes odoo/odoo#70084 Signed-off-by: Géry Debongnie (ged) --- addons/web/controllers/main.py | 20 ++++++++++---------- addons/web/models/ir_http.py | 2 +- addons/web/static/src/js/core/session.js | 2 +- doc/reference/javascript_reference.rst | 4 +++- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index dd627f34526..bca3f772b8d 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -549,13 +549,13 @@ class HomeStaticTemplateHelpers(object): return etree.tostring(root, encoding='utf-8') if root is not None else b'', checksum.hexdigest()[:64] - def _get_asset_paths(self): + def _get_asset_paths(self, bundle): """Proxy for ir_asset._get_asset_paths Useful to make 'self' testable. """ - return request.env['ir.asset']._get_asset_paths(addons=self.addons, bundle='web.assets_qweb', xml=True) + return request.env['ir.asset']._get_asset_paths(addons=self.addons, bundle=bundle, xml=True) - def _get_qweb_templates(self): + def _get_qweb_templates(self, bundle): """One and only entry point that gets and evaluates static qweb templates :rtype: (str, str) @@ -563,7 +563,7 @@ class HomeStaticTemplateHelpers(object): xml_paths = defaultdict(list) # group paths by module, keeping them in order - for path, addon, _ in self._get_asset_paths(): + for path, addon, _ in self._get_asset_paths(bundle): addon_paths = xml_paths[addon] if path not in addon_paths: addon_paths.append(path) @@ -572,12 +572,12 @@ class HomeStaticTemplateHelpers(object): return content, checksum @classmethod - def get_qweb_templates_checksum(cls, addons=None, db=None, debug=False): - return cls(addons, db, checksum_only=True, debug=debug)._get_qweb_templates()[1] + def get_qweb_templates_checksum(cls, addons=None, db=None, debug=False, bundle=None): + return cls(addons, db, checksum_only=True, debug=debug)._get_qweb_templates(bundle)[1] @classmethod - def get_qweb_templates(cls, addons=None, db=None, debug=False): - return cls(addons, db, debug=debug)._get_qweb_templates()[0] + def get_qweb_templates(cls, addons=None, db=None, debug=False, bundle=None): + return cls(addons, db, debug=debug)._get_qweb_templates(bundle)[0] class GroupsTreeNode: @@ -934,12 +934,12 @@ class WebClient(http.Controller): ]) @http.route('/web/webclient/qweb/', type='http', auth="none", cors="*") - def qweb(self, unique, mods=None, db=None): + def qweb(self, unique, mods=None, db=None, bundle=None): if not request.db and mods is None: mods = odoo.conf.server_wide_modules or [] - content = HomeStaticTemplateHelpers.get_qweb_templates(mods, db, debug=request.session.debug) + content = HomeStaticTemplateHelpers.get_qweb_templates(mods, db, debug=request.session.debug, bundle=bundle) return request.make_response(content, [ ('Content-Type', 'text/xml'), diff --git a/addons/web/models/ir_http.py b/addons/web/models/ir_http.py index cba920611eb..cbc46ca5ad8 100644 --- a/addons/web/models/ir_http.py +++ b/addons/web/models/ir_http.py @@ -51,7 +51,7 @@ class Http(models.AbstractModel): mods = odoo.conf.server_wide_modules or [] if request.db: mods = list(request.registry._init_modules) + mods - qweb_checksum = HomeStaticTemplateHelpers.get_qweb_templates_checksum(debug=request.session.debug) + qweb_checksum = HomeStaticTemplateHelpers.get_qweb_templates_checksum(debug=request.session.debug, bundle="web.assets_qweb") lang = user_context.get("lang") translation_hash = request.env['ir.translation'].get_web_translations_hash(mods, lang) menu_json_utf8 = json.dumps(request.env['ir.ui.menu'].load_menus(request.session.debug), default=ustr, sort_keys=True).encode() diff --git a/addons/web/static/src/js/core/session.js b/addons/web/static/src/js/core/session.js index 66010f21eb3..3fa9f1fe7bd 100644 --- a/addons/web/static/src/js/core/session.js +++ b/addons/web/static/src/js/core/session.js @@ -225,7 +225,7 @@ var Session = core.Class.extend(mixins.EventDispatcherMixin, { var lock = this.qweb_mutex.exec(function () { var cacheId = self.cache_hashes && self.cache_hashes.qweb; var route = '/web/webclient/qweb/' + (cacheId ? cacheId : Date.now()); - return $.get(route).then(function (doc) { + return $.get(route, { bundle: 'web.assets_qweb' }).then(function (doc) { if (!doc) { return; } const owlTemplates = []; for (let child of doc.querySelectorAll("templates > [owl]")) { diff --git a/doc/reference/javascript_reference.rst b/doc/reference/javascript_reference.rst index b4fd5e536a5..dc8cc92819f 100644 --- a/doc/reference/javascript_reference.rst +++ b/doc/reference/javascript_reference.rst @@ -1293,7 +1293,9 @@ python implementation. Now, let us explain how the templates are loaded. Whenever the web client starts, a rpc is made to the */web/webclient/qweb* route. The server will then return a list of all templates defined in data files for each installed modules. -The correct files are listed in the *qweb* entry in each module manifest. +The correct files are listed in the *web.assets_qweb* entry in each module +manifest. It is also possible to lazy-load another bundle's templates by calling +this same route and giving it the corresponding "bundle" query parameter. The web client will wait for that list of template to be loaded, before starting its first widget.