RSSPaper

~ My static generate newspaper ~


Comisiones cuando vendes en Apple Store

Comisiones cuando vendes en Apple Store

Programador Web Valencia

Comisión

¿Quieres vender en la Apple Store? Lo siento pero tenemos que hablar.

Cuando decides poner a la venta algún elemento dentro de un App no todas las ganancias van a tu bolsillo. Dependiendo de ciertas variables Apple se llevará un porcentaje por cada transacción, que puede ser de un 0% (ninguna), 15% o un 30%.

Un ejemplo rápido. Acabas de publicar un App de cocina donde ofreces deliciosas recetas veganas para perros. Decides que la vas a monetizar por media de una suscripción a un precio de 10 euros al mes. Solamente quienes paguen podrán visualizar las recetas completas con todos sus pasos; el resto únicamente disfrutaran del primer paso. En este caso de cada suscripción a ti te llegará 7 euros (un 70%) mientras que Apple se quedará una comisión de 3 euros (un 30%). Y esta situación ser repetirá en cada usuario y renovación.

Existen 2 servicios que no debes confundir, ya que su uso es completamente diferente a pesar que ambos gestionen dinero.

  • Apple Pay: Implementación para hacer pagos en una web o App por medio de una tarjeta que ha sido vinculada con la cartera de Apple.

  • In-App Purchase: Implementación para realizar pagos dentro de un App. Orientado a ofrecer contenido como: productos digitales, suscripciones y contenido premium.

El último servicio es el que nos interesa. Dentro podremos encontrar 3 subcategorías de posibles pagos:

  • Consumibles: como gemas en un videojuego o incrementar la visibilidad de un perfil temporalmente en un red de citas.
  • No consumibles: características premium que son compradas en una ocasión y no expiran.
  • Suscripciones: características premium o acceso a contenido a través de un pago recurrente. Cuando el usuario decide cancelar el siguiente pago, estas características dejan de ser accesibles transcurrido el periodo pagado.

Es importante que sepas donde encaja el App en estas subcategorías porque las comisiones cambiarán.

Comisiones

  • El App es gratis en tienda, no se vende nada: 0%.
  • El App es gratis en tienda pero posee anuncios: 0%.
  • El App es gratis en tienda pero se vende productos o servicios físicos: 0%.
  • El App es gratis en tienda aunque puedes pagar por consumibles: 30%.
  • El App es de pago, no se vende nada: 30%.
  • El App es gratis en tienda aunque puedes pagar una suscripción: 30%, aunque después del primer año baja a 15%.
  • Existe pagos o suscripciones fuera del App: 0%, sin embargo no debe existir ningún enlace o referencia al lugar donde se pueden realizar los pagos.
  • Existen pagos o suscripciones fuera del App con posibilidad de hacerlo también dentro de un dispositivo Apple: 0% si no es en el ecosistema de Apple, dentro del App se debe pagar las comisiones anteriormente mencionadas.

Tabla de precios disponibles

Los precios no los eliges libremente, Apple te da una tabla de posibilidades que si o si debes seleccionar la opción que más se ajuste con tu negocio. Te aviso que las cantidades a percibir varían dependiendo del país. Puede darse el caso que marques 10 euros, pero en un lugar como la India se venda por 4 euros.

Tabla precios In-App

Otras comisiones

No olvides que independientemente de Apple debes integrar una pasarela de pago. Alguien debe gestionar el movimiento de dinero entre la tarjeta del cliente y tu cuenta bancaria. Corre por tu cuenta. Las más populares son las siguientes.

  • Stripe: Se lleva una comisión de 1,4 % + 0,25 € para tarjetas europeas y 2,9 % + 0,25 € para tarjetas no europeas.
  • Paypal: Se lleva una comisión de 2,8 % + una tarifa fija dependiendo de la moneda.

Sin olvidar el pago anual de Apple Developer Program, que son 100 dolares. Es el precio para que tu App esté accesible en la tienda. En caso de no pagarlo sería retirada.

Y por último los impuestos locales de cada país. Pero esto es inabarcable de explicar en un artículo de blog.

Conclusión

