Foro de elhacker.net

Programación => Desarrollo Web => Mensaje iniciado por: Leguim en 19 Noviembre 2020, 20:20 pm



Título: [Pregunta]: ¿Cómo agregar una nueva versión siendo esta ya visible para todos?
Publicado por: Leguim en 19 Noviembre 2020, 20:20 pm
Hola!

Varias veces me pasó que cuando modifico una parte de mi código de javascript o algún estilo, para que sea aplicado en la aplicación web es necesario borrar la cache con el tradicional (CTRL+F5) para que se vean los cambios. Mi pregunta viene siendo, entonces como le hago para que cuando yo agregue una nueva versión, imaginemos que mi aplicación web esta en fase de producción (ya la están usando las personas) entonces yo al modificar un script para que estas personas puedan ver los cambios van a tener que borrar la cache, pero no todo el mundo sabe lo de CTRL+F5 y nunca vi a una aplicación notificar que como hay una nueva versión hay que tocar CTRL+F5 para que se vean los cambios entonces como hacen para poder implementar la versión/cambios y ya estén a la vista sin tener que reiniciar la caché?


Título: Re: [Pregunta]: ¿Cómo agregar una nueva versión siendo esta ya visible para todos?
Publicado por: MCKSys Argentina en 19 Noviembre 2020, 20:40 pm
Hola!

No soy desarrollador web per-se, pero te sugiero probar con el header HTTP Cache-Control: https://developer.mozilla.org/es/docs/Web/HTTP/Headers/Cache-Control (https://developer.mozilla.org/es/docs/Web/HTTP/Headers/Cache-Control)

Creo que usando max-age y must-revalidate (u otras combinaciones similares) debería hacer que el browser recargue solito el recurso...

Por las dudas, te dejo otro link que creo es importante: https://developer.mozilla.org/es/docs/Web/HTTP/Caching (https://developer.mozilla.org/es/docs/Web/HTTP/Caching)

Saludos!


Título: Re: [Pregunta]: ¿Cómo agregar una nueva versión siendo esta ya visible para todos?
Publicado por: @XSStringManolo en 19 Noviembre 2020, 22:07 pm
Para empezar depende el tipo de caché que uses. Estás usando Squid? Api Caché? Un hosting de terceros? Hasta que punto lo pueds modificar? Tu propio hosting?



Título: Re: [Pregunta]: ¿Cómo agregar una nueva versión siendo esta ya visible para todos?
Publicado por: Leguim en 24 Noviembre 2020, 03:31 am
Está todo como medio engorroso, hay como muchas de maneras de hacerlo y es por eso que me generan muchas dudas que al final no se que tenga que usar y que no (dependiendo que sea lo más optimo)...

¿Cómo hacen ustedes con sus aplicaciones web (si es que están en eso)?


Título: Re: [Pregunta]: ¿Cómo agregar una nueva versión siendo esta ya visible para todos?
Publicado por: yoelrodguez en 24 Noviembre 2020, 04:23 am
Hola buenas noche, si quieres evitar borrar la cache cada vez que modifiques tu código javascript, solo tienes que agregar esto ?n=100 el número 100 lo vas rotando como si fuere una nueva versión de tu fichero:

Gracias

Ejemplo:

Código:
<script src="nombre_del_script.js?n=100"></script>


Título: Re: [Pregunta]: ¿Cómo agregar una nueva versión siendo esta ya visible para todos?
Publicado por: @XSStringManolo en 24 Noviembre 2020, 09:11 am
Está todo como medio engorroso, hay como muchas de maneras de hacerlo y es por eso que me generan muchas dudas que al final no se que tenga que usar y que no (dependiendo que sea lo más optimo)...

¿Cómo hacen ustedes con sus aplicaciones web (si es que están en eso)?
Depende de tu applicación, tus clientes, el uso que se haga, la frecuencia de actualización...

No hay uno "mejor". Es como preguntar si es mejor un redirect en php, uno en el servidor o uno en javascript. Lógicamente depende de la situación y blablabla.

Antes de usar cosas (como caché) lo primero es entender que es, para que sirve, que tipos hay, que ventajas tienen, como usarlos...

Después hay implementaciones concretas de cada uno.
A nivel de servidor me gusta mucho como lo hace netlify. Siempre que subes un archivo nuevo al servidor el etag cambia y el navegador descarga el nuevo archivo y lo utilizará mientras no cambie el etag.
https://www.netlify.com/blog/2017/02/23/better-living-through-caching/

