Syntaxis
<script type="speculationrules">
// JSON object defining rules
</script>
De attributen src, async, nomodule, defer, crossorigin, integrity en referrerpolicy mogen niet worden opgegeven.
Uitzonderingen
TypeError | De speculatieregeldefinitie is geen geldig JSON-object. |
|---|
Beschrijving
Een <script type="speculationrules">-element moet een geldige JSON-structuur bevatten die speculatieregels definieert. De volgende voorbeelden tonen afzonderlijke prefetch- en prerender-regels:
<script type="speculationrules">
{
"prefetch": [
{
"urls": ["next.html", "next2.html"],
"requires": ["anonymous-client-ip-when-cross-origin"],
"referrer_policy": "no-referrer"
}
]
}
</script><script type="speculationrules">
{
"prerender": [
{
"where": { "href_matches": "/next" },
"eagerness": "eager"
}
]
}
</script>JSON-representatie van speculatieregels
De JSON-structuur bevat een of meer velden op het hoogste niveau, elk daarvan vertegenwoordigt een actie waarvoor speculatieregels worden gedefinieerd. Momenteel worden de volgende acties ondersteund:
"prefetch" Optioneel Experimenteel | Regels voor mogelijke toekomstige navigaties waarvan de bijbehorende document-responsebody moet worden gedownload, wat leidt tot aanzienlijke prestatieverbeteringen wanneer naar die documenten wordt genavigeerd. Merk op dat geen van de subbronnen waarnaar de pagina verwijst wordt gedownload. |
|---|---|
"prerender" Optioneel Experimenteel | Regels voor mogelijke toekomstige navigaties waarvan de bijbehorende documenten volledig moeten worden gedownload, gerenderd en geladen in een onzichtbaar tabblad. Dit omvat het laden van alle subbronnen, het uitvoeren van alle JavaScript, en zelfs het laden van subbronnen en het uitvoeren van datafetches die door JavaScript worden gestart. Wanneer naar die documenten wordt genavigeerd, verlopen navigaties direct, wat leidt tot aanzienlijke prestatieverbeteringen. |
Raadpleeg de hoofdpagina van de Speculation Rules API voor volledige details over hoe je prefetch en prerender effectief kunt gebruiken.
Elk actieveld bevat een array, die op zijn beurt een of meer objecten bevat. Elk object bevat een enkele regel die een set URL's en gerelateerde parameters definieert.
Elk object kan de volgende eigenschappen bevatten:
|
Een string die de bron aangeeft van de URL's waarop de regel van toepassing is. Dit is optioneel, omdat de waarde altijd kan worden afgeleid uit andere eigenschappen. Dit kan een van de volgende zijn:
|
|---|---|
| Een array van strings die een lijst met URL's weergeeft waarop de regel van toepassing is. Deze kunnen absoluut of relatief zijn. Relatieve URL's worden geparseerd ten opzichte van de basis-URL van het document (indien inline in een document) of ten opzichte van de URL van de extern opgehaalde bron (indien extern opgehaald). "urls" en "where" kunnen niet allebei in dezelfde regel worden ingesteld. |
|
Een object dat de voorwaarden weergeeft waarmee de regel URL's matcht die in het bijbehorende document voorkomen. In feite vertegenwoordigt het Dit object kan precies één van de volgende eigenschappen bevatten:
|
|
Een string die een hint aan de browser geeft over hoe gretig deze de linkdoelen moet prefetchen/prerenderen om de prestatievoordelen af te wegen tegen de overhead aan bronnen. Mogelijke waarden zijn:
Als |
| Een string die een hint aan de browser geeft over welke waarde van de No-Vary-Search-header zal worden ingesteld op reacties voor documenten waarvoor het prefetch-/prerenderverzoeken ontvangt. De browser kan dit gebruiken om vooraf te bepalen of het nuttiger is om te wachten tot een bestaande prefetch/prerender is voltooid, of om een nieuw fetch-verzoek te starten wanneer de speculatieregel overeenkomt. Zie het "expects_no_vary_search"-voorbeeld voor meer uitleg over hoe dit kan worden gebruikt. |
|
Een string die een specifiek referrer-policybeleid weergeeft dat moet worden gebruikt bij het opvragen van de in de regel opgegeven URL's — zie Opmerking
Een cross-site prefetch vereist een referrer-beleid dat minstens zo strikt is als de standaardwaarde Opmerking
Bij documentregels wordt het opgegeven referrer-beleid van de gematchte link gebruikt (bijvoorbeeld met het |
|
Een string die aangeeft waarop je wilt dat op URL gematchte links relatief worden gematcht. De waarde kan een van de volgende zijn:
Deze sleutelinstelling is alleen relevant voor regels die zijn gedefinieerd in een extern bestand (ingesteld met de |
|
Een array van strings die mogelijkheden van de browser vertegenwoordigt die de regel parseert, en die beschikbaar moeten zijn wil de regel worden toegepast op de opgegeven URL's. Let op
Prefetches zullen automatisch mislukken in browsers die niet aan een opgegeven vereiste kunnen voldoen, zelfs als ze de Speculation Rules API ondersteunen. Mogelijke waarden zijn:
|
| Een string die wordt gebruikt om een regel of ruleset te identificeren. Dit wordt opgenomen in de Sec-Speculation-Tags-request-header voor alle speculaties die onder die regel vallen. |
| Een string die aangeeft waar de pagina verwacht dat de geprerenderde inhoud wordt geactiveerd.
De directive wordt niet ondersteund voor prefetch-speculaties.
Toegestane waarden zijn:
|
Omdat speculatieregels gebruikmaken van een <script>-element, moeten ze expliciet worden toegestaan in de Content-Security-Policy script-src-directive als de site deze bevat. Dit gebeurt door de waarde "inline-speculation-rules" toe te voegen, samen met een hash- of nonce-bron.
Voorbeelden
Prefetch en prerender in dezelfde set regels
De basisvoorbeelden die in het beschrijvingsgedeelte werden getoond, bevatten afzonderlijk gedefinieerde speculatieregels voor prefetch en prerender. Het is mogelijk om beide te definiëren in één set regels:
<script type="speculationrules">
{
"prefetch": [
{
"urls": ["next.html", "next2.html"],
"requires": ["anonymous-client-ip-when-cross-origin"],
"referrer_policy": "no-referrer"
}
],
"prerender": [
{
"where": { "selector_matches": ".product-link" },
"eagerness": "eager"
}
]
}
</script>
Dit codefragment bevat een lijst-regel ("urls") en een voorbeeld van een documentregel ("where").
Meerdere regelsets
Het is ook toegestaan om meerdere sets regels op te nemen in één HTML-bestand:
<script type="speculationrules">
{
"prefetch": [
{
"urls": ["next.html", "next2.html"],
"requires": ["anonymous-client-ip-when-cross-origin"],
"referrer_policy": "no-referrer"
}
]
}
</script>
<script type="speculationrules">
{
"prerender": [
{
"where": { "selector_matches": ".product-link" },
"eagerness": "eager"
}
]
}
</script>En meerdere regels in één resultaatset:
<script type="speculationrules">
{
"prerender": [
{
"urls": ["one.html"]
},
{
"urls": ["two.html"]
}
]
}
</script>Dynamisch invoegen van regels
Hieronder staat een voorbeeld dat speculatieregels detecteert en, indien ondersteund, dynamisch een prerender-speculatieregel toevoegt via JavaScript:
if (
HTMLScriptElement.supports &&
HTMLScriptElement.supports("speculationrules")
) {
const specScript = document.createElement("script");
specScript.type = "speculationrules";
const specRules = {
prerender: [
{
urls: ["/next.html"],
},
],
};
specScript.textContent = JSON.stringify(specRules);
console.log("added speculation rules to: next.html");
document.body.append(specScript);
}Syntaxisvoorbeelden voor where
Een regel met bron document bevat een "where"-eigenschap, die een object is met criteria die bepalen welke links in het document worden gematcht. In feite vertegenwoordigt het "where"-object een test die op elke link op de pagina wordt uitgevoerd om te bepalen of de speculatieregel erop van toepassing is.
De meest basale versie matcht een enkel URL-patroon of CSS-selector:
{ "where": { "href_matches": "/next" } }{ "where": { "selector_matches": ".important-link" } }"href_matches" en "selector_matches" kunnen ook worden ingesteld op een array van waarden, zodat meerdere URL-patronen of CSS-selectors tegelijk kunnen worden gematcht:
{ "where": { "href_matches": ["/next", "/profile"] } }{ "where": { "selector_matches": [".important-link", "#unique-link"] } }URL-patronen en selectors kunnen ook wildcard-tekens (*) bevatten, waardoor een enkele waarde meerdere URL's kan matchen. Het onderstaande object kan bijvoorbeeld overeenkomen met user/, user/settings, user/stats, enz.
{ "where": { "href_matches": "/user/*" } }Zoekparameters (of query-strings) kunnen ook worden getarget in href_matches. Het onderstaande object kan bijvoorbeeld overeenkomen met alle same-origin URL's met een category-zoekparameter (als eerste of latere parameter):
{ "where": { "href_matches": "/*\\?*(^|&)category=*" } }Elke voorwaarde kan worden genegeerd door deze in een "not"-voorwaarde te plaatsen — dit betekent dat een link, wanneer deze overeenkomt, de speculatieregel niet toegepast krijgt, maar wel wanneer deze niet overeenkomt. Het volgende voorbeeld zorgt ervoor dat alle links die niet overeenkomen met het URL-patroon /logout de regel toegepast krijgen, maar niet de links die overeenkomen met /logout:
{ "where": { "not": { "href_matches": "/logout" } } }Meerdere "where"-voorwaarden combineren met "and" of "or"
Meerdere voorwaarden kunnen worden gecombineerd binnen "and"- of "or"-voorwaarden — deze nemen de waarde aan van arrays met meerdere voorwaarden, waarvan alle of een willekeurige (respectievelijk) moeten overeenkomen wil de speculatieregels op een link worden toegepast. Met "and" of "or" kunnen voorwaarden meerdere niveaus diep worden genest — er is geen opgegeven limiet aan toegestane nestingniveaus.
Het is nuttig om je het "where"-object voor te stellen als het equivalent van een if-statement. Dus
{ and: [A, B, { or: [C, { not: D }] }] }is gelijk aan
if (A && B && (C || !D)) {
apply speculation rule
}In het volgende complete speculatieregelvoorbeeld worden alle same-origin pagina's gemarkeerd voor prefetching, behalve degene die bekend staan als problematisch — de /logout-pagina, en alle links die zijn gemarkeerd met een klasse .no-prerender:
<script type="speculationrules">
{
"prefetch": [
{
"where": {
"and": [
{ "href_matches": "/*" },
{ "not": { "href_matches": "/logout" } },
{ "not": { "selector_matches": ".no-prerender" } }
]
}
}
]
}
</script>
Het bovenstaande where-patroon omvat geen cross-site links, die wel worden ondersteund voor prefetching (mits de gebruiker geen cookies heeft ingesteld voor de doelsite, ter bescherming tegen tracking), maar niet voor prerendering.
Voorbeeld van "relative_to"
Voor regelsets die extern worden opgehaald (dat wil zeggen, via de Speculation-Rules-responsheader) worden URL's in lijstregels en URL-patronen in documentregels standaard geparseerd ten opzichte van de URL van het bevattende externe tekstbestand. Om URL's in een lijstregel te parseren ten opzichte van de basis-URL van het document, wordt "relative_to" als volgt gebruikt:
{
"urls": ["/home", "/about"],
"relative_to": "document"
}Bij documentregels kan "relative_to" direct gekoppeld worden aan "href_matches", waarbij de basis-URL van het document alleen wordt gebruikt voor patronen in die specifieke voorwaarde:
{
"where": {
"or": [
{ "href_matches": "/home", "relative_to": "document" },
{ "href_matches": "/about" }
]
}
}In het bovenstaande voorbeeld wordt alleen de eerste "href_matches" gematcht ten opzichte van de basis-URL van het document.
relative_to is vooral relevant als het JSON-bestand met speculatieregels zich op een andere oorsprong bevindt dan het document waarop je ze wilt toepassen:
-
Als het document zich bevindt op
https://example.com/some/subpage.htmlen de regels ophttps://example.com/resources/rules.json, dan komt/homealtijd overeen methttps://example.com/home, ongeacht ofrelative_tois ingesteld opdocumentofruleset. -
Als echter het document zich bevindt op
https://example.com/some/subpage.htmlen de regels ophttps://other.example/resources/rules.json(bijvoorbeeld op een oorsprong van derden of zonder cookies), dan:"relative_to": "document"zorgt ervoor dat/homeovereenkomt methttps://example.com/home."relative_to": "ruleset"zorgt ervoor dat/homeovereenkomt methttps://other.example/home.
Dit is het typische gebruiksgeval voor
"relative_to". -
Een ander mogelijk (maar zeldzamer) gebruiksgeval is wanneer je URL's zijn opgegeven in de vorm
homein plaats van/home. Als het document zich bevindt ophttps://example.com/some/subpage.htmlen de regels ophttps://example.com/resources/rules.json, dan:"relative_to": "document"zou ervoor zorgen dathomeovereenkomt methttps://example.com/some/home."relative_to": "ruleset"zou ervoor zorgen dathomeovereenkomt methttps://example.com/resources/home.
Voorbeeld van "expects_no_vary_search"
Overweeg het geval van een landingspagina voor een gebruikersmap, /users, die een id-parameter heeft toegevoegd om informatie over een specifieke gebruiker op te roepen, bijvoorbeeld /users?id=345. Of deze URL als identiek moet worden beschouwd voor cachingdoeleinden, hangt af van het gedrag van de applicatie:
- Als deze parameter tot gevolg heeft dat een volledig nieuwe pagina wordt geladen met de informatie voor de opgegeven gebruiker, dan moet de URL apart worden gecachet.
- Als deze parameter tot gevolg heeft dat de opgegeven gebruiker op dezelfde pagina wordt uitgelicht, en er mogelijk een uitklappaneel wordt getoond met hun gegevens, dan moet de URL voor cachingdoeleinden als hetzelfde worden beschouwd. Dit kan resulteren in prestatieverbeteringen bij het laden van de gebruikerspagina's en kan worden bereikt via een
No-Vary-Searchmet een waarde vanparams=("id").
Hoe beïnvloedt dit speculatieregels? Overweeg de volgende code:
<script type="speculationrules">
{
"prefetch": [
{
"urls": ["/users"]
}
]
}
</script>
<a href="/users?id=345">User Bob</a>Wat zou er in dit geval gebeuren wanneer de gebruiker een navigatie start naar /users?id=345 terwijl de headers voor de prefetch van /users nog niet zijn ontvangen? Op dit punt weet de browser niet wat de waarde van No-Vary-Search zal zijn, als deze er al is. Als er geen No-Vary-Search-waarde was ingesteld, en het applicatiegedrag meer op Optie 1 hierboven leek, zou de prefetch verspild zijn geweest en zou de browser de aparte pagina /users?id=345 opnieuw vanaf nul moeten ophalen.
Om dit op te lossen, kunnen we een hint geven over wat de paginaauteur verwacht dat de No-Vary-Search-waarde is. Een speculatieregel kan een "expects_no_vary_search"-veld hebben, dat een stringweergave bevat van de verwachte headerwaarde:
<script type="speculationrules">
{
"prefetch": [
{
"urls": ["/users"],
"expects_no_vary_search": "params=(\"id\")"
}
]
}
</script>
<a href="/users?id=345">User Bob</a>Dit geeft aan dat Optie 2, hierboven beschreven, is wat de server naar verwachting oplevert. Als er een navigatie start terwijl er een lopende prefetch van /users is, informeert dit de browser dat het beter is om op de prefetch te wachten, in plaats van meteen een nieuwe fetch voor /users?id=345 te starten.
Documentregels kunnen ook worden gebruikt in combinatie met "expects_no_vary_search", afhankelijk van het gebruikte patroon. In het geval van bijvoorbeeld:
<script type="speculationrules">
{
"prefetch": [
{
{ "where": { "href_matches": "/users?id=*" } },
"expects_no_vary_search": "params=(\"id\")"
}
]
}
</script>
<a href="/users?id=012">User Bill</a>
<a href="/users?id=345">User Bob</a>
<a href="/users?id=678">User Ben</a>Als er over een link wordt gehoverd, begint de browser met het prefetchen van die specifieke link.
Als de gebruiker over een andere link hovert voordat de prefetch is voltooid, geeft het expects_no_vary_search-patroon de browser aan dat het niet nodig is om de huidige prefetch te annuleren, omdat alle /users-URL's met id-URL-parameterwaarden in deze context (en voor cachingdoeleinden) effectief naar dezelfde pagina verwijzen.
Extra aandacht is nodig bij het gebruik van prerender met No-Vary-Search, aangezien de pagina in eerste instantie mogelijk wordt geprerenderd met andere URL-parameters. No-Vary-Search wordt gebruikt voor URL-parameters die dezelfde bron van de server leveren, maar die door de client om verschillende redenen worden gebruikt (client-side rendering, UTM-parameters voor analysemeting, enz.). Aangezien de eerste prerender mogelijk voor andere URL-parameters is, mag alle code die daarvan afhankelijk is pas worden uitgevoerd nadat de prerender is geactiveerd.
Meerdere parameters kunnen worden opgegeven in een door spaties gescheiden array:
<script type="speculationrules">
{
"prefetch": [
{
{ "where": { "href_matches": "/users?id=*" } },
"expects_no_vary_search": "params=(\"id\" \"order\" \"lang\")"
}
]
}
</script>Als structured field moeten de parameters door spaties gescheiden, gequote strings zijn — zoals hierboven getoond — en niet door komma's gescheiden, wat ontwikkelaars mogelijk meer gewend zijn.
Voorbeeld van eagerness
De volgende set documentregels toont hoe eagerness kan worden gebruikt om een hint te geven over hoe gretig de browser elke overeenkomende set links moet prerenderen.
<script type="speculationrules">
{
"prerender": [
{
"where": { "href_matches": "/*" },
"eagerness": "conservative"
},
{
"where": { "selector_matches": ".product-link" },
"eagerness": "eager"
}
]
}
</script>Hier geven we de hint dat:
- Alle same-site links in het document conservatief moeten worden geprerenderd (dat wil zeggen, wanneer de gebruiker ze begint te activeren).
- Alle productlinks (in dit geval, die met een
classvan.product-link) in het document gretig moeten worden geprerenderd (dat wil zeggen, als de gebruiker enige vorm van beweging richting het navigeren ernaartoe maakt).
De effecten van eagerness-instellingen zijn minder nuttig voor lijstregels. Standaard worden lijstregel-URL's geprefetcht/geprerenderd zodra de regels zijn geparseerd, wat je zou verwachten — ze zijn bedoeld voor het expliciet vermelden van URL's met hoge prioriteit die je zo snel mogelijk beschikbaar wilt maken. Om deze reden heeft eager in huidige implementaties hetzelfde effect als immediate. Lagere eagerness-instellingen zijn voor prefetching/prerendering wanneer met links wordt geïnteracteerd, en hiervoor zul je eerder documentregels gebruiken om ze op de pagina te vinden.
Voorbeeld van tag
Een tag kan op het hoogste niveau worden opgenomen, om de gehele ruleset te identificeren:
<script type="speculationrules">
{
"tag": "my-rules",
"prerender": [
{
"where": { "href_matches": "/*" },
"eagerness": "conservative"
}
]
}
</script>Of om afzonderlijke regels te identificeren:
<script type="speculationrules">
{
"prefetch": [
"tag": "my-prefetch-rule",
"urls": ["next.html"]
],
"prerender": [
"tag": "my-prerender-rule",
"urls": ["next2.html"]
],
}
</script>Zie Sec-Speculation-Tags voor meer voorbeelden.
Voorbeeld van target_hint
Een target_hint kan worden opgenomen om het doelvenster aan te geven waarin overeenkomende prerender-speculaties worden geopend:
<script type="speculationrules">
{
"tag": "my-rules",
"prerender": [
{
"eagerness": "eager",
"target_hint": "_blank",
"urls": ["page2.html"]
}
]
}
</script>De bovenstaande regels zorgen ervoor dat de volgende links correct worden geprerenderd in de juiste doelen:
<a href="page1.html">Open link in this window</a>
<a target="_blank" href="page2.html">Open link in new window</a>target_hint is alleen nodig voor lijstregels, die urls gebruiken.
Ze zijn niet nodig voor documentregels (die where gebruiken), aangezien daarin het doel kan worden afgeleid uit het target-attribuut van het <a>-linkelement.