Bezeichnerkollisionen zwischen obfuskierten Dateien vermeiden
Landen mehrere VM-obfuskierte Dateien im selben Bundle, können sie denselben Bezeichner auf oberster Ebene deklarieren und die Seite bereits beim Parsen zum Absturz bringen. Hier erfahren Sie, warum das passiert und wie Sie es beheben.
Das Symptom
Ihr Build läuft fehlerfrei, doch der Browser wirft beim Parsen einen Fehler, noch bevor die App startet:
Um zu sehen, wie viele Chunks den Namen aus der Fehlermeldung deklarieren, zählen Sie die Dateien, die eine Deklaration davon enthalten:
-l listet jede passende Datei einmal auf, und -w findet nur ganze Wörter, sodass vmdX nicht mitgezählt wird. var bleibt außen vor, weil eine wiederholte var-Deklaration für sich genommen kein Fehler ist. Ein Ergebnis über 1
bedeutet, dass der Name in mehr als einem Chunk deklariert wird. Ersetzen Sie vmd durch den Namen aus Ihrer Fehlermeldung.
Bezeichnerkollisionen spielen nur eine Rolle, wenn sich die Deklarationen einen Gültigkeitsbereich teilen. Derselbe Name in getrennten Modulen oder Closures ist noch kein Beweis für eine Kollision; der obige Parse-Fehler dagegen schon.
Warum das passiert
VM-Voreinstellungen setzen Identifier Names Generator auf mangled-shuffled. Dieser Generator durchläuft ein kleines Alphabet in einer gemischten Reihenfolge,
und bei VM-Obfuskierung erhält jeder umbenannte globale Bezeichner das Präfix vm (der Standardwert von identifiersPrefix). Die gemischte
Reihenfolge wird pro Prozess zwischengespeichert, daher schöpfen Dateien, die im selben Prozess oder mit demselben festen seed obfuskiert werden,
aus derselben Folge: Der erste globale Bezeichner jeder Datei hat also denselben Namen, der zweite einen anderen gemeinsamen Namen und so weiter.
Jede Datei wird unabhängig obfuskiert, und der Generator beginnt für jede wieder am Anfang seiner Folge. Landen
zwei Dateien im selben Gültigkeitsbereich, kollidieren die Namen. Zwei Deklarationen const vmd = … auf oberster Ebene landen im selben
Gültigkeitsbereich, und der Parser weist die zweite zurück.
Optionen, die mehr Bezeichner auf oberster Ebene einführen, erhöhen die Wahrscheinlichkeit, dass zwei Dateien denselben generierten Namen erreichen.
vmWrapTopLevelInitializers ist eine davon, und jede VM-Voreinstellung aktiviert sie bereits; Optionen wie
vmDynamicOpcodes oder vmBytecodeEncoding fügen weitere hinzu.
Lösungen
Bündeln Sie vorzugsweise zuerst und obfuskieren Sie das Bundle dann einmal. Wenn Sie doch getrennt obfuskieren und sich die Skripte einen globalen Gültigkeitsbereich teilen, wählen Sie eine der folgenden Möglichkeiten:
randomIdentifiersPrefixaktivieren (empfohlen)Jeder Obfuskierungslauf erhält ein zufälliges Präfix, das jedem globalen Bezeichner vorangestellt wird (bei VM-Obfuskierung ersetzt es das Standardpräfix
vm). Namen aus verschiedenen Dateien teilen sich keinen Namensraum mehr, sodass die Kollisionen verschwinden, ohne dass Sie Präfixe von Hand abstimmen müssen.Pro Datei ein eindeutiges
identifiersPrefixfestlegenÜbergeben Sie beim Obfuskieren jeder Datei manuell ein anderes Präfix (z. B.
identifiersPrefix: 'auth_'für die eine,checkout_für eine andere). Wirksam, aber fehleranfällig, wenn Sie viele Dateien haben; bevorzugen Sie die zufällige Variante oben.identifierNamesGeneratoraufhexadecimalumstellenHexadezimale Namen nutzen einen deutlich größeren Schlüsselraum, sodass zwei Dateien weit seltener denselben Bezeichner erzeugen, doch Eindeutigkeit ist nicht garantiert. Nachteil: Die Bezeichner sind länger als die Ausgabe von
mangled-shuffled, das Bundle wird also etwas größer.Die Stapelverarbeitung mehrerer Dateien in der Oberfläche nutzen oder Ihr Bundler-Plugin prüfen
Das Dashboard fügt jeder Datei ein eigenes Präfix hinzu, wenn Sie mehrere Dateien im Stapel obfuskieren; diese Funktion ist in den kostenpflichtigen Tarifen verfügbar. Verwenden Sie ein Bundler-Plugin, prüfen Sie dessen Verhalten, statt anzunehmen, dass es dasselbe tut. Binden Sie die Obfuskierung manuell über die npm-API ein, müssen Sie ein Präfix selbst aktivieren.
Um die Lösung zu überprüfen, erstellen Sie die zusammengesetzte Anwendung neu, laden Sie sie erneut und vergewissern Sie sich, dass der SyntaxError
verschwunden ist. Der Name aus der alten Fehlermeldung sollte nicht mehr in mehr als einem Chunk deklariert sein; ein Präfix ändert jeden generierten
Namen, daher gibt der obige grep-Befehl nur Auskunft über diesen einen Namen, nicht über die neuen.
Verwandte Optionen
randomIdentifiersPrefix- zufälliges Präfix pro Build (empfohlen)identifiersPrefix- explizite Präfix-ZeichenketteidentifierNamesGenerator- Form der Namen (mangled,hexadecimal, …)
