own page load microopt: reduce blocking on i18n

* localStorage cache is faster than chrome.i18n.get
* TreeWalker is faster than tHTML for removing extraneous whitespace
* simple for() is faster than for-of with [...iterable]
This commit is contained in:
tophf 2017-04-17 18:54:39 +03:00
parent 4eae87e606
commit b3b1d4a628
4 changed files with 47 additions and 12 deletions

View File

@ -37,6 +37,18 @@ function webNavigationListener(method, data) {
}); });
} }
// reset i18n cache on language change
setTimeout(() => {
const {browserUIlanguage} = tryJSONparse(localStorage.L10N) || {};
const UIlang = chrome.i18n.getUILanguage();
if (browserUIlanguage != UIlang) {
localStorage.L10N = JSON.stringify({
browserUIlanguage: UIlang,
});
}
});
// messaging // messaging
chrome.runtime.onMessage.addListener(onRuntimeMessage); chrome.runtime.onMessage.addListener(onRuntimeMessage);

View File

@ -5,10 +5,14 @@ tDocLoader();
function t(key, params) { function t(key, params) {
const s = chrome.i18n.getMessage(key, params); const cache = !params && t.cache[key];
const s = cache || chrome.i18n.getMessage(key, params);
if (s == '') { if (s == '') {
throw `Missing string "${key}"`; throw `Missing string "${key}"`;
} }
if (!params && !cache) {
t.cache[key] = s;
}
return s; return s;
} }
@ -35,24 +39,38 @@ function tHTML(html) {
function tNodeList(nodes) { function tNodeList(nodes) {
for (const node of [...nodes]) { const PREFIX = 'i18n-';
for (let n = nodes.length; --n >= 0;) {
const node = nodes[n];
// skip non-ELEMENT_NODE // skip non-ELEMENT_NODE
if (node.nodeType != 1) { if (node.nodeType != 1) {
continue; continue;
} }
if (node.localName == 'template') { if (node.localName == 'template') {
const elements = node.content.querySelectorAll('*');
tNodeList(elements);
template[node.dataset.id] = elements[0];
// compress inter-tag whitespace to reduce number of DOM nodes by 25% // compress inter-tag whitespace to reduce number of DOM nodes by 25%
template[node.dataset.id] = tHTML(node.innerHTML); const walker = document.createTreeWalker(elements[0], NodeFilter.SHOW_TEXT);
const toRemove = [];
while (walker.nextNode()) {
const textNode = walker.currentNode;
if (!textNode.nodeValue.trim()) {
toRemove.push(textNode);
}
}
toRemove.forEach(el => el.remove());
continue; continue;
} }
for (const attr of [...node.attributes]) { for (let a = node.attributes.length; --a >= 0;) {
let name = attr.nodeName; const attr = node.attributes[a];
if (name.indexOf('i18n-') != 0) { const name = attr.nodeName;
if (!name.startsWith(PREFIX)) {
continue; continue;
} }
name = name.substr(5); // 'i18n-'.length const type = name.substr(PREFIX.length);
const value = t(attr.value); const value = t(attr.value);
switch (name) { switch (type) {
case 'text': case 'text':
node.insertBefore(document.createTextNode(value), node.firstChild); node.insertBefore(document.createTextNode(value), node.firstChild);
break; break;
@ -63,15 +81,17 @@ function tNodeList(nodes) {
node.insertAdjacentHTML('afterbegin', value); node.insertAdjacentHTML('afterbegin', value);
break; break;
default: default:
node.setAttribute(name, value); node.setAttribute(type, value);
} }
node.removeAttribute(attr.nodeName); node.removeAttribute(name);
} }
} }
} }
function tDocLoader() { function tDocLoader() {
t.cache = tryJSONparse(localStorage.L10N) || {};
const cacheLength = Object.keys(t.cache).length;
// localize HEAD // localize HEAD
tNodeList(document.getElementsByTagName('*')); tNodeList(document.getElementsByTagName('*'));
@ -85,6 +105,9 @@ function tDocLoader() {
const onLoad = () => { const onLoad = () => {
tDocLoader.stop(); tDocLoader.stop();
process(observer.takeRecords()); process(observer.takeRecords());
if (cacheLength != Object.keys(t.cache).length) {
localStorage.L10N = JSON.stringify(t.cache);
}
}; };
tDocLoader.start = () => { tDocLoader.start = () => {
observer.observe(document, {subtree: true, childList: true}); observer.observe(document, {subtree: true, childList: true});

View File

@ -4,8 +4,8 @@
<title i18n-text-append="optionsHeading">Stylus </title> <title i18n-text-append="optionsHeading">Stylus </title>
<link rel="stylesheet" href="index.css"> <link rel="stylesheet" href="index.css">
<script src="/dom.js"></script> <script src="/dom.js"></script>
<script src="/localization.js"></script>
<script src="/messaging.js"></script> <script src="/messaging.js"></script>
<script src="/localization.js"></script>
<script src="/prefs.js"></script> <script src="/prefs.js"></script>
<script src="/apply.js"></script> <script src="/apply.js"></script>
</head> </head>

View File

@ -56,8 +56,8 @@
</template> </template>
<script src="dom.js"></script> <script src="dom.js"></script>
<script src="localization.js"></script>
<script src="messaging.js"></script> <script src="messaging.js"></script>
<script src="localization.js"></script>
<script src="prefs.js"></script> <script src="prefs.js"></script>
<script src="apply.js"></script> <script src="apply.js"></script>
<script src="popup.js"></script> <script src="popup.js"></script>