Evitare le collisioni di identificatori tra file offuscati
Quando più file offuscati con la VM finiscono nello stesso bundle, possono dichiarare lo stesso identificatore di primo livello e far fallire la pagina in fase di parsing. Ecco perché succede e come risolverlo.
Il sintomo
La build viene eseguita senza problemi, ma il browser genera un errore in fase di parsing, prima dell'avvio dell'app:
Per vedere quanti chunk dichiarano il nome indicato nell'errore, conta i file che ne contengono una dichiarazione:
-l elenca ogni file corrispondente una sola volta e -w trova solo parole intere, quindi vmdX non viene conteggiato. var è escluso perché ripetere una dichiarazione var di per sé non è un errore. Un risultato maggiore di 1
significa che il nome è dichiarato in più di un chunk. Sostituisci vmd con il nome presente nel tuo messaggio di errore.
Le collisioni di identificatori contano solo quando le dichiarazioni condividono uno scope. Lo stesso nome ripetuto in moduli o closure separati non prova una collisione; l'errore di parsing qui sopra sì.
Perché succede
I preset VM usano mangled-shuffled come Identifier Names Generator. Percorre un piccolo alfabeto in un ordine mescolato e,
con l'offuscamento VM, ogni variabile globale rinominata riceve un prefisso vm (aggiunto davanti a qualsiasi identifiersPrefix impostato, quindi checkout_
diventa vm_checkout_...). L'ordine mescolato viene
memorizzato in cache per processo, quindi i file offuscati nello stesso processo, o con lo stesso seed fisso, attingono alla stessa
sequenza: la prima variabile globale di ogni file ha lo stesso nome, la seconda ne condivide un altro, e così via.
Ogni file viene offuscato in modo indipendente e il generatore riparte dall'inizio della sua sequenza per ciascuno di essi. Quando
due file finiscono nello stesso scope, i nomi entrano in collisione. Due dichiarazioni di primo livello let vmd finiscono nello stesso
scope e il parser rifiuta la seconda.
Ogni file offuscato con la VM dichiara un nome di runtime di primo livello senza suffisso, e questo basta per una collisione.
renameGlobals: true peggiora molto le cose: ogni dichiarazione di primo livello diventa un breve nome vm* e i nomi propri
del runtime perdono il loro suffisso univoco.
Soluzioni
Se possibile, esegui prima il bundling e poi offusca il bundle una sola volta. Se invece offuschi i file separatamente e gli script condividono uno scope globale, scegli una delle seguenti soluzioni:
Attiva
randomIdentifiersPrefix(consigliato)Ogni esecuzione dell'offuscamento riceve un prefisso casuale anteposto a ogni identificatore globale (con l'offuscamento VM sostituisce il prefisso predefinito
vm). I nomi di file diversi non condividono più uno spazio dei nomi, quindi le collisioni scompaiono senza che tu debba coordinare manualmente i prefissi.Imposta un
identifiersPrefixunivoco per ogni filePassa manualmente un prefisso diverso quando offuschi ciascun file (ad esempio
identifiersPrefix: 'auth_'per uno,checkout_per un altro). È efficace, ma soggetto a errori se hai molti file: preferisci l'opzione casuale descritta sopra.Imposta
identifierNamesGeneratorsuhexadecimalI nomi esadecimali usano uno spazio di chiavi molto più ampio, quindi è molto meno probabile che due file producano lo stesso identificatore, ma l'univocità non è garantita. Compromesso: gli identificatori sono più lunghi dell'output di
mangled-shuffled, quindi il bundle è leggermente più grande.Usa l'interfaccia di elaborazione multi-file o verifica il plugin del bundler
La dashboard aggiunge un prefisso distinto a ogni file all'interno di uno stesso batch multi-file (piani a pagamento); i file di batch separati possono comunque entrare in collisione. Se usi un plugin del bundler, verifica il suo comportamento invece di dare per scontato che faccia lo stesso. Se chiami tu stesso il pacchetto
javascript-obfuscatoro l'API, devi attivare un prefisso.
Per verificare la correzione, ricompila e ricarica l'applicazione combinata e conferma che il SyntaxError sia scomparso. Il nome presente
nel vecchio messaggio di errore non dovrebbe più essere dichiarato in più di un chunk; un prefisso cambia ogni nome generato, quindi
il comando grep qui sopra ti informa solo su quel nome specifico, non su quelli nuovi.
Opzioni correlate
randomIdentifiersPrefix- prefisso casuale per ogni build (consigliato)identifiersPrefix- stringa di prefisso esplicitaidentifierNamesGenerator- forma dei nomi (mangled,hexadecimal, …)
