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 (domyślny identifiersPrefix).
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 const vmd = … lądują w tym samym
zakresie, a parser odrzuca drugą z nich.
Opcje wprowadzające więcej identyfikatorów najwyższego poziomu zwiększają szansę, że dwa pliki dojdą do tej samej
wygenerowanej nazwy. Jedną z nich jest vmWrapTopLevelInitializers, którą każdy preset VM już włącza; opcje takie jak
vmDynamicOpcodes czy vmBytecodeEncoding dodają kolejne.
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 dla każdego pliku, gdy korzystasz z obfuskacji wielu plików naraz, dostępnej w płatnych planach. Jeśli używasz wtyczki bundlera, sprawdź jej zachowanie, zamiast zakładać, że robi to samo. Jeśli podłączasz obfuskację ręcznie przez API pakietu npm, 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, …)
