динамическая загрузка js скриптов
Динамическая загрузка внешних JavaScript-файлов
[Disclaimer: Данная статья была переведена в рамках «Конкурса на лучший перевод статьи» на сервисе Quizful. Ссылка на оригинал находится внизу страницы.]
Попробовал запустить – получил ошибку времени выполнения «Undetermined string constant (неопределенная строковая константа)».
Что, во имя всего святого, это могло бы значить?
Но отыскать ответ на свой вопрос мне удалось только после прочтения JavaScript: The Definitive Guide Дэвида Фланагана. В общем, содержимое тэга тэгом следующим образом: (что и сделано в нижеуказанном фрагменте кода). Экранирование предотвращает нежелательное выполнение JavaScript-строки, содержащей тэг
Метод staticLoadScript() в этом примере должен быть вызван, пока страница загружается (т.к. он использует document.write(), чтобы создать
В отличие от staticLoadScript() из предыдущего примера, метод dhtmlLoadScript() может быть вызван в любой момент выполнения программы, правда, документ должен быть хотя бы частично загружен в браузер. В указанном выше фрагменте, документ гарантированно будет загружен к моменту вызова dhtmlLoadScript(), т.к. вызов происходит в обработчике onload.
Ограничения
Приведенный выше метод dhtmlLoadScript() будет работать только в браузерах, поддерживающих динамическое добавление элементов к странице, используя DOM (Document Object Model). А значит, этот метод не заработает в Netscape версии ниже 6, а также Opera 7 и ниже. Я не считаю, это реальной проблемой, врядли кто-либо в здравом уме будет поддерживать эти давно устаревшие браузеры, по крайней мере, если на это нет чертовски хорошей причины.
Если Вам понравилась статья, проголосуйте за нее
Голосов: 10 Голосовать
Динамическая подгрузка Javascript
Добрый день всему хабрасообществу! Недавно мне выпало разрабатывать огромный веб-проект (точнее доделать), на котором была просто уйма Ajax. Проблема заключалась в том, что все яваскриптовые файлы грузились сразу. Тобиш, если б мне захотелось добавить ещё функционал — то это новый js-файл, который следует грузить пользователю (хотя возможно ему этот функционал может даже не потребоватся). Недавно прочтенная статья «Динамическая подгрузка модулей на Javascript» дала мне понять, что js можно подгружать динамически, поэтому я стал искать метод решения.
И вот какое решения нашел. Поскольку переписывать проект у меня не было не времени не желания, мне оставалось только найти быстрый способ как осуществить быструю подгрузку js-файлов по требованию. В Интернете я случайно наткнулся на такую библиотеку как JSAN (JavaScript Archive Network, не путайте с JSON). Разработчики данной библиотеки пытаются сделать аналог CPAN только для JavaScript.
Вот ссылка на источник.
Там все красиво описывается, но я объясню самое основное. JSAN предоставляет средства для динамической подгрузки кода, используя XMLHttpRequest к серверу. Библиотека содержится в одном js-файле, который и требуется подключить к странице. Дальше — проще. К примеру:
JSAN.require(‘js.creating’);
var creating = new js.creating();
Cледующий ниже вызов JSAN.require постарается загрузить js/creating.js, пробуя искать во всех источниках, указанных в JSAN include_path, который по умолчанию равен [‘.’, ‘lib’]. И все!
Единственным требованием является, чтобы все модули находились внутри своего namespace, так для примера, приведенного выше, начало s/creating.js будет выглядеть примерно так:
if(js == undefined) var js = <>;
if(js.creating == undefined) js.creating = <>;
Но я бы отнес это скорее к плюсу нежели к минусу, т.к это заставляет разработчика изолировать свои библиотеки от внешнего мира, тем самым сводя проблему конфликта имен практически к нулю. Кстати, помимо JSAN.require, существует также метод JSAN.use, который позволяет экспортировать только необходимый функционал из модуля, что как раз мне потребовалось. Первое что пришлось сделать, так это преобразовать вид старых функций с
поскольку только так функции подгружались. Дальше я просто добавил в шаблонах простую замену. Например есть функция itemsCreating в файле js/creating.js. По клику на обьект на странице она должна выполнятсяю Для этого вместо
ЗЫ Моя первая статья на Хабре, поэтому критика не мало важна.
Форум
Справочник
JavaScript динамическое подключение скриптов. Как динамически подключить javascript?
Динамическая подрузка javascript скриптов. Подключение скриптов на javascript.
Чтобы динамически подключать скрипты, нужно заюзать библиотеку scriptjava, которая упрощает программирование на javascript и избавляет от лишних проблем.
На чистом яваскрипте реализовать динамическое подключение скриптов можно, но это вызовет кучу проблем.
Например если нам потребуется подключить скрипт и запустить из него функцию, то произойдет ошибка потому что мы не знаем сколько по времени будет грузится скрипт, а пока он грузится скрипт вызовет функцию которая еще не загрузилась что приведет к ошибке.
ScriptJava работает во всех браузерах и выполняет функции только после полной загрузки скриптов избавляя нас от лишней мароки и ошибок.
Подключите к своему сайту перед тегом ScriptJava фреймворк, добавив вот такой код:
Далее пишем функцию динамического подключения кода:
В любом месте сайта, когда нужно динамически подключить скрипт нужно вызвать функцию
Но что делать когда нужно динамически подключать скрипты сразу после загрузки сайта?
Ведь опять не зная когда загрузится полностью сайт мы не можем динамически подключать внешний скрипт.
На самом деле определять загрузку сайта может scriptjava, но не то как это определяет метод onload, а совсем по другому.
Сайт может еще не полностью загрузится, а скриптджава сама определит когда можно выполнять код.
Дописываю вышепоказанный код, для его запуска сразу после загрузки сайта:
Выше написанный код нельзя помещать в функцию.
Он может запускаться только во время загрузки сайта т.е. как есть.
Динамическая загрузка скриптов в JavaScript
При создании сайтов, а именно при верстке часто возникают такие ситуации, когда нужно динамически загрузить тот или иной модуль для того, чтобы получить доступ к функционалу предоставляемому данным модулем. Для таких случаев может использоваться механизм динамической загрузки JavaScript файлов.
Скрипт очень простой:
// здесь создаем объект-обертку, дабы не загрязнять глобальное пространство имен
var loader = loader || <>
loader.importJS = function( uri ) <
// создаем новый тег script
let script = document.createElement(‘script’);
// получаем ссылку на тег head документа
let head = document.getElementsByTagName(‘head’)[0];
// устанавливаем тип и uri
script.type = ‘text/javascript’;
script.src = uri;
// загружаем скрипт в тег head
head.appendChild(script);
>
loader.importJS(‘https://cdnjs.cloudflare.com/ajax/libs/timeago.js/3.0.2/timeago.js’)
// timeago().format(new Date())
Таким образом, можно просто осуществить динамическую загрузку JavaScript библиотек.
Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!
Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.
Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления
Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.
Порекомендуйте эту статью друзьям:
Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):
Комментарии ( 0 ):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.
Copyright © 2010-2021 Русаков Михаил Юрьевич. Все права защищены.
Современная загрузка скриптов
Передать нужный код для каждого браузера – непростая задача.
В этой статье рассмотрим несколько вариантов, как эту задачу можно решить.
Передача современного кода современным браузером может очень сильно повысить производительность. Ваши JavaScript-пакеты смогут содержать более компактный или оптимизированный современный синтаксис и поддерживать старые браузеры.
Среди инструментов для разработчиков доминирует паттерн module/nomodule декларативной загрузки современного или legacy-кода, который предоставляет браузерам источники и позволяет решать, какие из них использовать:
К сожалению, не всё так просто. Показанный выше подход на основе HTML инициирует перезагрузку скриптов в Edge и Safari.
Что можно сделать?
В зависимости от браузера нам нужно доставить один из вариантов скомпилированных скриптов, но пара старых браузеров не поддерживают весь необходимый для этого синтаксис.
Способ первый: динамическая загрузка
Но при таком подходе необходимо дождаться выполнения «лакмусового» модульного скрипта, прежде чем внедрять правильный скрипт. Это происходит, потому что всегда работает асинхронно. Но есть способ получше!
Можно реализовать независимый вариант, проверяя, поддерживается ли nomodule в браузере. Это означает, что мы будем рассматривать браузеры вроде Safari 10.1 как устаревшие, даже если они поддерживают модули. Но это может быть к лучшему. Вот соответствующий код:
Это можно быстро превратить в функцию, которая загружает современный или legacy-код, а также обеспечивает асинхронность их загрузки:
Какой же здесь компромисс?
Если для вас эта методика подходит, можете уменьшить размер HTML-документа, в который вы встраиваете эти скрипты. Если ваша полезная HTML-нагрузка маленькая, как экран заставки или код загрузки клиентского приложения, то отказ от сканера предварительной загрузки вряд ли повлияет на производительность. А если вы отрисовываете на сервере много важного HTML, чтобы отправить в браузеры, тогда сканер предварительной загрузки окажется вам полезен и описанный подход будет для вас не лучшим вариантом.
Вот как это решение может выглядеть в эксплуатации:
Способ второй: отслеживание User Agent
У меня нет подходящего примера кода, поскольку отслеживание User Agent — задача нетривиальная. Но зато вы можете почитать прекрасную статью в Smashing Magazine.
По сути всё начинается с того же в HTML для всех браузеров. Когда запрашивается bundle.js, сервер парсит строку User Agent запрашивающего браузера и выбирает, какой JavaScript возвращать — современный или legacy, в зависимости от того, как был распознан браузер.
Для сайтов, которые уже генерируют HTML на сервере в ответ на каждый запрос, это может быть эффективным переходом к загрузке современных скриптов.
Способ третий: штрафуем старые браузеры
Негативный эффект паттерна module/nomodule виден в старых версиях Chrome, Firefox и Safari — их количество очень невелико, поскольку браузеры обновляются автоматически. С Edge 16-18 ситуация иная, но есть надежда: новые версии Edge будут использовать движок отрисовки на основе Chromium, который не имеет таких проблем.
Для некоторых приложений это было бы идеальным компромиссом: загружать современную версию кода в 90 % браузеров, а в старые — отдавать legacy-код. Нагрузка в старых браузерах повысится.
К слову, ни один из User Agent’ов, для которых такая перезагрузка является проблемой, не занимают значимую долю мобильного рынка. Так что источником всех этих лишних байтов вряд ли будут мобильные устройства или устройства со слабым процессором.
Если вы создаёте сайт, к которому обращаются в основном мобильные или свежие браузеры, то для большинства этих пользователей подойдёт простейший вид паттерна module/nomodule. Только удостоверьтесь, что вы добавили фикс Safari 10.1, если к вам заходят более старые iOS-устройства.
Способ четвёртый: применяйте условия использования пакетов
Хорошим решением будет использовать nomodule для условной загрузки пакетов с кодом, который не нужен в современных браузерах, например, с полифиллами. При таком подходе в худшем случае полифиллы будут загружены или даже выполнены (в Safari 10.1), но эффект от этого будет ограничен «переполифиллингом». Учитывая, что сегодня преобладает подход с загрузкой и выполнением полифиллов во всех браузерах, это может быть достойным улучшением.
Можно сконфигурировать Angular CLI для использования этого подхода с полифиллами, как продемонстрировал Минко Гечев. Узнав об этом подходе, я понял, что можно включить автоматическую инъекцию полифиллов в preact-cli — этот PR демонстрирует, насколько легко можно внедрить эту методику.
Так что же выбрать?
Если вы создаёте сайт, который отрисовывается на сервере, и можете позволить себе кэширование, то вам может подойти второй способ.
Если вы используете универсальный рендеринг, выигрыш в производительности, предлагаемый сканированием до загрузки, может оказаться очень важным. Поэтому обратите внимание на третий или четвёртый способы. Выбирайте то, что подходит для вашей архитектуры.
Лично я выбираю, ориентируясь на длительность парсинга на мобильных устройствах, а не на стоимость загрузки в десктопных версиях. Мобильные пользователи воспринимают парсинг и расходы на передачу данных как фактические расходы (расход заряда батареи и плату за передачу данных), тогда как пользователи десктопа не имеют таких ограничений. Также я исхожу из оптимизации под 90% пользователей — основная аудитория моих проектов пользуется современными и/или мобильными браузерами.
Что почитать
Хотите изучить эту тему подробнее? Можете начать отсюда: