logo elektroda
logo elektroda
X
logo elektroda

Jak zmniejszyłem rozmiar mojej strony konfiguracyjnej IoT 11 razy, używając Javascript zamiast HTML

p.kaczmarek2  40 3585 Fajne? (+7)
📢 Słuchaj (AI):
Fragment kodu JavaScript generujący elementy rozwijane.
Poniżej pokażę jak zredukowałem rozmiar strony HTML z konfiguracją pinów urządzenia IoT z około 90kB do zaledwie 8kB dzięki zamianie statycznego HTML na skrypt JS, który go generuje. Użyję mojego projektu OpenBeken jako przykładu, ale ogólny pomysł pokazany tutaj można łatwo zastosować do dowolnego innego środowiska tworzącego strony HTML z kodu C (lub podobnego). Ten temat zakłada, że użytkownik zna podstawy C, HTML i Javascript...

W tym temacie odnoszę się do strony konfiguracyjnej OBK, która pozwala ustawić role GPIO na listach rozwijanych:
Konfiguracja pinów urządzenia IoT w OpenBK7231 Zrzut ekranu strony konfiguracyjnej GPIO w projekcie OpenBeken
Wcześniej rozmiar tej strony przekraczał 90 000 bajtów:
Zrzut ekranu edytora tekstu z wyświetlonym fragmentem kodu HTML, wskazujący na długość pliku wynoszącą 92 698 bajtów oraz liczbę linii równą 2.
Powodowało to powolne ładowanie na wielu platformach.
Po zmianie rozmiar wynosi teraz:
Zrzut ekranu wyświetlający fragment kodu w edytorze tekstowym.
Zacznijmy od sprawdzenia, dlaczego rozmiar strony jest tak duży w przypadku tej konfiguracji. Możemy po prostu wyświetlić źródło strony w przeglądarce:
Fragment kodu HTML z konfiguracją pinów urządzenia IoT
Teraz wyraźnie widać, że dla każdego z rozwijanych menu lista opcji jest powtarzana. Jest to bardzo proste, ale też nieoptymalne. Powtarza się to dla każdego GPIO, więc jeśli na przykładowej platformie jest 30 dostępnych pinów IO, to powtarza się to 30 razy!
Krótkie spojrzenie na kod OBK potwierdza, że tak właśnie się dzieje:
Kod: C / C++
Zaloguj się, aby zobaczyć kod

Poniższe jest wykonywane dla każdego możliwego pinu! Musimy to zoptymalizować...

Aby to zoptymalizować, użyjemy Javascript. W JS utworzymy jedną, globalną tablicę ról pinów , a następnie dla każdego dropdown wstawimy do niej elementy za pomocą skryptu. Są jednak dwa problemy do rozwiązania:
- musimy również ustawić aktywny wybrany element, aby ludzie nie tracili ustawień przy każdym odświeżeniu i zapisaniu
- musimy wykluczyć role PWM dla pinów innych niż PWM.
Zignorujmy na razie kwestię PWM. Zacznijmy od następującego szkicu:
Kod: Javascript
Zaloguj się, aby zobaczyć kod

Tablica r jest listą nazw ról elementów. W mojej funkcji f, iteruję nazwy ról pinezek i dodaję je do listy rozwijanej d. Tam również sprawdzam wybraną rolę, której indeks musi być podany podczas wywoływania funkcji f.
Indeks wybranej roli można łatwo pobrać z kodu OBK, ale dla odniesienia do obiektu select DOM musiałem dalej modyfikować kod. Zdecydowałem się na pobieranie go przez ID:

Kod: Javascript
Zaloguj się, aby zobaczyć kod

Teraz, gdy mamy już podstawy, zastanówmy się również, jak możemy pominąć role PWM dla pinów innych niż PWM. OBK już wie, które piny obsługują PWM, więc możemy po prostu przekazać dodatkowy argument, a następnie sprawdzić, czy rola pinu zaczyna się od PWM, chociaż w przyszłości mogę po prostu zakodować indeks roli (będzie krótszy o kilka znaków). Zauważ, że zmienna "b" jest dodatkowym argumentem, który dodałem do funkcji:
Kod: Javascript
Zaloguj się, aby zobaczyć kod

Ostatecznie zmodyfikowałem mój kod C, aby po prostu wydrukować następujący skrypt podczas generowania strony OBK, oczywiście zastępując również fałszywe dane rzeczywistymi rolami pinów OBK:
Zrzut ekranu z kodem C generującym skrypt Javascript dla konfiguracji GPIO w projekcie OpenBeken.
To działa i rozmiar strony zmniejszył się 9-krotnie, ale czy to wszystko co możemy zrobić?

