Το 9ο redesign του pvgr.eu (πρώην prince.gr)

Πέρασαν 6 χρόνια από την τελευταία φορά που σχεδίασα και προγραμμάτισα αυτό το site — τότε λεγόταν prince.gr, καθώς αυτό ήταν το handle που χρησιμοποιούσα εκείνη την εποχή! Ωστόσο, βαρέθηκα να το βλέπω, παρόλο που δεν γράφω συχνά. Το ανανεωμένο pvgr.eu αποτελείται από στατικές σελίδες HTML -τέρμα το WordPress- και έχω κρατήσει μόνο τα (σχετικά) πρόσφατα άρθρα. Ακολουθούν τα τεχνικά του εγχειρήματος, και λίγη ιστορία…

Αγόρασα το prince.gr domain name το 2001. Χρειάστηκε να ταχυδρομήσω κάποια έγγραφα σε σε ένα μακρινό νησί και να περιμένω δύο ή τρεις εβομάδες για την γραπτή επιβεβαίωση. Εκείνη την εποχή χρησιμοποιούσαμε Netscape και αργότερα Microsoft Internet Explorer 4, και ήταν ωραία. Το Wayback Machine έχει (σπασμένα ή και μισά) captures του domain από τον Οκτώβριο του 2001, αλλά έχω zipάκια όλων σχεδόν των redesigns που έχω κάνει. Έπρεπε βέβαια να ψάξω διάφορα ξεχασμένα backups σε σκληρούς δίσκους, και βρήκα και ένα μάτσο CD σε ένα συρτάρι με άχρηστα καλώδια και ξεπερασμένο hardware, αλλά είχα διάθεση να δω αν λειτουργούν ακόμα και τί έχουν μέσα. Ίσως να έχω και το πρώτο site που έφτιαξα, αυτό που μου «έφερε» την πρώτη μου μισθωτή δουλειά στον χώρο!

Χρησιμοποιούσα πολύ Macromedia Flash τότε (εξαγοράστηκε από την Adobe Systems το 2005), ενώ το mp3 ήταν αρκετά φρέσκο, οπότε οι πρώτες μου δημιουργίες ήταν ένας συνδυασμός από τις δύο αυτές τεχνολογίες. Αργότερα έμαθα PHP, και ξαναέφτιαξα το site μου σε ExpressionEngine το 2007, αν δεν κάνω λάθος. Την επόμενη χρονιά έφτιαξα ένα βασικό CMS με PHP και MySQL και μετέφερα εκεί όλο μου το content, μέχρι που πέρασα στο WordPress και άρχισα να φτιάχνω custom themes — περίπου το 2009. Από τότε χρησιμοποιούσα το WordPress αλλά πλέον δεν μπορώ να παρακολουθήσω τις εξελίξεις στην PHP, αφού έχω αφοσιωθεί στο front-end κομμάτι της διαδικασίας κατασκευής ενός website.


Τα άρθρα που έχω γράψει κατά καιρούς είναι σε καθαρή, handmade HTML. Είχα δουλέψει αρκετά στο configuration της εκάστοτε πλατφόρμας που σέρβιραν το prince.gr στην πορεία των ετών ώστε να μην μου πειράζουν τον κώδικα! Η ιδέα λοιπόν ήταν να κρατήσω το markup, να σερβίρω πλέον στατικές HTML σελίδες από GitHub Pages ή Netlify (εκεί κατέληξα, παρεμπιπτόντως), για να κερδίσω σε ταχύτητα και να γλυτώσω το κόστος του shared hosting, αλλά δεν ήθελα να κάνω copy-paste τα header και footer και όλο το άσχετο με το εκάστοτε άρθρο markup σε κάθε νέο αρχείο! Γι’ αυτό τον λόγο εφευρέθηκαν τα CMS, νομίζω… Τελικώς χρησιμοποίησα Pug. Τα πηγαία αρχεία .pug, .scss και .es6 «μεταφράζονται» με το Prepros. Θα μπορούσα να χρησιμοποιήσω Gulp ή Webpack ή Middleman, Haml ή Twig ή οτιδήποτε άλλο είναι «της μόδας» αυτή την εποχή, αλλά κατέληξα σε αυτό το σύστημα που δουλεύει καλά και γρήγορα και είμαι ικανοποιημένος.

