This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
Donut hole caching μπορεί να είναι μια χρήσιμη τεχνική όπου θέλετε να κρύψετε ορισμένα στοιχεία μιας σελίδας, αλλά όχι όλα. Ωστόσο, μπορεί να είναι δύσκολο να εφαρμοστεί. Σε αυτό το άρθρο θα σας δείξω πώς να εφαρμόσετε μια απλή τεχνική αποθήκευσης ντόνατς χρησιμοποιώντας HTMX.
Ένα θέμα που είχα με αυτό το site είναι ότι ήθελα να χρησιμοποιήσω αντι-αξέχαστες μάρκες με τις φόρμες μου. Πρόκειται για μια καλή πρακτική ασφαλείας για την πρόληψη των επιθέσεων Cross-Site Request Forgery (CSRF). Ωστόσο, δημιουργούσε πρόβλημα με την αποθήκευση των σελίδων. Το αντι-αξέχαστο σύμβολο είναι μοναδικό σε κάθε αίτηση σελίδας, έτσι αν κρύψετε τη σελίδα, το σύμβολο θα είναι το ίδιο για όλους τους χρήστες. Αυτό σημαίνει ότι αν ένας χρήστης υποβάλει ένα έντυπο, το σύμβολο θα είναι άκυρο και η υποβολή του εντύπου θα αποτύχει. ASP.NET Core αποτρέπει αυτό με την απενεργοποίηση όλων των caching κατόπιν αιτήματος όπου χρησιμοποιείται το αντι-αξέχαστο σύμβολο. Αυτή είναι μια καλή πρακτική ασφαλείας, αλλά αυτό σημαίνει ότι η σελίδα δεν θα κρατηθεί καθόλου. Αυτό δεν είναι ιδανικό για ένα site όπως αυτό όπου το περιεχόμενο είναι κυρίως στατικό.
Ένας κοινός τρόπος γύρω από αυτό είναι το "donut hole" caching όπου μπορείτε να κρύψετε το μεγαλύτερο μέρος της σελίδας αλλά ορισμένα στοιχεία. Υπάρχουν πολλοί τρόποι για να επιτευχθεί αυτό στο ASP.NET Core χρησιμοποιώντας το μερικό πλαίσιο προβολής, ωστόσο είναι περίπλοκο να εφαρμόσει και συχνά απαιτεί συγκεκριμένα πακέτα και config. Ήθελα μια απλούστερη λύση.
Όπως ήδη χρησιμοποιώ το εξαιρετικό HTMX σε αυτό το έργο υπάρχει ένας σούπερ απλός τρόπος για να αποκτήσετε δυναμική λειτουργία 'donut hole' με δυναμική φόρτωση Μερικά με HTMX. Έχω ήδη μπλόκαρε περίπου χρησιμοποιώντας AntiForgeryRequest Tokens με Javascript Ωστόσο και πάλι το θέμα ήταν ότι αυτή η αποτελεσματικά ανάπηρη αποθήκευση για τη σελίδα.
Τώρα μπορώ να επαναφέρω αυτή τη λειτουργία όταν χρησιμοποιώ HTMX για να φορτώσω δυναμικά επιμέρους.
<li class="group relative mb-1">
<div hx-trigger="load" hx-get="/typeahead">
</div>
</li>
Απολύτως απλό, σωστά; Το μόνο που κάνει αυτό είναι να καλέσει τη μία γραμμή κώδικα στο χειριστήριο που επιστρέφει τη μερική άποψη. Αυτό σημαίνει ότι το αντι-αξέχαστο σύμβολο παράγεται στο διακομιστή και η σελίδα μπορεί να κρατηθεί ως φυσιολογικό. Η μερική θέα φορτώνεται δυναμικά έτσι ώστε το σύμβολο να είναι ακόμα μοναδικό σε κάθε αίτημα.
ΣΗΜΕΙΩΣΗ: Εάν χρησιμοποιείτε μια προσέγγιση "SPA" όπως εγώ με HTMX, θα πρέπει να διασφαλίσετε ότι η load
Το γεγονός δεν πυροβολεί ξανά στο πίσω κουμπί. Θα το κάνω να συμβεί με το να ρυθμίσω τον τύπο για να αντικαταστήσω τον στόχο με το πρώτο φορτίο.
<div id="typeaheadelement" hx-trigger="load" hx-get="/typeahead" hx-target="#typeaheadelement" hx-swap="outerHTML"></div>
Αυτό σημαίνει ότι την πρώτη φορά που τρέχει καθαρίζει την αρχική div και την αντικαθιστά με το νέο περιεχόμενο από το μερικό που επιστρέφει από το χειριστήριο παρακάτω. Καθώς το Anto-αξέχαστο σύμβολο παράγεται στον διακομιστή και αποθηκεύεται σε ένα cookie συνεδρίας θα πρέπει να εξακολουθεί να λειτουργεί με αυτή την προσέγγιση (μέχρι να επαναπρογραμματίσω την εφαρμογή). ~~~
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
[HttpGet("typeahead")]
public IActionResult TypeAhead()
{
return PartialView("_TypeAhead");
}
Μέσα στο μερικό έχουμε ακόμα την απλή μορφή με το αντι-αξέχαστο σύμβολο.
<div x-data="window.mostlylucid.typeahead()" class="relative" id="searchelement" x-on:click.outside="results = []">
@Html.AntiForgeryToken()
<label class="input input-sm dark:bg-custom-dark-bg bg-white input-bordered flex items-center gap-2">
<input
type="text"
x-model="query"
x-on:input.debounce.300ms="search"
x-on:keydown.down.prevent="moveDown"
x-on:keydown.up.prevent="moveUp"
x-on:keydown.enter.prevent="selectHighlighted"
placeholder="Search..."
class="border-0 grow input-sm text-black dark:text-white bg-transparent w-full"/>
<i class="bx bx-search"></i>
</label>
<!-- Dropdown -->
<ul x-show="results.length > 0"
class="absolute z-10 my-2 w-full bg-white dark:bg-custom-dark-bg border border-1 text-black dark:text-white border-b-neutral-600 dark:border-gray-300 rounded-lg shadow-lg">
<template x-for="(result, index) in results" :key="result.slug">
<li
x-on:click="selectResult(result)"
:class="{
'dark:bg-blue-dark bg-blue-light': index === highlightedIndex,
'dark:hover:bg-blue-dark hover:bg-blue-light': true
}"
class="cursor-pointer text-sm p-2 m-2"
x-text="result.title"
></li>
</template>
</ul>
</div>
Αυτό στη συνέχεια ενσωματώνει όλο τον κώδικα για την αναζήτηση του typenaward και όταν υποβάλλεται τραβάει το σήμα και τον προσθέτει στο αίτημα (ακριβώς όπως και πριν).
let token = document.querySelector('#searchelement input[name="__RequestVerificationToken"]').value;
console.log(token);
fetch(`/api/search/${encodeURIComponent(this.query)}`, { // Fixed the backtick and closing bracket
method: 'GET', // or 'POST' depending on your needs
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': token // Attach the AntiForgery token in the headers
}
})
Αυτός είναι ένας σούπερ απλός τρόπος για να κάνετε το 'donut hole' caching με HTMX. Είναι ένας πολύ καλός τρόπος για να πάρει τα οφέλη του caching χωρίς την πολυπλοκότητα ενός επιπλέον πακέτου. Ελπίζω να το βρεις χρήσιμο. Ενημερώστε με αν έχετε οποιεσδήποτε ερωτήσεις στα σχόλια που ακολουθούν.