Krótki rzut oka na kod HTML pokazuje, że wciąż jest miejsce na poprawę:
Zrzut ekranu z kodem HTML strony konfiguracyjnej urządzenia IoT z kodem C.
Generowanie div indeksu kanału może być również proceduralne. Oto upiększona wersja nowego kodu, który również generuje div:
Kod: Javascript
Zaloguj się, aby zobaczyć kod

Tworzenie div można by faktycznie wydzielić do innej funkcji, tak jak jest to robione dwa razy, ale nie sądzę, że dałoby mi to znaczną liczbę znaków.
Więc teraz rozmiar strony spadł do 8kB:
Zrzut ekranu z edytora tekstu pokazujący fragment kodu JavaScript.
Podsumowując - generowanie kodu HTML z C jest bardzo proste, ale też niezbyt optymalne. W przypadku powtarzających się danych, takich jak dropdowny z tymi samymi opcjami, wydajniej jest wygenerować Javascript, który później wygeneruje elementy HTML. Dla mnie dało to poprawę o ponad jeden rząd wielkości pod względem zajmowanego miejsca. Naprawiło to również problemy z OBK, miejmy nadzieję...
Tę samą zasadę można zastosować również do innych projektów IoT, te same problemy mogą wystąpić na ESP i mogą być również rozwiązane w ESP poprzez generowanie HTML + JS zamiast czystego HTML, więc mam nadzieję, że każdy się czegoś nauczył.
Moją próbkę można oczywiście jeszcze ulepszyć, również za pomocą skryptów kompresujących Javascript, ale myślę, że optymalizacja, którą udało mi się uzyskać do tej pory, jest wystarczająca dla naszego projektu.

Przy okazji, jeśli czyta to jakiś użytkownik OBK, proszę sprawdź to i daj mi znać. Czy możesz sprawdzić, jak działa Twoja strona pinów (szczególnie w Firefoksie), a następnie zaktualizować do wersji testowej:
https://github.com/openshwprojects/OpenBK7231T_App/pull/1215
czy strona ładuje się teraz szybciej? Czy lepiej? @divadiow @max4elektroda @dedamraz @miegapele ? Czy możesz przetestować to na wielu platformach OBK?
UWAGA: Obk zapewnia również ustawienie pinów w aplikacji internetowej, więc poniższa strona nie jest kluczowa, ale nadal dobrze jest mieć ją dobrze działającą.

O autorze
p.kaczmarek2
Inżynier programista z wieloletnim doświadczeniem embedded i full stack developer. Specjalizuje się w: embedded, Full-Stack Developer p.kaczmarek2 napisał 14408 postów o ocenie 12345 , pomógł 650 razy. Jest z nami od 2014 roku.

Komentarze

DeDaMrAz 11 Maj 2024 18:01

Miałem jeden konkretny moduł N, który całkowicie zawieszał się, gdy przechodziłem do pinów konfiguracyjnych, to rozwiązało ten problem! Przed: https://obrazki.elektroda.pl/7154115700_1715443251_thumb.jpg... [Czytaj dalej]

max4elektroda 11 Maj 2024 19:03

Działa tutaj na moim LN882H, strona ładuje się szybko (ale szczerze mówiąc, nie pamiętam, jak było wcześniej) Po szybkim spojrzeniu możesz nawet zaoszczędzić trochę więcej bajtów. Widzę kilka białych... [Czytaj dalej]

p.kaczmarek2 11 Maj 2024 19:19

Właściwie mam LN882H działający w tej chwili ze starszą wersją. Wygląda na to, że stara wersja również działa bardzo dobrze. Nie ma zauważalnego spowolnienia w starszej wersji. Testowałem zarówno Chrome,... [Czytaj dalej]

max4elektroda 11 Maj 2024 19:29

Naprawdę dobry pomysł i ogromna poprawa! Z ciekawości: Nie spodziewam się zbyt dużej poprawy rozmiaru obrazu? Chodzi mi o to, że było dużo kodu HTML, ale większość była tworzona w pętlach, IIRC. [Czytaj dalej]

p.kaczmarek2 11 Maj 2024 20:21

Nie sprawdzałem rozmiaru pamięci flash przed zmianą (główny system wydań wydaje się mieć obecnie pewne problemy), ale powiedziałbym, że zmiana rozmiaru pamięci flash jest bardzo, bardzo mała. Należy pamiętać,... [Czytaj dalej]