Para publicar un App en la Apple Store debemos tener en cuenta las siguientes comisiones.

  • Apple Developer Program: 100 dolares anuales.
  • In-App Purchase: Entre 0% al 30%.
  • Pasarela de pagos: Los mencionados rondan de entre 1,4% al 2.9% + una tarifa fija.
  • Reducción de precio en algunos países.
  • Impuestos locales.

Aún así, sigue siendo la plataforma más rentable dentro del desarrollo de Apps.

Más información

Todas las funciones: In‑App Purchase

Comisiones: Principales prácticas

Don Clojure de la Mancha

Don Clojure de la Mancha

Programador Web Valencia

Don Clojure de la Mancha

Próximamente será publicado el libro: Don Clojure de la Mancha. ¿Quieres ser el primero en enterarte? Tan solo debes dejar un comentario. El email que introduzcas no será visible y solo le daré uso para avisarte del momento y lugar. NO TE ESTAS SUSCRIBIENDO A UNA NEWSLETTER.

Gracias por apoyar al software libre, la programación funcional y la comunidad hispana de Clojure.

Django ordenar ignorando los acentos

Django ordenar ignorando los acentos

Programador Web Valencia

Django con acento

En caso que intentes ordenar una consulta de la base de datos y no uses PosgreSQL como base de datos principal te vas a encontrar un pequeño problema: Cuando hay acentos no se ordena de una forma lógica. Si utilizas SQLite te lo habrás encontrado de frente. Por ejemplo, si yo tengo una tabla con nombres e intento ordenarlas con order_by pasaré de:

Zaragoza, Ávila, Murcia, Albacete...

al siguiente orden

Albacete, Murcia, Zaragoza, Ávila...

Las palabras con acento, con ñ u otros carácteres acabarán al final de la lista.

Para arreglarlo he creado la siguiente solución que debes copiarlo en el archivo donde necesites realizar el orden deseado.

import re
import functools


def order_ignore_accents(queryset, column):
    """Order Queryset ignoring accents"""

    def remove_accents(raw_text):
        """Removes common accent characters."""
        sustitutions = {
            "[àáâãäå]": "a",
            "[ÀÁÂÃÄÅ]": "A",
            "[èéêë]": "e",
            "[ÈÉÊË]": "E",
            "[ìíîï]": "i",
            "[ÌÍÎÏ]": "I",
            "[òóôõö]": "o",
            "[ÒÓÔÕÖ]": "O",
            "[ùúûü]": "u",
            "[ÙÚÛÜ]": "U",
            "[ýÿ]": "y",
            "[ÝŸ]": "Y",
            "[ß]": "ss",
            "[ñ]": "n",
            "[Ñ]": "N",
        }
        return functools.reduce(
            lambda text, key: re.sub(key, sustitutions[key], text),
            sustitutions.keys(),
            raw_text,
        )

    return sorted(queryset, key=lambda x: remove_accents(eval(f"x.{column}")))

Supongamos, por ejemplo, que necesitas ordenar unos pueblos o municipios. Lo que haría cualquier desarrollador es:

towns = Town.objects.all().order_by('name')

En su lugar, omitirás order_by y añadirás la consulta a la función order_ignore_accents. Y como segundo argumento la columna que quieres usar para ordenar. En este caso será name.

towns_order = order_ignore_accents(Town.objects.all(), 'name')

Se ordenará como esperamos.

Albacete, Ávila, Murcia, Zaragoza...

Tutorial rápido de Twing para PHP

Tutorial rápido de Twing para PHP

Programador Web Valencia

Twing

Trabajar con un motor de plantillas en PHP simplifica la labor de concadenar variables en ficheros con mucho texto, como puede ser un html. Cualquier Framework que imagines incorpora un sistema similar pero podemos usarlo de manera independiente para pequeñas páginas o funcionalidades.

Primero debemos instalar Twig en su versión más reciente en la raíz del proyecto. Esto lo podemos realizar con composer.

composer require "twig/twig:^3.0"

Ahora creamos una carpeta donde almacenaremos todas las plantillas.

mkdir templates

Dentro creamos el archivo contacto.txt con el siguiente contenido.


Hola {{ nombre }},
gracias por escribirnos desde {{ email }} con el asunto "{{ asunto }}".
¡Nos vemos!

Como es un ejemplo, vamos a crear otro archivo, llamado contacto.html, con el contenido:


