Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: asynchroniczne ładowanie plików
Forum PHP.pl > Forum > Po stronie przeglądarki > JavaScript
gitbejbe
Stosuje ktoś z was jakieś własne implementacje dynamicznego ładowania bibliotek dla szablonu ?

Zawsze wszystkie biblioteki js zwyczajnie dodawałem na koniec pliku, ale ostatnio tknęło mnie aby w dokumencie był tylko jeden mały skrypt, który załaduje mi wszystko w locie. Zanim zacząłem pisać, pierwsza myśl jaka mnie naszła to "ale po co?". Skoro dodaje wszystkie biblioteki na końcu pliku, to ta cała asynchroniczność to tylko bajer - a być może i wada o której jeszcze nie wiem. Nie dawało mi to spokoju no i napisałem idealną dla mnie implementacje. Moje wnioski są takie:

(wrażenia bez włączonego cachu)

- (to raczej oczywisty wniosek) readyDom jest szybsze. Po załadowaniu treści i CSS'ów brak lagów. Strona nie czeka na wykonanie wszystkich skryptów po kolei przez co nie zacina jej na tym etapie.
- Zdarza się że przy zwykłym wczytywaniu, treść strony pod koniec ładowania skryptów przeskakuje. Przy wczytywaniu skryptów w locie takiego efektu nie ma,
- dużą ilość bibliotek można załadować i wykonać prawie że na raz.
- użytkowo nie odczuwa się w żaden sposób tego że biblioteki się "doczytywane" niezależnie od ilości, tzn cały proces trwa maksymalnie tyle co najdłużej(największa) pobierana biblioteka.
- W firebugu Total Load wygląda podobnie, nie zmienia to faktu że strona jest gotowa szybciej. 3 laików których poprosiłem o wskazanie która wersja się szybciej i "ładniej" wczytuje, za każdym razem padło na async.
- jako bajer można dodać jakiegoś loadera który przykryje całą stronę i zniknie gdy wszystko będzie gotowe - choć i tak trzeba by było go specjalnie przedłużyć bo za szybko by znikał ;p
- ogólne wrażenia na +

Pomińmy fakt zależności pomiędzy skryptami js, bo to nie jest dla mnie problem.

Chcę to rozwiązanie wprowadzić komercyjnie w swoim szablonie na themeforesta z uwagi na dużą ilość bibliotek js. Sam dedykowany skrypt "uruchamiający" cały szablon zbudowany jest z kilku modułów podzielonych na kilka plików aby łatwiej to było ogarnąć. Wszystko co się da łącze w duże pliki przez postprocesory lecz i tak odbija się to na ładowaniu strony - wierze że zawsze można zrobić coś wydajniej. Być może ktoś z was miał podobną rozkmine ? Wg mnie asynchroniczność naprawdę daje rade, choć nie mam wiedzy czy np dla jakiś FW typu angular to będzie jakiś problem do zaimplementowania - bo z tym też muszę się liczyć. Ważna jest też strona użytkowa. Dla z wizualizowania idei, mój cały skrypt js na stronie przykładowo wygląda tylko tak:

  1. //bardzo mały i głupi skrypt na końcu strony, ma za zadanie tylko załadować niezbędne biblioteki podane w kodzie funkcji + ewentualne te które mu wskaże przy inicjacj.
  2. <script type="text/javascript" src="theme.js"> </script>
  3.  
  4. theme({
  5. // ładowanie ewentualnych dodatkowych bibliotek
  6. load: ["costam.js", ... ],
  7. // inne ewentualne opcje
  8. })
  9. .done(function(){
  10. //cała strona obsłużona, wszystkie biblioteki załadowane. Miejsce na swoje skrypty
  11. });


edit: nie mam podglądu, localhost
by_ikar
Nie jest to jakieś odkrycie, że javascript działa jednowątkowo i trzeba robić wszystko żeby jedna akcja nie blokowała drugiej. Dlatego od jakiegoś czasu (~2010 IE 10+) do tagu script można dodać atrybut async który nie blokuje ładowania skryptów. Żeby dodatkowo jeszcze ustawić im odpowiednią kolejność, postał atrybut defer, dlatego że asynchroniczne ładowanie nie ma ustalonej kolejności i wykonuje się pierwszy który się pobierze.

Rozbijanie na wiele małych plików jest czymś od czego się ucieka. Przeglądarki mają przeważnie 4-5 jednoczesnych połączeń do jednego hosta (async trochę zmienia to zachowanie), dlatego o wiele lepiej gdybyś całość umiejętnie złączył w jeden plik, zamiast bawić się w wynajdowanie koła na nowo. Dodatkowo, jak już implementujesz jakieś obietnico-podobne metody, to zrób to zgodnie z tym jak to być powinno zrobione, zamiast tworzyć jquery-podobne fanaberie.

Podejście z ładowaniem wielu plików ma pewne zalety ale i wady:
- w tej swojej wersji nie obsługujesz przypadku że coś się nie załaduje (nie jest kwestią czy coś jebnie, tylko kiedy)
- kiedy 1 plik na 10 się nie załaduje - co zrobić w takim przypadku?
- wciąż jesteś ograniczony do limitu połączeń przeglądarki
- najpierw musisz załadować jeden plik i go zinterpretować, żeby móc załadować resztę

Zainteresuj się jakimś webpackiem, czy podobnymi, które ci te twoje wszystkie skrypty połączą w jeden plik ewentualnie będą miały już swoje loadery. W światku javascript problemem jest to, że każdego dnia powstaje kilka frameworków. Zamiast szybkiego rozwoju jednego-kilku, jest powolny rozwój kilkuset rozwiązań, z czego większość jest nie udokumentowana/nie przetestowana.
gitbejbe
Dzięki za odpowiedź