max4elektroda 11 Maj 2024 20:53

Mogę zasugerować małe "ulepszenie" (to kwestia "stylu" vs "rozmiaru"): Jeśli zmienisz function f(alias, id, c, b, ch1, ch2) { let f = document.getElementById("x"); ... [Czytaj dalej]

p.kaczmarek2 11 Maj 2024 21:06

To dobra zmiana, możemy ją dodać, nie ma problemu. Pytanie tylko, czy nie możemy po prostu użyć jednego z istniejących stylów? A może proponowane rozwiązanie jest najkrótsze? [Czytaj dalej]

max4elektroda 11 Maj 2024 21:49

Szczerze mówiąc byłem zbyt leniwy, aby spróbować zagłębić się w style, być może możliwe byłoby ponowne użycie innego, ale ponieważ potrzebowalibyśmy klasy, prawdopodobnie nie byłoby to dużo krótsze... ... [Czytaj dalej]

p.kaczmarek2 11 Maj 2024 22:13

Pole drugiego kanału jest obecnie wyświetlane tylko wtedy, gdy rola pinu je obsługuje. Na przykład przycisk może mieć dwa powiązane kanały - jeden dla pojedynczego kliknięcia, drugi dla podwójnego kliknięcia.... [Czytaj dalej]

divadiow 11 Maj 2024 22:15

Czy byłoby możliwe, aby drugie pole kanału ujawniało się natychmiast po wybraniu obsługiwanego urządzenia, zamiast konieczności zapisywania w celu ujawnienia drugiego pola, a następnie ponownego zapisywania... [Czytaj dalej]

p.kaczmarek2 12 Maj 2024 00:00

Oczywiście, ale wymagałoby to przechowywania drugiej tablicy z liczbą kanałów, których wymaga dana rola pinu, a następnie przechwytywania zdarzenia onChange listy rozwijanej, aby można było tam zmienić... [Czytaj dalej]

divadiow 12 Maj 2024 16:02

Nie mogę powiedzieć, że naprawdę zauważyłem spowolnienie, ale wszystkie są szybkie, a strona ładuje się dobrze. chrom. https://obrazki.elektroda.pl/3885064200_1715521417_thumb.jpg https://obrazki.elektroda.pl/5707795900_1715521449_thumb.jpg... [Czytaj dalej]

max4elektroda 12 Maj 2024 18:47

Próbowałem to zaimplementować w PR #1228 Tylko jako pierwszy pomysł, który wpadł mi do głowy podczas tej pracy: W tej chwili mamy właściwości roli IO w kilku miejscach: - mamy enum "main" ioRole_e... [Czytaj dalej]

divadiow 12 Maj 2024 21:26

Dobra robota! [Czytaj dalej]

p.kaczmarek2 13 Maj 2024 14:00

Bardzo dobrze, Za chwilę to scalę. Kilka rzeczy można by tam poprawić (kod mógłby być krótszy), ale nie jest to kluczowe. Ważniejsza była zmiana z 90kB na 8kB. To dobry pomysł i możemy to zrobić... [Czytaj dalej]

max4elektroda 13 Maj 2024 14:17

Tak, skupiłem się na funkcji, a nie na rozmiarze, ale przyjrzę się jeszcze raz, aby skrócić kod, jeśli funkcja zostanie sprawdzona ;-) . Zwykle używam Linuksa, ale jeśli nie jest to zbyt skomplikowane,... [Czytaj dalej]

p.kaczmarek2 13 Maj 2024 14:19

Jeśli używasz Linuksa, to może byłbyś w stanie pomóc nam w przeniesieniu: a) tylko autotestów na Linuksa (powinno być bardzo łatwo) b) całego symulatora na Linuksa (powinno być stosunkowo łatwo, ponieważ... [Czytaj dalej]

max4elektroda 13 Maj 2024 14:29

Chętnie pomogę, ale ostrzegam, że jestem tylko "programistą-hobbystą", a nie poważnym "deweloperem" ;-) . [Czytaj dalej]

p.kaczmarek2 13 Maj 2024 15:52

Cóż, pierwszą rzeczą byłoby skompilowanie symulatora (lub przynajmniej części autotestów, bez okna SDL) na Linuksie. Jak to zrobić? Win_main.c może być faktycznie skompilowany na Linuksie, jak sądzę. [Czytaj dalej]

%}