<h1>Hola {{ nombre }},</h1>
<p>gracias por escribirnos desde {{ email }} con el asunto "{{ asunto }}".</p>
<p>¡Nos vemos!</p>

Todas las variables entre {{ }} serán sustituidas por las variables que se definan. Si no ha quedado claro en breve lo entenderás.

En estos momentos disponemos de 2 plantillas con diferentes extensiones y formatos. No es obligatorio disponer de varias plantillas, busque aprecies que funciona de manera independiente con cualquier formato en texto plano.

Ahora creamos un archivo PHP donde ejecutaremos el código. Podemos llamarlo, por ejemplo, renderizar.php. Añadimos:

// Cargamos todas las extensiones. En este caso solo disponemos de Twig
require_once('vendor/autoload.php');
// Indicamos en Twig el lugar donde estarán las plantillas.
$loader = new \Twig\Loader\FilesystemLoader('templates');
// Cargamos las plantillas al motor de Twig
$twig = new \Twig\Environment($loader);
// Definimos las variables que deseamos rellenar en las plantillas.
$variablesEmail = [
    'nombre' => 'Cid',
    'email' => 'cid@campeador.vlc',
    'asunto' => 'Reconquista'
];
// Renderizamos con la plantilla 'contacto.txt'
$plantillaPlana =  $twig->render('contacto.txt', $variablesEmail);
// Renderizamos con la plantilla 'contacto.html'
$plantillaHTML =  $twig->render('contacto.html', $variablesEmail);

Si yo hiciera un echo de cada variable podemos ver el trabajo realizado.

echo $plantillaPlana;
/**
Hola Cid,
gracias por escribirnos desde cid@campeador.vlc con el asunto "Reconquista".
¡Nos vemos!
**/
echo $plantillaHTML;
/**
<h1>Hola Cid,</h1>
<p>gracias por escribirnos desde cid@campeador.vlc con el asunto "econquista".</p>
<p>¡Nos vemos!</p>
**/

Y eso es todo.

Es realmente interesante para trabajar con emails, plantillas más complejas o en la búsqueda de renderizar un PDF. Sea cual sea tu objetivo final, disponer de un motor de plantillas en PHP hará más fácil tu trabajo.

Cómo cargar variables de entorno para un Back-End

Cómo cargar variables de entorno para un Back-End

Programador Web Valencia

Enviroment

Una buena práctica es no dejar secretos, como contraseñas o Tokens, dentro del código. Y ni mencionar el peligro que conlleva subirlo a un repositorio. En gran medida se hace hincapié en esta omisión de variables por no dejar expuesto al resto del equipo un contenido sensible. Además otorga la posibilidad de jugar con diferentes credenciales durante el desarrollo, algunas pueden ser solo para hacer pruebas y otras las que serán usadas en el proyecto final.

Muchos Frameworks ya incorporan un sistema similar al que vamos a mencionar. En breve descubrirás que la técnica es tan sencilla que puedes montártelo por tu cuenta.

Primero crea un archivo plano con el siguiente contenido. Yo lo llamaré: .env

TOKEN=123456789
USER=TUX
PASSWORD=qwe123

Son 3 futuras variables de entorno con sus valores.

A continuación ejecuta el siguiente comando en el terminal, en la misma carpeta donde se encuentra el fichero. Convertirá cada línea del fichero en una variable de entorno.

export $(cat .env | egrep -v "(^#.*|^$)" | xargs)

Si quieres comprobar que se ha ejecutado correctamente puedes hacer un echo con cualquier variable añadiendo el prefijo $.

echo $TOKEN
123456789

Tarea terminada. Recuerda que si cierras el terminal o modificas el archivo, debes volver a ejecutar el comando.

Leer variables de entorno en PHP

$token = getenv('TOKEN');
$user = getenv('USER');
$password = getenv('PASSWORD');

echo $token;
// 123456789

Leer variables de entorno en Python

import os

token = os.getenv('TOKEN')
user = os.getenv('USER')
password = os.getenv('PASSWORD')

Leer variables de entorno en Clojure

(def token (System/getenv "TOKEN"))
(def user (System/getenv "USER"))
(def password (System/getenv "PASSWORD"))

