27.05.2022, 12:19
|
Аспирант
|
|
Регистрация: 18.01.2011
Сообщений: 93
|
|
Автозагрузка криптов и стилей
Всем привет, в некоторых JS библиотеках есть такая фича, как подгрузка скриптов и стилей динамически. Это как бы не новость, но мне вот что интересно: стили в виде
<link rel="stylesheet" href="./assets/css/bootstrap.min.css">
попадают в DOM, в head, это нормально, и так оно реализовано у всех. Со скриптами тоже самое, но, у некоторых библиотек, например Tiny Mce, скрипты в DOM не подгружаются, если наблюдать по консоли в момент запуска плагина видно, как в head прописались стили, а скрипты нет, нигде в теле документа новые теги <script> не прописались. Плюс ко всему, мы их не увидим в web developer tools (information/View Javscript).
Но тем не менее, плагин работает, функции из "невидимо подгруженных" скриптов отрабатывают. Гугление дает только те коды, которые прописывают скрипты в head, а мне интересно как это реализовать без этого. Буду очень благодарен за любую информацию по вопросу!
|
|
27.05.2022, 12:21
|
|
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,228
|
|
Возможно скрипты подключают не в head...
|
|
27.05.2022, 12:28
|
Аспирант
|
|
Регистрация: 18.01.2011
Сообщений: 93
|
|
Сообщение от ksa
|
Возможно скрипты подключают не в head...
|
100% точно нигде не подключаются, если бы они подключились куда угодно в DOM, я бы их в том числе увидел в web developer tools
|
|
27.05.2022, 12:57
|
Профессор
|
|
Регистрация: 07.11.2013
Сообщений: 458
|
|
Volonter,
В DevTools, вкладке Network, всё видно.
|
|
27.05.2022, 13:13
|
Аспирант
|
|
Регистрация: 18.01.2011
Сообщений: 93
|
|
Сообщение от Rise
|
Volonter,
В DevTools, вкладке Network, всё видно.
|
Да, действительно есть, я само собой догадывался, что нельзя нигде не увидеть джаваскрипт, но как они делают, что это не добавляется в DOM то? Я вот чего понять не могу)) плагин запустил, в инспекторе "моргнуло" что стили прописались, а скриптов нет. Механизм подгрузки там асинхронный, но так или иначе все заканчивается банальным body.appendChild(), вот кусок кода библиотеки
const id = dom.uniqueId();
elm = document.createElement('script');
elm.id = id;
elm.type = 'text/javascript';
elm.src = Tools._addCacheSuffix(url);
if (this.settings.referrerPolicy) {
dom.setAttrib(elm, 'referrerpolicy', this.settings.referrerPolicy);
}
elm.onload = done;
elm.onerror = error;
(document.getElementsByTagName('head')[0] || document.body).appendChild(elm);
});
|
|
27.05.2022, 13:39
|
Профессор
|
|
Регистрация: 07.11.2013
Сообщений: 458
|
|
Сообщение от Volonter
|
но как они делают, что это не добавляется в DOM то?
|
Всё добавляется, ты как-то неправильно DOM смотришь, смотри вкладку Elements.
|
|
27.05.2022, 13:48
|
Аспирант
|
|
Регистрация: 18.01.2011
Сообщений: 93
|
|
Сообщение от Rise
|
Всё добавляется, ты как-то неправильно DOM смотришь, смотри вкладку Elements.
|
а как еще - консоль- инспектор
вот ради прикола набросал на коленке,
class ScriptLoader {
load(src) {
const e = document.createElement('script');
e.defer = true;
e.src = src;
document.body.appendChild(e);
}
}
class Test {
constructor(params) {
this.params = typeof params === 'object' ? params : {};
this.url = params.url;
}
init() {
const scriptLoader = new ScriptLoader;
scriptLoader.load(this.url + '/foo.js');
}
}
let test = new Test({
url: '/path/to/script',
})
test.init()
понятно что здесь ничего не загрузится, но на компе все сразу в консоли видно, что подгрузился скрипт.
|
|
27.05.2022, 14:39
|
Профессор
|
|
Регистрация: 07.11.2013
Сообщений: 458
|
|
Volonter,
Ну ты можешь элемент script удалить из DOM, как и любой другой элемент. Например, на событие load, которое вызывается, когда скрипт загружен и выполнен:
e.onload = function() {
e.remove();
};
На работоспособность js это не повлияет.
|
|
27.05.2022, 19:48
|
Аспирант
|
|
Регистрация: 18.01.2011
Сообщений: 93
|
|
Сообщение от Rise
|
e.remove();
|
да, действительно, покопался основательно в их коде - так и есть, просто там remove() немного более завуалированно прописано. Тогда вопрос - нафига и зачем удалять?
|
|
27.05.2022, 22:12
|
Аспирант
|
|
Регистрация: 18.01.2011
Сообщений: 93
|
|
Сообщение от Rise
|
Чтобы освободить память
|
Понял, спасибо! Вот что получилось изобразить
async function manager(params) {
params = typeof params === 'object' ? params : {};
element = params.element;
url = params.url;
loadCss(url, ['icons', 'style', 'dropzone'])
await loadScript(url + '/helper/Helper.js')
let helper = new Helper({ element: element });
document.getElementById(element).insertAdjacentHTML('beforeend', helper.html())
}
function loadCss(url, style) {
let head = document.getElementsByTagName('head')[0]
style.forEach(file => {
let cssLink = document.createElement('link')
cssLink.href = url + '/css/' + file + '.css'
cssLink.type = 'text/css'
cssLink.rel = 'stylesheet'
head.appendChild(cssLink);
});
}
function loadScript(url) {
return new Promise((resolve, reject) => {
let elm;
const cleanup = () => {
elm.remove()
if (elm) {
elm.onerror = elm.onload = elm = null;
}
};
const done = () => {
cleanup();
resolve();
};
const error = () => {
cleanup();
reject('Failed to load script: ' + url);
};
elm = document.createElement('script');
elm.type = 'text/javascript';
elm.src = url;
elm.onload = done;
elm.onerror = error;
(document.getElementsByTagName('head')[0] || document.body).appendChild(elm);
})
}
Вопрос к гуру - стоит ли стили тоже асинхронно подключать?
|
|
|
|