Hoe verschillen tussen twee HTML-bestanden te vinden
Twee HTML-bestanden kunnen identiek worden weergegeven in een browser maar toch op tientallen plaatsen in de broncode verschillen. Witruimte rondom tags, de volgorde van attributen, HTML-entiteiten en self-closing-syntaxis zijn de gebruikelijke boosdoeners. Een gewone tekstdiff markeert al die gevallen als wijzigingen, wat de werkelijk relevante zaken verbergt. Deze gids laat zien hoe je een schoon resultaat krijgt.
Als je direct naar de tool wilt gaan, kun je op onze HTML-vergelijkingspagina twee bestanden plakken en de diff in je browser bekijken, zonder installatie. De rest van dit artikel legt uit waar je op moet letten zodra je de uitvoer hebt.
Waarom HTML-diffs zoveel ruis produceren
HTML is geen regelgeoriënteerd formaat. Een alinea kan één lange regel zijn of verspreid over tien regels staan — beide zijn geldig. De meeste editors, codeformatters en CMSes herformatteren HTML bij het opslaan, wat betekent dat een enkele woordwijziging kan leiden tot tientallen opnieuw opgemaakte regels. De diff ziet die als gewijzigde regels, niet als "één woord gewijzigd."
De WHATWG HTML Living Standard specificeert hoe browsers HTML parsen, maar schrijft niet voor hoe het geserialiseerd moet worden naar tekst. Twee tools kunnen structureel identieke HTML produceren die er als onbewerkte tekst totaal anders uitziet.
Vier dingen zijn verantwoordelijk voor het grootste deel van de ruis:
- Witruimte tussen en binnen tags
- Attribuutvolgorde (browsers vereisen geen specifieke volgorde)
- HTML-entiteiten versus letterlijke tekens
- Void-elementsyntaxis (
<br>vs<br />)
Witruimte: de grootste bron van valse positieven
In de meeste contexten wordt opeenvolgende witruimte in HTML samengevouwen tot één spatie wanneer de browser het weergeeft. Dat betekent dat deze twee fragmenten identiek worden weergegeven:
<!-- Version 1 -->
<p>Free text comparison tool.</p>
<!-- Version 2 -->
<p>
Free text comparison tool.
</p>
Een gewone tekstdiff markeert beide regels als gewijzigd. Ze zijn in geen betekenisvolle zin gewijzigd. Beslis voordat je vergelijkt of witruimte relevant is voor jouw gebruik. Voor e-mailtemplates of PDF-renderers doet het er soms toe. Voor de meeste webpagina's niet.
De beste oplossing is om beide bestanden door een formatter zoals Prettier te halen met dezelfde configuratie voordat je gaat vergelijken. Dat normaliseert inspringing, regellengte en spatiëring in één stap. Zodra beide bestanden dezelfde opmaakstijl delen, markeert een gewone tekstdiff alleen echte inhoudswijzigingen.
Attribuutvolgorde
De HTML-specificatie vereist niet dat attributen in een bepaalde volgorde
verschijnen. <div id="main" class="container"> en
<div class="container" id="main"> zijn hetzelfde element.
Maar een regeldiff behandelt ze als verschillende regels. Dit komt vooral
voor wanneer templates worden gegenereerd door verschillende tools of wanneer
iemand een auto-formatter gebruikt die attributen alfabetisch sorteert.
Volgens de WHATWG-parseerspecificatie zijn attributen op hetzelfde element per definitie ongeordend. Een diff die een attribuutvolgordeverandering als wijziging rapporteert is technisch correct maar zelden nuttig. Normaliseer de attribuutvolgorde in beide bestanden voordat je vergelijkt als dit ruis veroorzaakt.
HTML-entiteiten
&, <, >,
, numerieke referenties zoals —
— dit zijn allemaal manieren om tekens te coderen in HTML-broncode. Twee
bestanden kunnen hetzelfde teken verschillend coderen en toch dezelfde
pagina weergeven. Een tekstdiff ziet & en
& als verschillende tekenreeksen, ook al produceren beide
een ampersand in de browser.
Als entiteitverschillen je diff vervuilen, haal beide bestanden dan door een
HTML-parser die entiteiten normaliseert voordat je vergelijkt. De eigen
DOMParser API
van de browser is een betrouwbare manier om dit in JavaScript te doen: parseer
beide tekenreeksen, serialiseer ze terug met innerHTML en
vergelijk het resultaat.
Void-elementen
In HTML5 hebben void-elementen (elementen zonder kinderen) geen afsluitende
slash nodig. <br>, <br/> en
<br /> zijn allemaal geldig en worden identiek geparseerd.
Hetzelfde geldt voor <img>, <input>,
<meta> en de rest. Als het ene bestand XHTML-stijl
self-closing slashes gebruikt en het andere gewone HTML5-syntaxis, markeert
een tekstdiff elk van die elementen.
De volledige lijst van
void-elementen op MDN
omvat alle 14. Een snelle zoekopdracht naar /> in je
diff-uitvoer laat zien hoeveel van de ruis self-closing-syntaxis is.
Een uitgewerkt voorbeeld
Hier is een realistisch voor-en-na voor een site-header. Drie dingen zijn gewijzigd: een CSS-klasse is toegevoegd aan de header, het doel van de Home-link is gecorrigeerd en een Contact-link is toegevoegd.
<!-- Version 1 -->
<header class="site-header">
<nav>
<a href="/home" class="nav-link active">Home</a>
<a href="/about" class="nav-link">About</a>
</nav>
</header>
<!-- Version 2 -->
<header class="site-header sticky-top">
<nav>
<a href="/" class="nav-link active">Home</a>
<a href="/about" class="nav-link">About</a>
<a href="/contact" class="nav-link">Contact</a>
</nav>
</header>
Plak beide in de HTML-vergelijkingstool en de diff markeert precies die drie regels: het header class-attribuut, de Home href en de nieuwe ankertag. Geen ruis, omdat de inspringing en opmaak consistent zijn tussen de twee versies.
| Element | Versie 1 | Versie 2 | Type wijziging |
|---|---|---|---|
<header> |
class="site-header" |
class="site-header sticky-top" |
Klasse toegevoegd |
| Home-link | href="/home" |
href="/" |
Pad gecorrigeerd |
| Contact-link | Niet aanwezig | <a href="/contact">Contact</a> |
Toegevoegd |
Wanneer normaliseren voor het vergelijken
Niet elke HTML-vergelijking heeft normalisatie nodig. Als je twee bestanden vergelijkt die je zelf hebt geschreven met dezelfde editorinstellingen, is een gewone tekstdiff meestal voldoende. Normalisatie loont wanneer:
- Één bestand afkomstig is van een CMS-export en het andere van je editor
- Een buildtool één bestand heeft herformateerd maar het andere niet
- Je geminificeerde HTML vergelijkt met netjes opgemaakte HTML
- Je een HTML-e-mailtemplate van een externe afzender beoordeelt
De W3C Markup Validation Service is nuttig om te controleren of beide bestanden correct parseren voordat je ze vergelijkt. Een bestand met een gebroken tagstructuur geeft een misleidende diff, omdat de parser op zijn eigen manier herstelt van fouten en twee parsers anders kunnen herstellen.
Gegenereerde HTML vergelijken
Server-rendered frameworks (Angular, Next.js, Rails) embedden vaak tijdstempels, nonces of willekeurige identificatoren in de HTML-uitvoer. Twee renders van dezelfde pagina zullen op die regels anders zijn in de diff, ook al is de inhoud identiek. Als je gegenereerde HTML vergelijkt, verwijder of normaliseer die velden dan voordat je gaat vergelijken.
De onderliggende diff-engine op deze site is Google's diff-match-patch (Apache 2.0), die werkt op onbewerkte tekst. Het parseert geen HTML, dus het markeert opmaaksverschillen naast inhoudswijzigingen. Daarom is het eerst normaliseren belangrijk. Voor de meeste doeleinden geeft het direct plakken van de twee bestanden echter al een bruikbaar resultaat in een paar seconden. Onze XML-vergelijkingstool is ook de moeite waard als je HTML goed gevormde XHTML is, omdat XML-bewust vergelijken namespaces en attribuutvolgorde correct afhandelt.
Veelgestelde vragen
- Waarom toont mijn HTML-diff honderden wijzigingen terwijl ik slechts één regel heb gewijzigd?
- Het is bijna altijd een opmaakwijziging. Als je editor of een buildtool het bestand heeft herformateerd (inspringing gewijzigd, lange regels omgebroken of attributen hergeordend) bij het opslaan, ziet een gewone tekstdiff elke opnieuw opgemaakte regel als een wijziging. Haal beide bestanden eerst door dezelfde formatter en vergelijk daarna. De echte wijziging is de enige overgebleven regel.
- Is de volgorde van attributen belangrijk in HTML?
- Niet voor de browser. De HTML Living Standard vereist niet dat attributen in een bepaalde volgorde verschijnen en browsers parseren ze correct ongeacht de volgorde. Sommige linters en formatters sorteren attributen alfabetisch als stijlregel, waardoor twee semantisch identieke bestanden er anders kunnen uitzien in een tekstdiff. Als attribuutvolgorde ruis veroorzaakt, normaliseer beide bestanden dan met dezelfde formatter voordat je vergelijkt.
- Wat is het verschil tussen &amp; en & in HTML-broncode?
- Beide produceren een ampersandteken wanneer de browser de pagina weergeeft. In HTML-broncode is
&de entiteit-gecodeerde vorm en&het letterlijke teken. Technisch gezien moet&in attribuutwaarden worden gecodeerd als&per de specificatie, maar browsers accepteren beide. Een tekstdiff behandelt ze als verschillende tekenreeksen. Als entiteitscodering ruis veroorzaakt, parseer beide bestanden dan met een bibliotheek of de DOMParser van de browser en serialiseer terug voordat je vergelijkt. - Kan ik geminificeerde HTML vergelijken met netjes opgemaakte HTML?
- Ja, maar je moet het geminificeerde bestand eerst opmaken. Een diff van geminificeerd tegen netjes opgemaakt levert een resultaat op waarbij bijna elke regel gewijzigd lijkt, omdat minificatie alle witruimte verwijdert die de formatter had toegevoegd. Haal het geminificeerde bestand door Prettier of een gelijkwaardige formatter en vergelijk dan. De betekenisvolle wijzigingen zijn zichtbaar zonder de witruimteruis.
- Hoe vergelijk ik slechts een deel van een HTML-bestand, zoals een specifiek component?
- Extraheer het relevante gedeelte uit beide bestanden en plak alleen dat in de difftool. Als je bijvoorbeeld wijzigingen in een navigatiecomponent beoordeelt, kopieer dan alleen het
<nav>-blok uit elk bestand. Het vergelijken van het hele document wanneer je alleen om één sectie geeft voegt ruis toe van niet-gerelateerde delen van de pagina. - Zijn HTML-commentaren zichtbaar in een diff?
- Ja. Een tekstgebaseerde diff bevat alles in het bestand, inclusief commentaren. Als de ene versie een commentaarblok heeft dat de andere heeft verwijderd, of als een ontwikkelaar een commentaar heeft bijgewerkt, toont de diff dat. Dat is meestal nuttig: een verwijderd commentaar duidt vaak op opzettelijke opruiming. Als je commentaren wilt negeren, verwijder ze dan uit beide bestanden voordat je vergelijkt.
Klaar om je HTML-bestanden te vergelijken? Plak ze allebei in de gratis HTML-vergelijkingstool en bekijk de verschillen zij aan zij gemarkeerd, geen account nodig.