Aunque también puedes usar la dependencia environ.

Añade en project.clj.

[environ "0.5.0"]

Y usa con total libertad.

(require [environ.core :refer [env]])

(def token (env :TOKEN))
(def user (env :USER))
(def password (env :PASSWORD))

Comandos esenciales de un Full Stack en Linux

Comandos esenciales de un Full Stack en Linux

Programador Web Valencia

Terminal

Si quieres ser un buen desarrollador Web, o simplemente un usuario de Linux competente, defenderte con el terminal es básico. Por suerte gran parte de estos comandos pueden ser utilizados entre diversos sistemas operativos como Linux, BSD, MacOS X y Windows 10 a través de Shell. Son un estándar para profundizar en tareas, trabajar rápidamente y ir directo a una funcionalidad.

Por ello mismo dejo una lista de los comandos que creo esenciales para un Fullstack: manipular documentos, archivos, directorios, búsquedas, trabajar con logs, instalar servicios… etc. A partir de aquí ya puedes ir creciendo.

ls

Lista carpetas y archivos de un directorio.

ls

Muestra más información.

ls -l

Incluye los archivos ocultos.

ls -a

mkdir

Crea carpetas.

mkdir nueva_carpeta

Crea directorios recursivamente.

mkdir -p carpeta1/carpeta2

less

less archivo.txt

touch

Crea un archivo vacío.

touch archivo.txt

cd

Cambia de directorio.

cd carpeta

Subir un nivel

cd ..

Retroceder un directorio (subir al padre)

cd ..

Directorio del usuario

cd ~

Volver al directorio anterior

cd -

Ver información

Muestra información de un archivo o carpeta.

file paris.jpg

Buscar

Buscar archivos o carpetas.

Un fichero

find carpeta-donde-buscar -name feliz.jpg

Solo directorios

find carpeta-donde-buscar -type d -name vacaciones

pwd

Muestra la ruta absoluta del directorio donde nos encontramos.

pwd

mv

Mueve o renombra un archivo o carpeta.

mv fichero_original.txt fichero_nuevo_nombre.txt

cp

Copia un archivo o carpeta.

cp texto.txt texto_copiado.txt

Copia una carpeta

cp -r carpeta carpeta_copiada

rm

Borra un archivo

rm archivo.txt

Borrar carpeta

rm -r carpeta

Fecha

Ver la fecha

date

Convertir tiempo de formato unix a humano

date -r 1619018708

Nombre de usuario

whoami

tar

Comprime o descomprime archivos en formato Linux: tar, gzip y bz2.

Ver aquí

grep

Imprime el contenido de un archivo filtrando por un patrón.

Filtrar el resultado de un comando

ls | grep texto

Filtrar un archivo

cat archivo.txt | grep texto

sudo/su

Ejecuta comando con otros permisos, como administrador u otro usuario.

chmod

Cambia los permisos de un archivo o carpeta.

chmod 744 script.sh

Otra forma es utilizado un trio con:

Rol

  • u → usuario

  • g → grupo

  • o → Otros

  • a → Todos

Acción

  • + → Añadir

  • - → Quitar

Permiso

  • r → Lectura

  • w → Escritura

  • x → Ejecución

Por ejemplo, se le quita el permiso de escritura a todos

chmod a-w first.txt

Al usuario se le da permisos de ejecución

chmod u+x script.sh

chown

Cambia propiedad de un archivo o carpeta.

chmod debian:debian archivo.txt

cat

Concadena archivos.

cat archivo1.txt archivo2.txt

echo

Imprime el contenido de un archivo.

echo archivo.txt

man

Muestra el manual de un comando.

man ls

history

Muestra el historial de comandos.

history

clear

Limpia el terminal.

clear

reboot

Reinicia.

sudo reboot

shutdown

Apaga.

sudo shutdown now

top/htop

Monitor de procesos.

htop

nano

Editor de archivos simple.

nano archivo.txt

vim/nvim/emacs

Editor de archivos avanzado.

emacs -nw archivo.txt

curl

Realiza peticiones HTTP.

curl programadorwebvalencia.com

tail

Muestra el final de un archivo.

tail archivo.txt

ip

Muestra información de tu red.

ip address show eth0

lsof

