Unikanie kolizji identyfikatorów między zobfuskowanymi plikami
Gdy kilka plików zobfuskowanych przez VM trafia do tego samego bundle'a, mogą one zadeklarować ten sam identyfikator najwyższego poziomu i wywołać awarię strony już na etapie parsowania. Wyjaśniamy, dlaczego tak się dzieje i jak temu zaradzić.
Objaw
Build przebiega bez problemów, ale przeglądarka zgłasza błąd na etapie parsowania, zanim aplikacja się uruchomi:
Aby sprawdzić, ile chunków deklaruje nazwę z komunikatu błędu, policz pliki zawierające jej deklarację:
-l wypisuje każdy pasujący plik raz, a -w dopasowuje tylko całe słowa, więc vmdX nie jest liczone. var pominięto, ponieważ powtórzenie deklaracji var samo w sobie nie jest błędem. Wynik większy niż 1
oznacza, że nazwa jest zadeklarowana w więcej niż jednym chunku. Zastąp vmd nazwą z Twojego komunikatu błędu.
Kolizje identyfikatorów mają znaczenie tylko wtedy, gdy deklaracje dzielą ten sam zakres. Ta sama nazwa powtórzona w osobnych modułach lub domknięciach nie dowodzi kolizji; dowodzi jej dopiero powyższy błąd parsowania.
Dlaczego tak się dzieje
Presety VM używają generatora mangled-shuffled opcji Identifier Names Generator. Przechodzi on przez niewielki alfabet w przetasowanej kolejności,
a przy obfuskacji VM każda zmienna globalna o zmienionej nazwie otrzymuje prefiks vm (dodawany przed każdym ustawionym przez Ciebie identifiersPrefix, więc checkout_
zmienia się w vm_checkout_...).
Przetasowana kolejność jest zapamiętywana w obrębie procesu, więc pliki obfuskowane w tym samym procesie albo z tym samym
stałym seed korzystają z tej samej sekwencji - pierwsza zmienna globalna w każdym pliku ma tę samą nazwę, druga również
wspólną, i tak dalej.
Każdy plik jest obfuskowany niezależnie, a generator dla każdego z nich zaczyna swoją sekwencję od początku. Gdy dwa pliki
trafią do tego samego zakresu, nazwy kolidują. Dwie deklaracje najwyższego poziomu let vmd lądują w tym samym
zakresie, a parser odrzuca drugą z nich.
Każdy plik obfuskowany przez VM deklaruje jedną nazwę środowiska uruchomieniowego najwyższego poziomu bez sufiksu, a to
wystarczy do kolizji. renameGlobals: true znacznie to pogarsza: każda deklaracja najwyższego poziomu staje się krótką
nazwą vm*, a własne nazwy środowiska uruchomieniowego tracą swój unikalny sufiks.
Rozwiązania
Najlepiej najpierw zbudować bundle, a potem obfuskować go jednorazowo. Jeśli jednak obfuskujesz pliki osobno, a skrypty dzielą globalny zakres, wybierz jedno z poniższych rozwiązań:
Włącz
randomIdentifiersPrefix(zalecane)Każde uruchomienie obfuskacji otrzymuje losowy prefiks dodawany na początku każdego globalnego identyfikatora (przy obfuskacji VM zastępuje on domyślny prefiks
vm). Nazwy z różnych plików nie dzielą już przestrzeni nazw, więc kolizje znikają bez konieczności ręcznego uzgadniania prefiksów.Ustaw unikalny
identifiersPrefixdla każdego plikuPodczas obfuskacji każdego pliku ręcznie przekaż inny prefiks (np.
identifiersPrefix: 'auth_'dla jednego,checkout_dla drugiego). To skuteczne, ale przy wielu plikach łatwo o pomyłkę, więc lepiej wybrać opcję losową opisaną wyżej.Przełącz
identifierNamesGeneratornahexadecimalNazwy szesnastkowe korzystają ze znacznie większej przestrzeni kluczy, więc prawdopodobieństwo, że dwa pliki wygenerują ten sam identyfikator, jest dużo mniejsze, ale unikalność nie jest gwarantowana. Koszt: identyfikatory są dłuższe niż w wyniku
mangled-shuffled, więc bundle jest nieco większy.Użyj interfejsu obfuskacji wielu plików naraz albo sprawdź wtyczkę bundlera
Panel dodaje osobny prefiks do każdego pliku w ramach jednej partii wielu plików (plany płatne); pliki z różnych partii nadal mogą kolidować. Jeśli używasz wtyczki bundlera, sprawdź jej zachowanie, zamiast zakładać, że robi to samo. Jeśli sam wywołujesz pakiet
javascript-obfuscatorlub API, musisz sam włączyć prefiks.
Aby zweryfikować poprawkę, przebuduj i ponownie wczytaj połączoną aplikację, a następnie upewnij się, że SyntaxError
zniknął. Nazwa ze starego komunikatu błędu nie powinna już być zadeklarowana w więcej niż jednym chunku; prefiks zmienia
każdą wygenerowaną nazwę, więc powyższy grep mówi tylko o tej konkretnej nazwie, a nie o nowych.
Powiązane opcje
randomIdentifiersPrefix- losowy prefiks dla każdego builda (zalecane)identifiersPrefix- jawnie podany ciąg prefiksuidentifierNamesGenerator- kształt nazw (mangled,hexadecimal, …)
