Photo by Kaleidico on Unsplash
Quante volte ti è capitato di pensare a una feature che vorresti usare nel tuo progetto, ma nessuno dei pacchetti esistenti che la implementa ti soddisfa?
A me, per fortuna, non tante, ma ci sono stati alcuni casi particolari in cui volevo implementare una feature molto specifica ma non avevo tempo, quindi ho scelto dei compromessi e ho preso qualcosa di simile. Ho avuto l'idea per questo pacchetto mentre scrivevo l'articolo sulle Data-Driven Strategies. Era semplice configurare l'intero progetto, registrare le sessioni utente e interrogare i dati, ma renderlo disponibile per tutti e aggiungere feature interessanti come le heat map? Così questa volta ho deciso di iniziare a costruire da zero il mio pacchetto Laravel per registrare le sessioni utente.
Laravel ha una buona guida per costruire pacchetti, possiamo fare riferimento a quella!
Il punto di partenza: il boilerplate del pacchetto
Il cuore di Laravel è aiutarti a concentrarti sulla logica del tuo progetto invece di perdere tempo su cose legacy. Per lo sviluppo di pacchetti, puoi usare il Laravel Package Boilerplate Generator che genererà automaticamente la struttura del pacchetto, includendo una struttura di base, un composer.json con la dipendenza illuminate, alcuni strumenti come il supporto integrato per Travis, StyleCI, Scrutinizer e dei file markdown di base.
Pagina di benvenuto del Package Boilerplate Generator
Dopo essere entrato nel sito del boilerplate generator ti verrà chiesto se vuoi costruire un pacchetto Laravel o un pacchetto PHP.
Componi i dettagli del tuo pacchetto
Ovviamente ho scelto Laravel, ora devi compilare i dettagli del tuo pacchetto:
- Vendor name: nella maggior parte dei casi è il tuo nickname, se lo stai costruendo per un'organizzazione sarà il nickname della tua organizzazione. Se vuoi costruire un pacchetto open-source per Github o altri sistemi di version control pubblici, sarà il tuo nickname.
- Package name: il nome che vuoi dare al tuo pacchetto.
- Author name: chi sei?
- Author email: l'email che le persone potranno eventualmente usare per contattarti.
- Package Description: cosa fa il tuo pacchetto? Sii breve qui, avrai tutto il README.MD per spiegarlo!
- License: la scelta è tua, guidarti attraverso tutti i tipi di licenza è piuttosto difficile, ma ti aiutano tramite lo strumento "Choose an open-source license". Per questo ho scelto la MIT License: semplice e permissiva!
E questo è tutto per il boilerplate, basta cliccare next e scaricare il tuo file ZIP.
Download del boilerplate del pacchetto
Ora avrai la struttura del tuo pacchetto che puoi estrarre in una cartella qualsiasi e modificare usando il tuo editor preferito. Il nome del mio pacchetto, in particolare, è Laravel Spyhole!
La struttura del tuo pacchetto sarà più o meno così:
$ tree
.
├── .editorconfig
├── .gitattributes
├── .gitignore
├── .scrutinizer.yml
├── .styleci.yml
├── .travis.yml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── composer.json
├── config
│ └── config.php
├── phpunit.xml.dist
├── src
│ ├── LaravelSpyhole.php
│ ├── LaravelSpyholeFacade.php
│ └── LaravelSpyholeServiceProvider.php
└── tests
└── ExampleTest.php
3 directories, 17 files
Cosa c'è dentro?
- File markdown:
CHANGELOG.MDper tenere traccia degli aggiornamenti di versione del tuo pacchetto (per rimanere coerente suggerisco di usare il Semantic Versioning);CONTRIBUTING.MDper esplicitare come vuoi che le altre persone contribuiscano al tuo pacchetto;LICENSE.MDdove verrà messo il codice della licenza che hai scelto, se non hai scelto la licenza che volevi puoi modificarlo qui;README.MDciò che le persone vedranno entrando nel tuo repository. composer.json: file base di specifica di composer con i dati che hai scritto durante il tutorial e le dipendenze.phpunit.xml.dist: la configurazione di PHPUnit per eseguire i test..travis.yml: file di configurazione se vuoi usare lo strumento Travis CI (nota che Travis CI è gratuito per i progetti open-source)..scrutinizer.yml: file di configurazione se vuoi usare lo strumento Scrutinizer CI (anche Scrutinizer CI è gratuito per i progetti open-source)..styleci.yml: file di configurazione se vuoi usare lo strumento StyleCI (StyleCI è gratuito per i progetti open-source).- File di configurazione base di Git (
.gitattributese.gitignore). - Cartella config contenente un file per i file di configurazione del pacchetto laravel.
- La cartella source conterrà il codice del pacchetto.
- La cartella test contenente i test del pacchetto.
La prima cosa che ho fatto è stata mettere mano al file composer.json:
- aggiungere l'uso di PHP 8.0:
"php": "^7.3|^8.0" - aggiungere il supporto per più versioni del pacchetto:
"illuminate/support": "^7.0|^8.0" - aggiungere il pacchetto Orchestral Testbench nelle dipendenze di sviluppo per testare il pacchetto come in un'applicazione laravel (come suggerito nella guida di laravel)
composer require --dev orchestra/testbench.
Ora basta installare tutto
$ composer install
E siamo pronti a scrivere codice!
L'idea
Bene, prima di iniziare a scrivere codice, è meglio avere un'idea chiara di cosa vuoi costruire.
The Laravel Spyhole purpose is to have a nice and simple way to record and rewatch user sessions.
Questo è il modo facile per dirlo, ora sviluppiamolo.
Lo scopo di Laravel Spyhole è fornire un modo per incorporare il recorder in una view, il recorder invierà i dati a una route di Spyhole dove i dati verranno memorizzati. Spyhole registrerà gli eventi utente e i movimenti del mouse. Durante ogni sessione di registrazione, il DOM può cambiare: questi cambiamenti devono essere tracciati per rendere le registrazioni coerenti.
Le sessioni registrate devono essere disponibili per essere riviste. Ho usato molti pacchetti laravel con qualche tipo di integrazione dashboard, ognuno era diverso e integrare il loro comportamento all'interno di un sistema custom era piuttosto faticoso a causa delle varie interfacce, configurazioni e permessi da regolare. Prendendo ispirazione dalle mie esperienze precedenti, voglio dare all'utente il pieno controllo sulla propria integrazione, fornendo:
- una view incorporabile per incorporare solo il player disabilitando ogni altra interfaccia. Per tutti coloro che hanno già una dashboard e vogliono solo incorporare il player.
- una dashboard minimale per controllare tutte le registrazioni, rivederle ed eliminarle (fondamentalmente un CRUD), con una Gate per il controllo dei permessi. Per tutti coloro che vogliono usare il pacchetto out-of-the-box.
Progettare l'architettura di un sistema è complesso, un pacchetto che vuoi far usare ad altre persone lo è ancora di più, quindi abbraccerò la filosofia KISS (Keep It Simple, Stupid).
Il database
Struttura della tabella delle registrazioni delle sessioni.
La struttura da implementare è davvero semplice, consiste praticamente in una singola tabella: session_recordings.
La tabella dovrebbe memorizzare:
- ID: un intero auto-increment.
- path: questo aiuterà a filtrare e rivedere come funziona la UX di una pagina nel tempo e a calcolare ulteriori statistiche che possono essere utili (come controllare quanto tempo un utente passa su quella pagina, per esempio).
- session ID: può essere il vero session ID di Laravel o un UUID (se non vuoi tracciare l'ID reale), questo aiuterà a tracciare l'intera navigazione dell'utente facendo corrispondere session ID, path e timestamp.
- user ID: l'identificatore dell'utente per il tracking utente. Questo non è un intero ma una stringa per aderire al
getAuthIdentifierdell'interfaccia Authenticatable. In molti casi l'identificatore è un ID, ma qualche sviluppatore potrebbe voler usare un UUID o qualche tipo diverso di identificatore. - recordings: il payload della registrazione come JSON proveniente dal frontend.
- timestamp di creazione e aggiornamento: per il tracking temporale.
Una volta completato lo studio del database, implementare la migration (nella cartella database/migrations come in un'applicazione Laravel) è piuttosto facile.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateSessionRecordingsTable extends Migration
{
public function up()
{
Schema::create('session_recordings', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('path');
$table->string('session_id');
$table->binary('recordings');
$table->unsignedBigInteger('user_id')->nullable();
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('session_recordings');
}
}
Per far caricare la migration a Spyhole, nel metodo boot del Service Provider bisogna decommentare la riga della migration:
$this->loadMigrationsFrom(__DIR__.'/../database/migrations');Gli asset
Mentre giocavo con cimice (di cui ho parlato nell'altro articolo), ho scoperto una libreria più mantenuta: RRWeb (Record and Replay the Web) disponibile qui.
rrweb is an open source web session replay library, which provides easy-to-use APIs to record user’s interactions and replay it remotely.
Mentre l'ultimo commit di cimice su Github risale a 5 anni fa, l'ultimo commit di RRWeb risale a meno di un mese fa (mentre sto scrivendo questo 📓). Un'altra cosa positiva di RRWeb è che registra automaticamente i cambiamenti del DOM durante la registrazione della sessione!
RRWeb è composto da diversi file per la registrazione e il replay, quindi la prima cosa da fare è scaricare questi asset e renderli disponibili nel pacchetto. Il modo di Laravel per farlo è permetterti di pubblicare i tuoi asset nella cartella public dell'applicazione finale.
Ho deciso di usare la cartella resources/assets per memorizzare gli asset da pubblicare. Così ho scaricato rrweb.min.js e rrweb-replay.min.js dalla pagina JSDeliver, in questo modo la libreria è sempre disponibile insieme al pacchetto.
Ora basta segnalarli nel service provider. Per la pubblicazione devi anche specificare la cartella public dove questi asset verranno copiati, in generale i pacchetti seguono la convenzione di mettere gli asset in una cartella chiamata come il pacchetto nella cartella public vendor. Il codice del boilerplate incapsula il codice della funzione publishes nel controllo dell'ambiente di esecuzione dell'applicazione, in particolare questo tipo di pubblicazione deve essere eseguito solo quando si è in esecuzione da console (durante l'invocazione di artisan vendor:publish).
$this->publishes([
__DIR__.'/../resources/assets' => public_path('vendor/laravel-spyhole'),
], 'assets');La configurazione
La configurazione del pacchetto è pronta all'uso. La cartella config contiene già un file chiamato config.php dove va scritta la configurazione. La pubblicazione di Laravel spingerà questo file in config/laravel-spyhole.php quindi l'ho subito rinominato per far funzionare l'autocomplete. Il file di configurazione contiene solo un array con le chiavi di configurazione e i loro valori associati, quindi per ora può essere omesso, verrà popolato durante lo sviluppo.
Se per il tuo pacchetto non hai bisogno di un file di configurazione, basta eliminare la cartella config e rimuovere dal Service provider la chiamata publishes per la pubblicazione della configurazione.
$this->publishes([
__DIR__ . '/../config/laravel-spyhole.php' => config_path('laravel-spyhole.php'),
], 'config');Setup completato
Photo by Dayne Topkin on Unsplash
“Change begins at the end of your comfort zone” ~ Roy T. Bennett
Non avevo mai costruito un pacchetto prima, questo è il mio "uscire dalla mia comfort zone".
La configurazione è integrata, gli asset registrati, la migration piazzata, ora il gioco comincia. Ho deciso di dividere lo sviluppo del pacchetto in più articoli a causa del tempo di sviluppo e testing. Questo articolo ha coperto il setup e lo studio attorno allo sviluppo di pacchetti.
Nella prossima parte costruirò il controller del recorder, aggiungerò la validazione e lo testerò!
Resta sintonizzato per la serie completa e se vuoi prenditi un momento per lasciare un commento su come faresti la progettazione o se avresti cambiato qualcosa in questo step! ☕️