Muestra que servicio esta utilizando cierto puerto.

lsof -i tcp:80

df

Muestra la información de espacio ocupado en el disco.

df -h

du

Muestra el espacio que ocupa los diferentes elementos de una carpeta.

Solo un nivel y en formato humano

du -d 1 -h

journalctl

Muestra los logs en tiempo real.

journalctl -f

Muestra los logs en tiempo real de un servicio.

journalctl -f -u ssh

Muestra los logs de un servicio.

journalctl -u ssh

Muestra las últimoas 20 líneas de un log.

journalctl -n 20

Limpia los logs hasta alcanzar el peso que indiques.

journalctl --vacuum-size=1G

Borra los logs con más de cierto tiempo.

journalctl --vacuum-time=1years

Ejecutar último comando

!!

Ejecuta último comando con sudo.

sudo !!

¿Qué hacer después de instalar Debian en un VPS o servidor?

¿Qué hacer después de instalar Debian en un VPS o servidor?

Programador Web Valencia

Logo Debian

Estos son todos los pasos que realizo cuando creo un VPS o servidor en Debian. A lo largo del tiempo he ido añadiendo puntos, modificando y quitando elementos innecesarios; por lo que no lo percibáis como “La guía definitiva”. Sino más bien como unos “apuntes de apoyo”. Personalmente ejecuto todo, aunque cada proyecto es un desafío diferente.

1. Actualizar a la última versión y estable

apt update && \
apt upgrade -y && \
apt dist-upgrade

2. Instalar software mínimo

apt install -y build-essential fail2ban iptables-persistent msmtp-mta python3-dev python3-pip libcurl4-openssl-dev libssl-dev htop git neovim wget curl zsh tmux && \
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" && \
apt autoremove -y

3. Configurar el cortafuegos

Dejamos pasar 80 y 443 para permitir los protocolos http y https.

iptables -A INPUT -p tcp --dport 80 -j ACCEPT &&
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

4. Cambiar editor por defecto

update-alternatives --config editor

5. Ajustar la hora

En este ejemplo configura la hora a Madrid (España).

ln -fs /usr/share/zoneinfo/Europe/Madrid /etc/localtime && \
dpkg-reconfigure -f noninteractive tzdata

6. Activa las actualizaciones automáticas de seguridad no atendidas

apt install -y unattended-upgrades apt-listchanges && \
echo unattended-upgrades unattended-upgrades/enable_auto_updates boolean true | debconf-set-selections && \
dpkg-reconfigure -f noninteractive unattended-upgrades

7. Crea un usuario

Se llamará debian, aunque puedes llamarlo como desees.

useradd --shell /bin/zsh -m debian

Ahora nos metemos en el usuario.

su debian

Configurarmos las claves ssh y oh-my-zsh.

ssh-keygen -t rsa
exit

Lo añadimos al grupo de sudo.

usermod -a -G sudo debian

Entramos en visudo para permitirle ejecutar sudo.

visudo

Editando la siguente línea.

%sudo   ALL=(ALL:ALL) NOPASSWD:ALL

Generamos la keygen de ssh para entrar en un futuro.

Copiamos las autorizaciones actuales asociadas con root.

cp /root/.ssh/authorized_keys /home/debian/.ssh/ && \
chown debian:debian /home/debian/.ssh/authorized_keys

8. Medida de seguridad ante disco lleno

Añadimos una archivo con contenido aleatorio de, por ejemplo, 1Gb. En caso que se llene el disco, podremos borrarlo para tener un margen de acción.

dd if=/dev/urandom of=balloon.txt bs=1MB count=1000

9. Limita el espacio de los logs

Editas

nano /etc/systemd/journald.conf

