Dokumentacja
/

Rozwiązywanie problemów

/

Unikanie kolizji identyfikatorów

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:

Text

Aby sprawdzić, ile chunków deklaruje nazwę z komunikatu błędu, policz pliki zawierające jej deklarację:

Text

-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 identifiersPrefix dla każdego pliku

    Podczas 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.

    JavaScript

  • Przełącz identifierNamesGenerator na hexadecimal

    Nazwy 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