[IMP] website: pregenerate frontend assets

closes odoo/odoo#99176

Signed-off-by: Christophe Monniez (moc) <moc@odoo.com>
This commit is contained in:
Xavier-Do
2022-09-12 13:49:00 +02:00
parent 31b04aa44b
commit c764c38d7c
3 changed files with 56 additions and 4 deletions
+1 -1
View File
@@ -84,4 +84,4 @@ class TestLoad(HttpCase):
with patch('odoo.addons.base.models.assetsbundle.AssetsBundle.save_attachment', save_attachment):
self.url_open('/web').raise_for_status()
#self.url_open('/').raise_for_status() #currently breaking because of the website_id
self.url_open('/').raise_for_status()
+50
View File
@@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import re
import logging
from collections import OrderedDict
from odoo import models
@@ -11,6 +13,8 @@ from odoo.addons.http_routing.models.ir_http import url_for
from odoo.osv import expression
from odoo.addons.website.models import ir_http
_logger = logging.getLogger(__name__)
re_background_image = re.compile(r"(background-image\s*:\s*url\(\s*['\"]?\s*)([^)'\"]+)")
@@ -149,3 +153,49 @@ class IrQWeb(models.AbstractModel):
atts['style'] = re_background_image.sub(lambda m: '%s%s' % (m.group(1), website.get_cdn_url(m.group(2))), atts['style'])
return atts
def _pregenerate_assets_bundles(self):
# website is adding a website_id to the extra part of the attachement url (/1)
# /web/assets/2223-ee56665/1/web.assets_common.min.css
# /web/assets/2224-47bce88/1/web.assets_frontend.min.css
# /web/assets/2225-8b64a2b/1/web.assets_common_minimal.min.js
# /web/assets/2226-17d3428/1/web.assets_frontend_minimal.min.js
# /web/assets/2227-b9cd4ba/1/web.assets_tests.min.js
# /web/assets/2228-7424684/1/web.assets_common_lazy.min.js
# /web/assets/2229-25b1d52/1/web.assets_frontend_lazy.min.js
# this means that the previously generated attachment wont be used on the website
# the main reason is to avoid invalidating other website attachement, but the
# version part combine with the initial extra (rtl) should be enough to ensure they are identical.
# we dont expect to have any pregenerated rtl/website attachment so we don't manage assets with extra
nodes = super()._pregenerate_assets_bundles()
website = self.env['website'].search([], order='id', limit=1)
if not website:
return nodes
nb_created = 0
for node in nodes:
bundle_info = node[1]
bundle_url = bundle_info.get('src', '') or bundle_info.get('href', '')
if bundle_url.startswith('/web/assets/'):
# example: "/web/assets/2152-ee56665/web.assets_common.min.js"
_, _, _, id_unique, name = bundle_url.split('/')
attachment_id, unique = id_unique.split('-')
url_pattern = f'/web/assets/%s-%s/{website.id}/{name}'
existing = self.env['ir.attachment'].search([('url', '=like', url_pattern % ('%', '%'))])
if existing:
if f'-{unique}/' in existing.url:
continue
_logger.runbot(f'Updating exiting assets {existing.url} for website {website.id}')
# we assume that most of the time the first website bundles will be the same as the base one
# if the unique changes, it is most likely because sources where update since install.
# this is mainly for dev downloading a database from runbot and trying to execute tests locally
existing.unlink()
new = self.env['ir.attachment'].browse(int(attachment_id)).copy()
new.url = url_pattern % (new.id, unique)
nb_created += 1
if nb_created:
_logger.runbot('%s bundle(s) were copied for website %s', nb_created, website.id)
return nodes
+5 -3
View File
@@ -2533,15 +2533,17 @@ class IrQWeb(models.AbstractModel):
js_bundles.add(asset)
if css:
css_bundles.add(asset)
nodes = []
start = time.time()
for bundle in sorted(js_bundles):
self._generate_asset_nodes(bundle, css=False, js=True)
nodes += self._generate_asset_nodes(bundle, css=False, js=True)
_logger.info('JS Assets bundles generated in %s seconds', time.time()-start)
start = time.time()
for bundle in sorted(css_bundles):
self._generate_asset_nodes(bundle, css=True, js=False)
nodes += self._generate_asset_nodes(bundle, css=True, js=False)
_logger.info('CSS Assets bundles generated in %s seconds', time.time()-start)
return nodes
def render(template_name, values, load, **options):
""" Rendering of a qweb template without database and outside the registry.