Yo utilizo ese método (porque tengo varios proyectos alojados) y también utilizo Caché Api para caché 100% navegador. Hice una implementación bastante simple, sacrifico potencia a cambio de sencillez. Lo más óptimo es ajustar cada archivo según tus necesidades. Por ejemplo so tienes una página de ventas que actualizas mensualmente, puedes cachear toda la web en el navegador durante un mes. O si actualizas cada 2 minutos o de forma irregular los twetts en tu aplicación, puedes cachear toda la página menos el componente que obtiene los twitts. Archivos como imágenes, pon por ejemplo el header del foro, se podría cachear de año en año xD.

Función para cachear de forma simple: https://github.com/StringManolo/ff/blob/master/ff.js#L41

Función (service worker) para interceptar peticiones y substituir la respuesta por el archivo en caché.
https://github.com/StringManolo/ff/blob/master/cache.js

Usándolo en una web: https://github.com/StringManolo/bugWriteups/blob/master/main.js#L247

Resultado: https://bugs.stringmanolo.ga/
* Se empieza a utilizar el caché del navegador tras la primera visita. Puedes comprobar que funciona visitándo la página sin internet, ya que al cargarse desde el caché del navegador no necesita internet para funcionar.
Esto obviamente reduce los tiempos de carga de una web drásticamente al ahorrarte todo el tiempo envuelto en hacer el handshake tcp, negociar certificados, enviar petición, esperar que el servidor reciva, procese, y responda.


Por otro lado los cache proxies están orientados a ahorrar tráfico y costos a un servidor. Por ejemplo puedes crear reglas inteligentes para cachear una página durante picos de actividad. O si tienes una gran cantidad de recursos y es frecuente que una vez se utilicen que vuelvan a reutilizar en los proximos minutos. Por ejemplo en páginas de descargas donde un archivo puede pasar años sin descargarse pero un día se vuelve popular y genera miles de descargas.
https://lpic2.unix.nl/ch09s03.html


Título: Re: [Pregunta]: ¿Cómo agregar una nueva versión siendo esta ya visible para todos?
Publicado por: Leguim en 25 Noviembre 2020, 04:28 am
Sí ya sabía lo que era la memoria caché (por lo menos en líneas generales), gracias a las respuestas de todos y algunas cosas que pregunté por separado haría esto...

Como ya dijeron, tendría que...
Código
  1. <script src="[...]/x.js?v0.0.1></script>
  2.  

mi duda igualmente viene siendo ¿Qué es lo que hago con las imágenes?, creo que las imágenes también son guardadas en la memoria caché ¿no es así?
¿debería...?

Código
  1. <img src="[...]/x.jpg?v0.0.1>
  2.  

¿Qué otra etiqueta o nose como se dirá... ¿src=""? debería aplicarle esto de concatenar un dato? (en este caso la versión)

Gracias.


Título: Re: [Pregunta]: ¿Cómo agregar una nueva versión siendo esta ya visible para todos?
Publicado por: @XSStringManolo en 26 Noviembre 2020, 13:09 pm
Sí ya sabía lo que era la memoria caché (por lo menos en líneas generales), gracias a las respuestas de todos y algunas cosas que pregunté por separado haría esto...

Como ya dijeron, tendría que...
Código
  1. <script src="[...]/x.js?v0.0.1></script>
  2.  

mi duda igualmente viene siendo ¿Qué es lo que hago con las imágenes?, creo que las imágenes también son guardadas en la memoria caché ¿no es así?
¿debería...?

Código
  1. <img src="[...]/x.jpg?v0.0.1>
  2.  

¿Qué otra etiqueta o nose como se dirá... ¿src=""? debería aplicarle esto de concatenar un dato? (en este caso la versión)

Gracias.
No entiendo tu pregunta.