Descomentas (quitas la #) a la vez que modificas la siguiente línea.

SystemMaxUse=1Gb

Para terminar reinicia el servicio.

systemctl restart systemd-journald

Extras

Instalar docker

apt update && \
apt install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
    lsb-release && \
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg && \
echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
  $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null && \
apt update && \
apt -y install docker-ce docker-ce-cli containerd.io docker-compose

Activar Swap

Habilitamos un espacio reservado en el disco en caso de que la RAM se llene.

Instalamos zram.

sudo apt install zram-tools

Editamos su configuración.

sudo nano /etc/default/zramswap

Le marcamos que su capacidad sea la mitad de la RAM.

PERCENTAGE=50
ALLOCATION=4096 #4Mb
ALLOCATION=8192 #8Mb

Instalar snap

sudo apt install snapd

Comandos para comprimir y descomprimir

Comandos para comprimir y descomprimir

Programador Web Valencia

Comprimir

Dentro de Linux y MacOS disponemos de una herramientas preinstalada que es fantásticas para comprimir y descomprimir cualquier tipo de archivo: fotos, vídeos, texto, carpetas… Con solo tar ya podremos realizar las tareas básicas.

Conceptos importantes.

  • tar: Tarro o contenedor. Sirve para agrupar un conjuntos de archivos, no comprime.
  • gzip: Algoritmo de compresión malo pero rápido. Equivalente a un zip.
  • bz2: Algoritmo de compresión bueno pero lento. Equivalente a un rar.

Comprimir

tar

Ejemplo de como crear un grupo o archivador usando tar.

tar -cvf nombre.tar carpetas-o-archivos

c —> Crea un archivador (tar).

v —> Muestra el progreso.

f —> Indicamos que vamos a especificar el nombre final.

gzip

Ejemplo de como comprimir creado un zip equivalente en Linux.

tar -czvf futuro-comprimido.tar.gz carpetas-o-archivos-a-comprimir

c —> Crea un archivador (tar).

z —> Comprime usando gzip (zip)

v —> Muestra el progreso.

f —> Indicamos que vamos a especificar el nombre final.

bz2

Ejemplo de como comprimir creado un rar equivalente en Linux. (sustituye z por j)

tar -cjvf futuro-comprimido.tar.bz2 carpetas-o-archivos-a-comprimir

c —> Crea un archivador (tar).

j —> Comprime usando bzip2 (equivalente a rar)

v —> Muestra el progreso.

f —> Indicamos que usaremos un archivo.

Descomprimir

Ejemplo de como descomprimir cualquier formato: tar, tar.gz o tar.bz2. (sustituye c por x)

tar -xvf comprimido.tar.gz

x —> Extrae.

v —> Muestra el progreso.

f —> Indicamos que usaremos un archivo.

Cómo suavizar un scroll

Cómo suavizar un scroll

Programador Web Valencia

cookie

Si queremos que al pulsar en un hipervínculo, o ancla, se desplace de manera suave y lenta, en lugar ser instantáneo, podemos optar por usar algunos de siguientes 3 trucos. Pasando por CSS, JavaScript o JQuery. El artículo no cubre la forma de realizar un ancla, aunque puedes aprender en mi curso gratuito de HTML.

DEMO

Versión solo con CSS

Al añadir el siguiente CSS conseguirás que los movimientos de tus anclas sean suaves en lugar de instantáneos.

body {
	scroll-behavior: smooth;
}

En el momento que se escribió este artículo no era compatible con Safari.

Versión solo con JavaScript Vainilla

En caso contrario de que no funcione como esperas podrás usar un poco de JavaScript para conseguir el mismo efecto.

<script>
	document.addEventListener('DOMContentLoaded', () => {	

	    	//===
		// SCROLL SMOOTH
		//===
		// Variables
		const links = document.querySelectorAll('a[href *= "#"]:not([href = "#"])');

		/**
		 * Event scroll
		 */
		function clickHandler(event) {
		  event.preventDefault();
		  const href = this.getAttribute("href");
		  const offsetTop = document.querySelector(href).offsetTop;

		  scroll({
		    top: offsetTop,
		    behavior: "smooth"
		  });
		}

		// Add event all links
		links.forEach((link) => link.addEventListener("click", clickHandler));
	});
</script>

Versión solo con JQuery

Y por último, en caso de que aún así no funcione; puedes recurrir a un clásico que nunca te va a fallar y ha sido utilizado durante muchos años.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
	$(function() {
	    $('a[href *= "#"]:not([href = "#"])').click(function() {
				if (location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') || location.hostname == this.hostname) {
					let target = $(this.hash);
		    target = target.length ? target : $('[name = ' + this.hash.slice(1) + ']');
		    if (target.length) {
			$('html, body').animate({
			    scrollTop: target.offset().top
			}, 1000);
			return false;
		    }
		}
	    });
	});
</script>

Obviamente necesitarás que esté presente JQuery en tu proyecto web.

HTML sobre WebSockets

HTML sobre WebSockets

Programador Web Valencia

WebSockets sobre HTML

La forma tradicional de conseguir una SPA (Single-page Application) es dividir las responsabilidades, el Back-End sirve la información y el Front-End la dibuja dinámicamente. Tristemente implica un doble esfuerzo en el desarrollo siendo necesario la creación de 2 aplicaciones con tecnologías diferentes aumentando costes e involucrando a dos perfiles especializados. Aunque, por supuesto, es el precio que debemos pagar si queremos una web en tiempo real y que se renderice en un pestañeo. ¿O hay una alternativa? ¿Con incluso mejor rendimiento? Así es, y además es más fácil de desarrollar al trabajar con un solo lenguaje. Esta arquitectura se denomina: HTML sobre WebSockets.

Chris McCord, creador de Phoenix (el Framework más popular dentro del ecosistema Elixir), presentó en ElixirConf 2019 una tecnología llamada LiveView. En apenas 15 minutos creó un clon de Twitter que funcionaba en tiempo real sin necesidad de incorporar JavaScript renderizador o un framework popular (React, Angular, Vue…) que gestione la Vista, demostrando que era posible quedarse en el Back-End y lograr productividad con una dulce aroma a buen rendimiento. Desde entonces se ha popularizado esta solución, inspirado a otros desarrolladores para crear implementaciones de HTML sobre WebSockets en otros lenguajes. Se puede volver al Back-End pero sin renunciar a lo bueno del Front-End.

¿Cómo funciona?

Disclamer: ¡si se usa JavaScript! Su labor no es renderizar sino crear un canal de comunicación con WebSockets y situar el HTML recibido en el lugar adecuado. Además de otras tareas secundarias como animaciones, gestión de eventos, etc.

La solución de McCord es no enviar al Front-End un JSON, sino HTML que no necesite ser preprocesado. De ese modo trasladamos la carga del dibujado, y toda su lógica, al Back-End. Ya pero… ¿Cómo hacemos que el servidor nos envíe nuevo contenido de forma inmediata y sin realizar una petición? Sencillo: con WebSockets.

Repasemos el sistema tradicional de la introducción. Desde la Web hago una petición HTTP, el navegador inicia la acción, obteniendo en la respuesta un JSON con toda la información en crudo. Lo siguiente es interpretar y crear el HTML correspondiente.

Tradicional

Mientras que HTML sobre WebSockets puede ser el envío de un JSON donde se devuelve HTML/CSS/JS. O incluso puede quitar el propio envío quedando a la escucha.

Protocolo WebSockets sobre HTML

Veamos el ejemplo donde se renderiza el artículo número 2 de un blog.

1. Conectamos

Partimos con una conexión. Ya hay un tubo de comunicación entre cliente y servidor.

Conectar con WebSockets

2. Petición de componente

El cliente pide el contenido de la ruta “/articulo/2/” a través del canal.

Pedir WebSockets sobre HTML

3. Recepción de HTML/CSS/JS

El servidor genera el HTML/CSS/JS, usando el sistema de plantillas del Back-End, y lo devuelve por el canal.

Recibir WebSockets sobre HTML

4. Impresión

Por último, el Front-End lo sitúa en el lugar adecuado o asignado.

¿Dónde puedo ver una demostración?

He creado un prototipo en Django de un Blog con 100 entradas, cada artículo esta relacionado con sus respectivos comentarios. Además existe un apartado para visualizar el artículo completo, un paginador y una sección estática con algunos párrafos.

Aquí puedes ver como los cambios son reflejados en todos los clientes.

Si observáis la url, nunca se cambia de página, y… ¡aun así funciona! ¿Quieres probarlo por ti mismo? Tienes la posibilidad de levantarlo a partir del código fuente en GitHub, esta Docketizado a un comando de distancia para arrancarlo.

¿Cuáles son sus ventajas?

  • Solo hay un motor de renderizado, simplificando la tarea.
  • Real-time, los clientes reciben los cambios tan rápido como sea posible.
  • El protocolo WebSockets es más rápido que HTTP. Fuente: starkoveflow
  • Apropiado para conexiones lentas. Fuente: browsee.
  • Crear un SPA sin apenas JavaScript.
  • Excelente SEO, los motores de búsqueda adorarán la página al encontrarse solo HTML.

¿Cuáles son sus inconvenientes?

  • El servidor necesitará más recursos al tener que dejar un WebSocket abierto por cliente.
  • Poca documentación al respecto.
  • Pocos frameworks.

¿Qué Frameworks existen?

Puedes empezar por los siguientes recursos.

  • Elixir/Phoenix: LiveView.
  • Python/Django: Sockpuppet y Reactor.
  • C#/.NET: Blazor Server.
  • JavaScript: Turbo con Stimulus

Apuntes finales

No creo que sea la solución definitiva, pero merece ser escuchada. Es llamativo su creciendo adopción y herramientas que están apareciendo. A nivel personal se sorprendió lo poco conocido que es, posiblemente a causa del poderoso ecosistema de JavaScript. Sin embargo es todo un placer no estar en la carrera de fondo que supone el Front-End para no quedarte desactualizado, y centrarte en el lenguaje de servidor.

En serio, ¿qué puedes perder por probarlo?

Itinerario de Desarrollador Backend

Itinerario de Desarrollador Backend

Podcast República Web

A la hora de empezar a desarrollar web, el perfil del desarrollador Backend se ve como una especialización. Donde el programador se enfoca desarrollo de API’s REST y su integración con la arquitectura de microservicios. Partiendo de la base de unos requisitos mínimos: Fundamentos de programación Programación estructurada Bases de datos relacionales Vamos a identificar tres posibles caminos: Java Javascript Python En los tres casos tendremos una buena base de programación orientada a objetos y la posibilidad de tener acceso … Ver más

Construye tu contenido en internet con independencia de las plataformas

Construye tu contenido en internet con independencia de las plataformas

Podcast República Web

Son tiempos de movimiento en el mundo del podcasting. Cada vez son más las iniciativas que buscan atraer y retener audiencias en el medio. Para muchos productores de contenido, el podcasting se antoja como un refugio de las guerras por el clic y la publicidad agresiva de la programática. El podcasting sigue creciendo y a esos pioneros programas amateur, se van uniendo producciones más originales y ambiciosas. Pero tanto si eres un pez grande como uno pequeño, a tus contenidos … Ver más

Itinerario de Desarrollador Frontend

Itinerario de Desarrollador Frontend

Podcast República Web

El perfil de Desarrollador Frontend es uno de los más populares en la industria del desarrollo de aplicaciones TIC (Tecnologías de la Información y la Comunicación, IT en inglés). Los requisitos habituales para este tipo de perfiles varían de empresa u organización pero siempre tienen una serie de aptitudes que son necesarias. Dentro de esta capacidades hay una serie de de mínimos que un futuro Desarrollador FrontEnd debe conocer, como son: Fundamentos de programación, Redes de Comunicaciones. Los fundamentos de … Ver más

¿Qué deberíamos exigir a un contratista en un desarrollo web?

¿Qué deberíamos exigir a un contratista en un desarrollo web?

Podcast República Web

Cuando nos enfocamos al desarrollo software, solemos ver los requisitos que nos pone el cliente como las normas que deben guiar el proyecto que debe llevarlo a cabo. Para ello es interesante ponernos en la piel de nuestros clientes sobre lo que esperan de un contratista o un licitador. En este artículo intentaré resumir aquellos requisitos que personalmente pondría si tuviera que contratar un desarrollo a una empresa. Estos criterios podrán trasladarse de una manera efectiva y objetiva a los … Ver más

Los podcasts que escuchamos en República Web

Los podcasts que escuchamos en República Web

Podcast República Web

No hay persona que tenga un podcast y que a su vez no sea un oyente habitual. A menudo, incluso un oyente compulsivo. Por supuesto el equipo de República Web también tenemos una lista bastante abultada de programas que escuchamos casi siempre que podemos. El otro día propuse a mis dos compañeros, que me pasaron algunos de los que escuchan ellos y así entre los tres, poder hacer una lista de recomendaciones. El único requisito es que estuvieran relacionados con … Ver más