Το σύστημα αρχείων, στην αρχή του έργου!

Χρησιμοποιώ το Bulma για την εμφάνιση του site — ασφαλώς όχι όλο το «πακέτο» αλλά μόνο λίγα defaults και utilities. Το τελικό stylesheet είναι μικρότερο από 70 KB, χωρίς τα stylesheets που συνοδεύουν τα παρακάτω third-party scripts (3 KB για το minified stylesheet του Prism, 18 KB για το minified stylesheet του lightgallery.js και κάτι ψιλά ακόμα για τα icon fonts και τα εικονίδια) — που όμως δεν φορτώνονται σε κάθε σελίδα! Θα μπορούσα να τα βελτιώσω περαιτέρω αλλά δεν αξίζει τον κόπο· υπάρχει άλλωστε service worker που αποθηκεύει αυτά τα resources στο localStorage — περισσότερα γι’ αυτό παρακάτω.

Ο κώδικας JavaScript που απαιτείται είναι: το Prism (16 KB, minified custom build), που χρωματίζει όμορφα τα κομμάτια κώδικα που παραθέτω, το lightgallery.js (24 KB, custom build) που χρειάζεται για τις συλλογές φωτογραφιών / screenshots που περιέχουν μερικά άρθρα, και λίγες γραμμές ακόμα δικός μου κώδικας που ενεργοποιεί τα παραπάνω. Δεν χρειάζομαι κουμπιά share, like ή tweet — είμαι σίγουρος πως όποιος θέλει να κοινοποιήσει στα κοινωνικά δίκτυα, θα το κάνει και χωρίς αυτά, και έτσι γλυτώνουμε όλοι το tracking! Επίσης, δεν μου χρειάζεται πλέον η jQuery. Την φόρμα επικοινωνίας διαχειρίζεται το Netlify. Δεν χρησιμοποιώ analytics.

Για τον σχολιασμό των άρθρων βρήκα τα JustComments, CommentBox και Commento. Είναι όλα hosted στο cloud και δεν βγάζουν τα λεφτά τους από διαφημίσεις, ή από την εκμετάλλευση του προφίλ των σχολιαστών. Το JustComments με το σύστημα pay-as-you-go που υποστηρίζει μου φάνηκε πολύ ενδιαφέρον, αλλά το public API ίσως να σημαίνει πως τα credits μου θα μπορούσαν να τελειώσουν πολύ γρήγορα στα χέρια ενός script kiddie… Το CommentBox για την δική μου χρήση πιθανότατα θα ήταν εντελώς δωρεάν, αλλά με τον κίνδυνο να ξεπεράσω το free tier — όπως συμβαίνει μερικές φορές με το πακέτο της καρτοκινητής μου και σιχτιρίζω! Το Commento αντίθετα μου στοιχίζει 3$ τον μήνα, ποσό αμελητέο σε σχέση με τα μειονεκτήματα που συνοδεύουν τα «δωρεάν» Discus και Facebook comments.


Η δομή των αρχείων ήταν αρχικά όπως φαίνεται στο screenshot. Η ιδέα ήταν τα άρθρα να είναι σε URLs του τύπου /ΓΛΩΣΣΑ/article/ΤΙΤΛΟΣ_ΑΡΘΡΟΥ.html, οι λίστες με τα άρθρα ανά κατηγορία να βρίσκονται στα /ΓΛΩΣΣΑ/articles/ΚΑΤΗΓΟΡΙΑ_ΑΡΘΡΩΝ.html, τα transpiled styles και scripts να είναι στο /assets/ και όλα τα πηγαία αρχεία, λογικά, στο /src/. Στην πορεία έκανα μερικές απαραίτητες αλλαγές, αλλά η βασική ιδέα παραμένει! Επίσης, αντιγράφω το περιεχόμενο του πιο πρόσφατου άρθρου στην σελίδα /index.html με το σωστό canonical <link>. Κάθε φορά που γράφω ένα άρθρο πρέπει να φτιάξω / ενημερώσω 5 ή 6 αρχεία (!), αλλά στην πραγματικότητα είναι ευκολότερο και γρηγορότερο απ’ όσο ακούγεται — και μοιάζει αρκετά με το πως φτιάχναμε τα site πριν από 20 χρόνια, με εργαλεία όπως το Dreamweaver… Ευτυχώς, οι τεχνολογίες της Web πλατφόρμας έχουν βελτιωθεί από τότε, και αυτές οι στατικές σελίδες που προσφέρω είναι accessible, mobile friendly, βασισμένες στα σύγχρονα web standards και περιέχουν πληροφορίες Schema.org και microformats.

