imp: qweb compiler now condenses whitespaces

This is a pretty big breaking change: the html output by qweb is now
different.

The main goal is to optimize the compiled templates:
- condense all consecutive whitespaces into a single spaces
- if possible, drop completely some text nodes, based on the following
  heuristic: if a text node is only composed of whitespaces, and
contains at least one linebreak, then it can be dropped.

This leads in my benchmark test to an improvement of about 10%, in
rendering speed and in memory consuption.

Note: whitespace here means anything that matches the \s regexp: newlines,
tabs, ...

close #8
This commit is contained in:
Géry Debongnie
2019-03-22 11:09:57 +01:00
parent d81e5d8f4f
commit a7d2edd0c9
11 changed files with 169 additions and 468 deletions
+19
View File
@@ -32,6 +32,9 @@ const DISABLED_TAGS = [
"optgroup"
];
const lineBreakRE = /[\r\n]/;
const whitespaceRE = /\s+/g;
//------------------------------------------------------------------------------
// Compilation Context
//------------------------------------------------------------------------------
@@ -49,6 +52,7 @@ export class Context {
shouldDefineOwner: boolean = false;
shouldProtectContext: boolean = false;
inLoop: boolean = false;
inPreTag: boolean = false;
constructor() {
this.rootContext = this;
@@ -84,6 +88,12 @@ export class Context {
return newContext;
}
withInPre(): Context {
const newContext = Object.create(this);
newContext.inPreTag = true;
return newContext;
}
withCaller(node: Element): Context {
const newContext = Object.create(this);
newContext.caller = node;
@@ -336,6 +346,12 @@ export class QWeb {
if (!(node instanceof Element)) {
// this is a text node, there are no directive to apply
let text = node.textContent!;
if (!ctx.inPreTag) {
if (lineBreakRE.test(text) && !text.trim()) {
return;
}
text = text.replace(whitespaceRE, " ");
}
if (ctx.parentNode) {
ctx.addLine(`c${ctx.parentNode}.push({text: \`${text}\`});`);
} else {
@@ -410,6 +426,9 @@ export class QWeb {
}
}
}
if (node.nodeName === "pre") {
ctx = ctx.withInPre();
}
this._compileChildren(node, ctx);