src es un atributo.
<script>, <img> son etiquetas.
script, img son elementos (en concreto elementos html).
/x.jpg es una url relativa.
https://example.com/x.jpg es una url absoluta.
En src="/x.jpg", /x.jpg es el valor del atributo src.
v0.0.1 es un query string(cadena de consulta en español, aunque nunca vi utilizar este término en español)
? es un separador para indicar el comienzo del query string en el protocolo http
El query string está compuesto de key/value pairs (en español parejas de claves (identificadores) y valores. Normalmente se utiliza tipo /x.jpg?ancho=400

Te explico como funciona añadir la version o cualquier otra cosa en la url:
Cuando tu introduces un src="example.com/miFoto.jpg" en tu código html, estás definiendo donde se encuentra el recurso.
En la fase de parseo del navegador(cuando cargas la página el navegador lee el texto (codigo html) y lo interpreta para generar la página a partir de él. Al encontrar un <img src="/miFoto.jpg"> añadirá el base url para transformar el valor del atributo src de una ruta/url relativa a una absoluta.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
Por defecto la ruta se obtiene del método href del objeto location. (location.href)
Una vez convertido quedará <img src="https://example.com/miFoto.jpg">

En el siguiente paso que realiza el navegador se obtiene el recurso(miFoto.jpg en este caso) realizando una petición HTTP con el método GET.
La petición que hace el navegador podría ser:
Código
  1. GET /miFoto.jpg HTTP/1.1
  2. Host: example.com
  3. Accept: */*

Entonces el servidor web de example.com recive esta petición y la procesa/parsea para comprenderla y responder en consecuencia.
El servidor web pongamos de ejemplo Apache comprueba el archivo .htaccess (si existe) en la carpeta de la web, donde puede haber unas directivas tal que:
Código
  1. <filesMatch ".(ico|jpg|jpeg|png|gif)$">
  2. Header set Cache-Control "max-age=2592000, public"
  3. </filesMatch>
Aquí se indica que se incluya una cabecera HTTP(header) en la respuesta HTTP que se le dará al navegador en caso de que el recurso solicitado exista y su nombre cumpla con lo indicado en la expresión regular. En este caso se cumplirá para una serie de archivos cuyo nombre acabe por alguna de las extensiones de la expresión.
Entonces se incluye Cache-Control: max-age=2592000, public como cabecera de respuesta.
El navegador recive la imagen en el cuerpo de la petición junto al caché control y en base a el hashea la url del recurso y lo almacena en el caché.

Cuando se vuelve a solicitar la misma imagen, el navegador comprueba si la url que se está solicitando coincide con la que está almacenada en caché. Cuando le añades el ?v0.0.1 la url no coincide, por lo que el navegador entiende que la imagen que tiene en caché no coincide con la que se está solicitando actualmente y entiende como que es una imagen distinta. Se solicita la nueva imagen y se repite todo el proceso.

El efecto de añadir ?v0.0.1 es casi el mismo que si le cambias el nombre a la imagen cada vez que la actualices.
miFoto_v0.0.1.jpg.


PD: De todas formas esto de añadir la versión es un apaño rápido. Una solución para salir del paso de forma rápida y sencilla. Está bien para algún recurso concreto o páginas muy pequeñas y con pocas actualizaciones.

Qué pasa si mañana decides hacer una remodelación de la web? Tendrás que ir url por url y archivo por archivo cambiando las versiones. Si cambias todo de forma global puede que cambies la versión de algún archivo que no ha cambiado y obligas al cliente a descargarlo de nuevo a pesar de tener copia actual en caché.

La solución correcta/recomendada/óptima, es configurar el caché según tus necesidades. Normalmente en el servidor. Como puedes ver en uno de los ejemplos, se pueden usar expresiones regulares para cambiar el caché en archivos concretos. Para el problema que tienes, que creo que es algo más de fase de desarrollo que de producción, te recomiendo configurar el caché de tu servidor como en el ejemplo que te comenté anteriormente (en otra respuesta) de Netlify. Usando el etag para que el navegador compruebe automáticamente si el archivo cambió o no (utilizando e-tag). A parte de que es una solución más robusta, también es más cómoda para ti, ya que no tienes que andar cambiando las url para nada.


Título: Re: [Pregunta]: ¿Cómo agregar una nueva versión siendo esta ya visible para todos?
Publicado por: Leguim en 27 Noviembre 2020, 04:58 am
No entiendo tu pregunta.

src es un atributo.
<script>, <img> son etiquetas.
script, img son elementos (en concreto elementos html).
/x.jpg es una url relativa.
https://example.com/x.jpg es una url absoluta.
En src="/x.jpg", /x.jpg es el valor del atributo src.
v0.0.1 es un query string(cadena de consulta en español, aunque nunca vi utilizar este término en español)
? es un separador para indicar el comienzo del query string en el protocolo http
El query string está compuesto de key/value pairs (en español parejas de claves (identificadores) y valores. Normalmente se utiliza tipo /x.jpg?ancho=400

Te explico como funciona añadir la version o cualquier otra cosa en la url:
Cuando tu introduces un src="example.com/miFoto.jpg" en tu código html, estás definiendo donde se encuentra el recurso.
En la fase de parseo del navegador(cuando cargas la página el navegador lee el texto (codigo html) y lo interpreta para generar la página a partir de él. Al encontrar un <img src="/miFoto.jpg"> añadirá el base url para transformar el valor del atributo src de una ruta/url relativa a una absoluta.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
Por defecto la ruta se obtiene del método href del objeto location. (location.href)
Una vez convertido quedará <img src="https://example.com/miFoto.jpg">

En el siguiente paso que realiza el navegador se obtiene el recurso(miFoto.jpg en este caso) realizando una petición HTTP con el método GET.
La petición que hace el navegador podría ser:
Código
  1. GET /miFoto.jpg HTTP/1.1
  2. Host: example.com
  3. Accept: */*

Entonces el servidor web de example.com recive esta petición y la procesa/parsea para comprenderla y responder en consecuencia.
El servidor web pongamos de ejemplo Apache comprueba el archivo .htaccess (si existe) en la carpeta de la web, donde puede haber unas directivas tal que:
Código
  1. <filesMatch ".(ico|jpg|jpeg|png|gif)$">
  2. Header set Cache-Control "max-age=2592000, public"
  3. </filesMatch>
Aquí se indica que se incluya una cabecera HTTP(header) en la respuesta HTTP que se le dará al navegador en caso de que el recurso solicitado exista y su nombre cumpla con lo indicado en la expresión regular. En este caso se cumplirá para una serie de archivos cuyo nombre acabe por alguna de las extensiones de la expresión.
Entonces se incluye Cache-Control: max-age=2592000, public como cabecera de respuesta.
El navegador recive la imagen en el cuerpo de la petición junto al caché control y en base a el hashea la url del recurso y lo almacena en el caché.

Cuando se vuelve a solicitar la misma imagen, el navegador comprueba si la url que se está solicitando coincide con la que está almacenada en caché. Cuando le añades el ?v0.0.1 la url no coincide, por lo que el navegador entiende que la imagen que tiene en caché no coincide con la que se está solicitando actualmente y entiende como que es una imagen distinta. Se solicita la nueva imagen y se repite todo el proceso.

El efecto de añadir ?v0.0.1 es casi el mismo que si le cambias el nombre a la imagen cada vez que la actualices.
miFoto_v0.0.1.jpg.


PD: De todas formas esto de añadir la versión es un apaño rápido. Una solución para salir del paso de forma rápida y sencilla. Está bien para algún recurso concreto o páginas muy pequeñas y con pocas actualizaciones.

Qué pasa si mañana decides hacer una remodelación de la web? Tendrás que ir url por url y archivo por archivo cambiando las versiones. Si cambias todo de forma global puede que cambies la versión de algún archivo que no ha cambiado y obligas al cliente a descargarlo de nuevo a pesar de tener copia actual en caché.

La solución correcta/recomendada/óptima, es configurar el caché según tus necesidades. Normalmente en el servidor. Como puedes ver en uno de los ejemplos, se pueden usar expresiones regulares para cambiar el caché en archivos concretos. Para el problema que tienes, que creo que es algo más de fase de desarrollo que de producción, te recomiendo configurar el caché de tu servidor como en el ejemplo que te comenté anteriormente (en otra respuesta) de Netlify. Usando el etag para que el navegador compruebe automáticamente si el archivo cambió o no (utilizando e-tag). A parte de que es una solución más robusta, también es más cómoda para ti, ya que no tienes que andar cambiando las url para nada.

Estuve leyendo eso de netlify y quedé medio perdido, en pocas palabras esto:

(https://cdn.netlify.com/7119089e56720a5ab3eef06b60892b5e87d02987/8978d/img/blog/cache_headers.png)

es equivalente a poner esto en mi html?

Código
  1. <meta age="0">
  2. <meta cache-control="public, max-age=0, must-revalidate">
  3. <meta content-encoding="gzip">
  4. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  5.  

 :huh: :huh:  :huh:


Título: Re: [Pregunta]: ¿Cómo agregar una nueva versión siendo esta ya visible para todos?
Publicado por: @XSStringManolo en 27 Noviembre 2020, 13:09 pm
No, tienes que configurarlo en el servidor, no en un html. Véase Apache, Nginx, Node y demás.


Título: Re: [Pregunta]: ¿Cómo agregar una nueva versión siendo esta ya visible para todos?
Publicado por: Leguim en 27 Noviembre 2020, 20:56 pm
Las configuraciones del servidor (uso PHP como lenguaje del servidor) las hago de forma dinámica con ini_set pero cual manera debería usar para estas configuraciones de la caché?

Código
  1. header('age: 0');
  2. header('cache-control: public, max-age=0, must-revalidate');
  3. header('content-encoding: gzip');
  4. header('etag: (esa clave larga)');
  5. // o quizás deba usar?
  6. ini_set('age', 0);
  7. ini_set('cache-control', 'public, max-age=0, must-revalidate');
  8. ini_set('content-encoding', 'gzip');
  9. ini_set('etag', '(esa clave larga)');
  10.  

Después está date, pero no estoy seguro si eso haga algo...


Título: Re: [Pregunta]: ¿Cómo agregar una nueva versión siendo esta ya visible para todos?
Publicado por: @XSStringManolo en 28 Noviembre 2020, 03:03 am
Las comillas están bien de la primera forma.

Aquí tienes una implementación del e-tag en php:
https://stackoverflow.com/questions/13197479/how-to-use-etags-in-a-php-file

Las cabeceras deberías cambiarlas directamente en el servidor si tienes la posibilidad.




Título: Re: [Pregunta]: ¿Cómo agregar una nueva versión siendo esta ya visible para todos?
Publicado por: Leguim en 28 Noviembre 2020, 04:40 am
Código
  1. $file = 'my_file.php';
  2. $last_modified = filemtime($file);
  3. $etag = md5_file($file);
  4.  
  5. header('age: 0');
  6. header('cache-control: public, max-age=0, must-revalidate');
  7. header('content-encoding: gzip');
  8. header('content-type: text/html; charset=UTF-8');
  9. header('last-modified: '.gmdate('D, d M Y H:i:s', $last_modified).' GMT');
  10. header('etag: '.($etag));
  11.  

Creo que ya sería todo...
En resumen, ¿de está manera ya no tendría ese problema? (no sé si esta vez lo apliqué bien)


Título: Re: [Pregunta]: ¿Cómo agregar una nueva versión siendo esta ya visible para todos?
Publicado por: @XSStringManolo en 28 Noviembre 2020, 10:20 am
Código
  1. $file = 'my_file.php';
  2. $last_modified = filemtime($file);
  3. $etag = md5_file($file);
  4.  
  5. header('age: 0');
  6. header('cache-control: public, max-age=0, must-revalidate');
  7. header('content-encoding: gzip');
  8. header('content-type: text/html; charset=UTF-8');
  9. header('last-modified: '.gmdate('D, d M Y H:i:s', $last_modified).' GMT');
  10. header('etag: '.($etag));
  11.  

Creo que ya sería todo...
En resumen, ¿de está manera ya no tendría ese problema? (no sé si esta vez lo apliqué bien)
Así está guay. Puede configurarlo para todos los archivos de tu web.


Título: Re: [Pregunta]: ¿Cómo agregar una nueva versión siendo esta ya visible para todos?
Publicado por: #!drvy en 28 Noviembre 2020, 13:29 pm
Esas cabeceras las deberías de aplicar en tu servidor http, vease, apache, nginx litespeed etc... no en PHP ... puesto que estas añadiendo una sobrecarga y solo lo aplicas a archivos PHP.

Saludos


Título: Re: [Pregunta]: ¿Cómo agregar una nueva versión siendo esta ya visible para todos?
Publicado por: Leguim en 28 Noviembre 2020, 14:24 pm
Ahh pensé que así era para el servidor, como se haría entonces a dónde debería ir?

Gracias.


Título: Re: [Pregunta]: ¿Cómo agregar una nueva versión siendo esta ya visible para todos?
Publicado por: @XSStringManolo en 28 Noviembre 2020, 16:45 pm
Depende del servidor que uses y los permisos de adminstración que tengas en él.


Título: Re: [Pregunta]: ¿Cómo agregar una nueva versión siendo esta ya visible para todos?
Publicado por: Leguim en 28 Noviembre 2020, 16:48 pm
Apache, más que eso no te puedo decir porque no sé...


Título: Re: [Pregunta]: ¿Cómo agregar una nueva versión siendo esta ya visible para todos?
Publicado por: @XSStringManolo en 28 Noviembre 2020, 18:07 pm
https://httpd.apache.org/docs/current/mod/mod_headers.html
Si usas un hosting mira su documentación o pregunta si tienen alguna comunidad.