Υπάρχει ένα block με μεταβλητές στην κορυφή του πηγαίου του εκάστοτε άρθρου, με τις σχετικές πληροφορίες, και το Prepros «απλά» ενώνει τα extended και imported αρχεία Pug και χτίζει μία σελίδα HTML — ορίστε το πηγαίο του συγκεκριμένου άρθρου, την ώρα που το έγραψα:

// /src/pug/el/article/pvgr-v9.pug
extends ../../_layout

block vars
  //- imports Prism style and script
  - var has_code = true

  //- imports lightGallery styles and scripts
  - var has_gallery = true

  //- controls the HTML lang attribute, “logo” language and paths @ header
  - var is_english = false

  //- self-explanatory, used in different places in other partial Pug files
  - var permalink_english = '/article/en/pvgr-v9.html'
  - var permalink_greek = '/article/el/pvgr-v9.html'
  - var canonical = 'https://www/pvgr.eu'+ permalink_greek
  - var title = 'pvgr.eu redesign, version 9 | Το ιστολόγιο του Παναγιώτη «pvgr» Βελισαράκου'

block content
  article.content.article-content(itemscope itemtype='http://schema.org/Article')
    .article-header.article-header-projects
      meta(itemprop='author' content='Παναγιώτης «pvgr» Βελισαράκος')
      h1.article-title(itemprop='name headline') Το 9<sup>ο</sup> redesign του <strong>pvgr.eu</strong> (πρώην <em>prince.gr</em>)
      time.article-subtitle(datetime='2019-04-18T15:00' itemprop='datePublished') 18 Απριλίου 2019
    figure.article-photo.article-thumb(itemprop='image' itemscope itemtype='https://schema.org/ImageObject')
      img(src='/assets/img/articles/pvgr-v9.svg' alt='' itemprop="url")
  …
// /src/pug/_layout.pug
doctype html

block vars

html(lang=is_english ? 'en-US' : 'el')
  head
    meta(charset='UTF-8')
    meta(name='viewport' content='width=device-width, initial-scale=1.0')
    title #{title}
    link(href='/assets/css/pvgr.css' rel='stylesheet')
    link(href=canonical rel='canonical')

    if has_code
      link(href='/assets/css/vendor/prism.css' rel='stylesheet')

    if has_gallery
      link(href='/assets/css/vendor/lightgallery.css' rel='stylesheet')

  body
    .site-wrapper
      include _header

      main(class='site-content')
        block content

      include _footer

    if has_code
      script(src="/assets/js/vendor/prism.js")

    if has_gallery
      script(src="/assets/js/vendor/lightgallery.min.js")

    script(src="/assets/js/pvgr.js")

Το εξαιρετικό βιβλίο του Jeremy Keith, Going Offline με βοήθησε να «χτίσω» ένα ServiceWorker script, που αποθηκεύει τα στατικά resources (stylesheets, javascripts, images) και τα πιο πρόσφατα άρθρα στην Cache του browser, και να σερβίρει μία σελίδα «offline» όταν ο επισκέπτης δεν έχει σύνδεση στο διαδίκτυο ΚΑΙ δεν έχει ήδη επισκεφτεί ξανά την σελίδα που ζήτησε! Good stuff!