make editor load even faster

* reorder scripts
* make style request earlier
This commit is contained in:
tophf 2020-10-13 21:19:12 +03:00
parent 2e1a903cc7
commit bc6c9c826a
4 changed files with 110 additions and 123 deletions

View File

@ -18,6 +18,22 @@
}
</style>
<link id="cm-theme" rel="stylesheet">
<script src="js/polyfill.js"></script>
<script src="js/dom.js"></script>
<script src="js/messaging.js"></script>
<script src="js/prefs.js"></script>
<script src="js/localization.js"></script>
<script src="js/script-loader.js"></script>
<script src="js/storage-util.js"></script>
<script src="js/msg.js"></script>
<script src="content/style-injector.js"></script>
<script src="content/apply.js"></script>
<script src="edit/edit.js"></script> <!-- run it ASAP to send a request for the style -->
<link href="vendor/codemirror/lib/codemirror.css" rel="stylesheet">
<script src="vendor/codemirror/lib/codemirror.js"></script>
@ -63,44 +79,27 @@
<script src="vendor-overwrites/codemirror-addon/match-highlighter.js"></script>
<script src="js/polyfill.js"></script>
<script src="js/dom.js"></script>
<script src="js/messaging.js"></script>
<script src="js/prefs.js"></script>
<script src="js/localization.js"></script>
<script src="js/script-loader.js"></script>
<script src="js/storage-util.js"></script>
<script src="js/msg.js"></script>
<script src="js/worker-util.js"></script>
<script src="content/style-injector.js"></script>
<script src="content/apply.js"></script>
<link href="edit/global-search.css" rel="stylesheet">
<script src="edit/global-search.js"></script>
<script src="msgbox/msgbox.js" async></script>
<link href="edit/codemirror-default.css" rel="stylesheet">
<script src="edit/codemirror-default.js"></script>
<script src="edit/codemirror-factory.js"></script>
<script src="edit/util.js"></script>
<script src="edit/regexp-tester.js"></script>
<script src="edit/live-preview.js"></script>
<script src="edit/applies-to-line-widget.js"></script>
<script src="edit/reroute-hotkeys.js"></script>
<script src="edit/codemirror-factory.js"></script>
<link href="edit/global-search.css" rel="stylesheet">
<script src="edit/global-search.js"></script>
<script src="edit/colorpicker-helper.js"></script>
<script src="edit/beautify.js"></script>
<script src="edit/show-keymap-help.js"></script>
<script src="edit/codemirror-themes.js"></script>
<script src="edit/source-editor.js"></script>
<script src="edit/sections-editor-section.js"></script>
<script src="edit/sections-editor.js"></script>
<script src="edit/edit.js"></script>
<script src="msgbox/msgbox.js" async></script>
<script src="js/worker-util.js"></script>
<script src="edit/linter.js"></script>
<script src="edit/linter-defaults.js"></script>
<script src="edit/linter-engines.js"></script>
@ -109,8 +108,6 @@
<script src="edit/linter-report.js"></script>
<script src="edit/linter-config-dialog.js"></script>
<link id="cm-theme" rel="stylesheet">
<template data-id="appliesTo">
<li class="applies-to-item">
<div class="select-resizer">

View File