w tym temacie bardziej chodzi mi o sam fakt czy wg was warto wczytywać biblioteki w locie. Kwestia wykonania loadera nie jest dla mnie tutaj istotna, ale sprostuje:

- biblioteki ładowane są tylko lokalnie więc co może się nie wczytać?. Mam zaimplementowaną obsługę wyjątków choć to tak naprawdę bardziej bajer/pomoc w debag'u niż must have - nie podałem tego w przykładzie bo nie chodzi mi w tym temacie o kwestie techniczne samego loadera. Jeśli ktoś jednak chciałby za pomocą loadera odnieść się do zewnętrznych źródeł to proszę bardzo. Loader wtedy ma dodatkowy atut, bo można go sobie faktycznie oskryptować pod takie przypadki - czego nie można powiedzieć o zwykłej deklaracji dokumentów w szablonie.
- co do promise, pierwotnie oparłem wszystko na czystym js'sie zgodnie ze sztuką, ale jak się okazało jest problem z kompatybilnością ze starszymi przeglądarkami. Projekt oparty jest tak czy siak na jquery z uwagi na mase bibliotek bazujących właśnie na nim, tak więc skorzystałem z $.deferred i jest bajka.
- limitu nie przeskoczymy choć po moich testach jest on dla mnie prawie niezauważalny
viking
Takich bibliotek jest multum, zaczynając od requirejs. Korzystałem dawno temu i przez wiele lat, od pewnego czasu głównie webpack i zdecydowanie wolę takie podejście (transpilacja ES2015/TS/whatever). Tak piszesz, jakbyś chciał akceptacji tego rozwiązania. Co tu można więcej dodać? Nie działa w starszych? Pierwsze z brzegu https://github.com/taylorhakes/promise-polyfill
gitbejbe
Nie ważne jak wygląda moja implementacja - to był tylko przykład, tym bardziej nie interesują mnie żadne requirejs/webpack itd. Chodzi mi tylko o to czy warto jest stosować podejście asynchronicznego ładowania bibliotek skoro tak czy siak deklaruje je na samym końcu dokumentu.
viking
http://contentloaded.com/dom-ready/
by_ikar
Cytat(gitbejbe @ 9.01.2017, 18:38:01 ) *
Nie ważne jak wygląda moja implementacja - to był tylko przykład, tym bardziej nie interesują mnie żadne requirejs/webpack itd. Chodzi mi tylko o to czy warto jest stosować podejście asynchronicznego ładowania bibliotek skoro tak czy siak deklaruje je na samym końcu dokumentu.


Odpowiedź na twoje podstawowe pytanie zawarłem w pierwszym zdaniu:

Cytat
Nie jest to jakieś odkrycie, że javascript działa jednowątkowo i trzeba robić wszystko żeby jedna akcja nie blokowała drugiej.


Twoje podejście jest dobre, ale rozwiązanie jest średnie. Średnie dlatego że wynajdujesz koło na nowo, tworzysz N-te nieudokumentowane rozwiązanie, bez testów (jednostkowych/funkcjonalnych). Zamiast skorzystać z doświadczeń dziesiątków ludzi którzy pracują nad jakimś rozwiązaniem, które jest swego rodzaju nawet standardowym sposobem na ładowanie zależności, to tworzysz swoje rozwiązanie, nie kompatybilne z niczym.

Dlatego powstało określenie "programista wordpressa"..
gitbejbe
Dziękuje wszystkim za odpowiedzi, dowiedziałem się tego co chciałem. Temat do zamknięcia.

by_ikar

dlatego grubo się zastanawiam czy deklarować biblioteki tak jak to robią wszyscy - zwyczajnie na końcu strony i mieć gdzieś że strona się wolniej wykona, czy jednak wyjść przed szereg i zabłysnąć opcjonalnym rozwiązaniem które poprawi wydajność. Jak byłby to projekt dla mnie zapewne pokusiłbym się o gotowce, ale sprzedając szablon dla ludu nie można oczekiwać, że każdy będzie zadowolony że projekt oparty jest na np requirejs - dlatego też niektórzy sprzedają swoje szablony w kilku wariantach. Narazie muszę wydać wersje bazową i musi być debilready. Nie mniej jednak mam wewnętrzny głos aby dodać tego prostego loadera chociażby z uwagi na cele marketingowe bo nikt takiego czegoś nie oferuje. Co by nie było robi wrażenie fakt braku masy linków w kodzie, włącza się ciekawość no i można się pochwalić jakimś hasłem ze szablon jest "super wydajny", intuicyjny i nie narzuca gotowych fw. Loadera napisałem tak aby była to tylko opcja, jak chcesz stosuj, jak nie to wrzuć sobie wszystko na sztywno i też będzie działać. Dobra ale żeby nie zostać znowu posądzonym o próbę wymuszenia akceptacji mojego pomysłu, to nie oczekuje odpowiedzi smile.gif Tak więc idę podejmować decyzje...
Comandeer
Cytat
Rozbijanie na wiele małych plików jest czymś od czego się ucieka.

Mamy rok 2017 i naprawdę warto zacząć myśleć w kategoriach HTTP/2 first wink.gif A tutaj wiele małych plików przy sposobie, w jaki działa ten protokół (+ przy możliwości server pusha) jest wręcz best practice.

Co do wczytywania skryptów: na chwilę obecną najlepszą praktyką jest umieszczenia skryptów na końcu body, niemniej warto się zastanowić nad wrzucaniem skryptów w head, przed style i dodawaniem im atrybutu [defer]. Oczywiście przy dodatkowym stosowaniu server pusha skrypty po prostu już będą czekały na wykonanie.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2024 Invision Power Services, Inc.