@ -1,15 +1,11 @@
/* global CodeMirror onDOMready prefs setupLivePrefs $ $$ $create t tHTML
createSourceEditor sessionStorageHash getOwnTab FIREFOX API tryCatch
closeCurrentTab messageBox debounce workerUtil
initBeautifyButton ignoreChromeError dirtyReporter
closeCurrentTab messageBox debounce
initBeautifyButton ignoreChromeError dirtyReporter linter
moveFocus msg createSectionsEditor rerouteHotkeys CODEMIRROR_THEMES */
/* exported showCodeMirrorPopup editorWorker toggleContextMenuDelete */
'use strict';
const editorWorker = workerUtil.createWorker({
url: '/edit/editor-worker.js'
});
let saveSizeOnClose;
// direct & reverse mapping of @-moz-document keywords and internal property names
@ -28,27 +24,37 @@ document.addEventListener('visibilitychange', beforeUnload);
window.addEventListener('beforeunload', beforeUnload);
msg.onExtension(onRuntimeMessage);
preinit();
lazyInit();
(async function init() {
const [style] = await Promise.all([
initStyleData(),
onDOMready(),
prefs.initializing,
prefs.initializing.then(() => new Promise(resolve => {
const theme = prefs.get('editor.theme');
const el = $('#cm-theme');
if (theme === 'default') {
resolve();
} else {
// preload the theme so CodeMirror can use the correct metrics
el.href = `vendor/codemirror/theme/${theme}.css`;
el.addEventListener('load', resolve, {once: true});
}
})),
]);
const usercss = isUsercss(style);
const dirty = dirtyReporter();
let wasDirty = false;
let nameTarget;
prefs.subscribe(['editor.linter'], updateLinter);
prefs.subscribe(['editor.keyMap'], showHotkeyInTooltip);
addEventListener('showHotkeyInTooltip', showHotkeyInTooltip);
showHotkeyInTooltip();
buildThemeElement();
buildKeymapElement();
setupLivePrefs();
initNameArea(style, usercss);
initNameArea();
initBeautifyButton($('#beautify'), () => editor.getEditors());
initResizeListener();
detectLayout();
@ -70,7 +76,7 @@ preinit();
$('#name').required = !usercss;
$('#save-button').onclick = editor.save;
function initNameArea(style, usercss) {
function initNameArea() {
const nameEl = $('#name');
const resetEl = $('#reset-name');
const isCustomName = style.updateUrl || usercss;
@ -116,6 +122,8 @@ preinit();
function buildThemeElement() {
CODEMIRROR_THEMES.unshift(chrome.i18n.getMessage('defaultTheme'));
$('#editor.theme').append(...CODEMIRROR_THEMES.map(s => $create('option', s)));
// move the theme after built-in CSS so that its same-specificity selectors win
document.head.appendChild($('#cm-theme'));
}
function buildKeymapElement() {
@ -216,81 +224,68 @@ preinit();
function updateTitle() {
document.title = `${dirty.isDirty() ? '* ' : ''}${style.customName || style.name}`;
}
function updateLinter(key, value) {
$('body').classList.toggle('linter-disabled', value === '');
linter.run();
}
})();
function preinit() {
// preload the theme so that CodeMirror can calculate its metrics in DOMContentLoaded->setupLivePrefs()
new MutationObserver((mutations, observer) => {
const themeElement = $('#cm-theme');
if (themeElement) {
themeElement.href = prefs.get('editor.theme') === 'default' ? ''
: 'vendor/codemirror/theme/' + prefs.get('editor.theme') + '.css';
observer.disconnect();
}
}).observe(document, {subtree: true, childList: true});
if (chrome.windows) {
browser.tabs.query({currentWindow: true}).then(tabs => {
const windowId = tabs[0].windowId;
if (prefs.get('openEditInWindow')) {
if (
/true/.test(sessionStorage.saveSizeOnClose) &&
'left' in prefs.get('windowPosition', {}) &&
!isWindowMaximized()
) {
// window was reopened via Ctrl-Shift-T etc.
chrome.windows.update(windowId, prefs.get('windowPosition'));
}
if (tabs.length === 1 && window.history.length === 1) {
chrome.windows.getAll(windows => {
if (windows.length > 1) {
sessionStorageHash('saveSizeOnClose').set(windowId, true);
saveSizeOnClose = true;
}
});
} else {
saveSizeOnClose = sessionStorageHash('saveSizeOnClose').value[windowId];
}
}
/* Stuff not needed for the main init so we can let it run at its own tempo */
async function lazyInit() {
const ownTabId = (await getOwnTab()).id;
// use browser history back when 'back to manage' is clicked
if (sessionStorageHash('manageStylesHistory').value[ownTabId] === location.href) {
onDOMready().then(() => {
$('#cancel-button').onclick = event => {
event.stopPropagation();
event.preventDefault();
history.back();
};
});
}
getOwnTab().then(tab => {
const ownTabId = tab.id;
// use browser history back when 'back to manage' is clicked
if (sessionStorageHash('manageStylesHistory').value[ownTabId] === location.href) {
onDOMready().then(() => {
$('#cancel-button').onclick = event => {
event.stopPropagation();
event.preventDefault();
history.back();
};
});
// no windows on android
if (!chrome.windows) {
return;
}
const tabs = await browser.tabs.query({currentWindow: true});
const windowId = tabs[0].windowId;
if (prefs.get('openEditInWindow')) {
if (
/true/.test(sessionStorage.saveSizeOnClose) &&
'left' in prefs.get('windowPosition', {}) &&
!isWindowMaximized()
) {
// window was reopened via Ctrl-Shift-T etc.
chrome.windows.update(windowId, prefs.get('windowPosition'));
}
// no windows on android
if (!chrome.windows) {
if (tabs.length === 1 && window.history.length === 1) {
chrome.windows.getAll(windows => {
if (windows.length > 1) {
sessionStorageHash('saveSizeOnClose').set(windowId, true);
saveSizeOnClose = true;
}
});
} else {
saveSizeOnClose = sessionStorageHash('saveSizeOnClose').value[windowId];
}
}
chrome.tabs.onAttached.addListener((tabId, info) => {
if (tabId !== ownTabId) {
return;
}
// When an edit page gets attached or detached, remember its state
// so we can do the same to the next one to open.
chrome.tabs.onAttached.addListener((tabId, info) => {
if (tabId !== ownTabId) {
return;
if (info.newPosition !== 0) {
prefs.set('openEditInWindow', false);
return;
}
chrome.windows.get(info.newWindowId, {populate: true}, win => {
// If there's only one tab in this window, it's been dragged to new window
const openEditInWindow = win.tabs.length === 1;
if (openEditInWindow && FIREFOX) {
// FF-only because Chrome retardedly resets the size during dragging
chrome.windows.update(info.newWindowId, prefs.get('windowPosition'));
}
if (info.newPosition !== 0) {
prefs.set('openEditInWindow', false);
return;
}
chrome.windows.get(info.newWindowId, {populate: true}, win => {
// If there's only one tab in this window, it's been dragged to new window
const openEditInWindow = win.tabs.length === 1;
if (openEditInWindow && FIREFOX) {
// FF-only because Chrome retardedly resets the size during dragging
chrome.windows.update(info.newWindowId, prefs.get('windowPosition'));
}
prefs.set('openEditInWindow', openEditInWindow);
});
prefs.set('openEditInWindow', openEditInWindow);
});
});
}
@ -507,10 +502,6 @@ function rememberWindowSize() {
}
}
prefs.subscribe(['editor.linter'], (key, value) => {
$('body').classList.toggle('linter-disabled', value === '');
});
function fixedHeader() {
const scrollPoint = $('#header').clientHeight - 40;
const linterEnabled = prefs.get('editor.linter') !== '';

View File

@ -1,6 +1,11 @@
/* global prefs */
/* global workerUtil */
'use strict';
/* exported editorWorker */
const editorWorker = workerUtil.createWorker({
url: '/edit/editor-worker.js'
});
/* exported linter */
const linter = (() => {
const lintingUpdatedListeners = [];
@ -59,8 +64,3 @@ const linter = (() => {
.then(results => [].concat(...results.filter(Boolean)));
}
})();
// FIXME: this should be put inside edit.js
prefs.subscribe(['editor.linter'], () => {
linter.run();
});

View File

@ -71,7 +71,7 @@ function createSectionsEditor(editorBase) {
});
function fitToContent(section) {
const {cm, cm: {display: {wrapper, sizer}}} = section;
const {el, cm, cm: {display: {wrapper, sizer}}} = section;
if (cm.display.renderedView) {
resize();
} else {
@ -84,7 +84,7 @@ function createSectionsEditor(editorBase) {
return;
}
if (headerOffset == null) {
headerOffset = wrapper.getBoundingClientRect().top;
headerOffset = el.getBoundingClientRect().top;
}
contentHeight += 9; // border & resize grip
cm.off('update', resize);
@ -95,16 +95,15 @@ function createSectionsEditor(editorBase) {
}
function fitToAvailableSpace() {
const available =
Math.floor(container.offsetHeight - sections.reduce((h, s) => h + s.el.offsetHeight, 0)) ||
window.innerHeight - container.offsetHeight;
if (available <= 0) {
return;
const ch = container.offsetHeight;
let available = ch - sections[sections.length - 1].el.getBoundingClientRect().bottom + headerOffset;
if (available <= 1) available = window.innerHeight - ch - headerOffset;
const delta = Math.floor(available / sections.length);
if (delta > 1) {
sections.forEach(({cm}) => {
cm.setSize(null, cm.display.wrapper.offsetHeight + delta);
});
}
const cmHeights = sections.map(s => s.cm.getWrapperElement().offsetHeight);
sections.forEach((section, i) => {
section.cm.setSize(null, cmHeights[i] + Math.floor(available / sections.length));
});
}
function genId() {