Hoe kan ik clients dwingen JavaScript-bestanden te vernieuwen?

We werken momenteel in een privé-bèta en zijn dus nog steeds bezig met het maken van vrij snelle wijzigingen, hoewel we dit proces uiteraard zullen vertragen naarmate het gebruik begint toe te nemen. Dat gezegd hebbende, een probleem waar we tegenaan lopen, is dat nadat we een update met nieuwe JavaScript-bestanden hebben uitgebracht, de clientbrowsers nog steeds de gecachte versie van het bestand gebruiken en de update niet zien. Het is duidelijk dat we ze tijdens een ondersteuningsoproep eenvoudig kunnen informeren om een ​​ctrlF5-vernieuwing uit te voeren om ervoor te zorgen dat ze de up-to-date bestanden van de server krijgen, maar het zou dit bij voorkeur voor die tijd afhandelen.

Onze huidige gedachte is om simpelweg een versienummer toe te voegen aan de naam van de JavaScript-bestanden en wanneer er wijzigingen worden aangebracht, de versie van het script te verhogen en alle verwijzingen bij te werken. Hiermee wordt de klus zeker geklaard, maar het bijwerken van de referenties op elke release kan omslachtig worden.

Omdat ik zeker weet dat we niet de eersten zijn die hiermee te maken hebben, dacht ik, ik leg het voor aan de community. Hoe zorgt u ervoor dat klanten hun cache bijwerken wanneer u uw code bijwerkt? Als u de hierboven beschreven methode gebruikt, gebruikt u dan een proces dat de wijziging vereenvoudigt?


Antwoord 1, autoriteit 100%

Voor zover ik weet is een veelvoorkomende oplossing het toevoegen van een ?<version>aan de src-link van het script.

Bijvoorbeeld:

<script type="text/javascript" src="myfile.js?1500"></script>

Ik neem op dit moment aan dat er geen betere manier is dan zoeken-vervangen om deze “versienummers” in alle scripttags te verhogen?

Misschien laat een versiebeheersysteem dat voor u doen? De meeste versiecontrolesystemen hebben bijvoorbeeld een manier om het revisienummer automatisch in te voeren bij het inchecken.

Het zou er ongeveer zo uitzien:

<script type="text/javascript" src="myfile.js?$$REVISION$$"></script>

Natuurlijk zijn er altijd betere oplossingen zoals deze.


Antwoord 2, autoriteit 18%

Het toevoegen van de huidige tijd aan de URL is inderdaad een veelvoorkomende oplossing. U kunt dit desgewenst echter ook op webserverniveau beheren. De server kan worden geconfigureerd om verschillende HTTP-headers voor javascript-bestanden te verzenden.

Als u bijvoorbeeld wilt dat het bestand niet langer dan 1 dag in de cache wordt opgeslagen, stuurt u het volgende:

Cache-Control: max-age=86400, must-revalidate

Als u de gebruiker wilt dwingen om altijd de nieuwste versie te krijgen, gebruikt u voor bèta:

Cache-Control: no-cache, must-revalidate

Antwoord 3, autoriteit 8%

Google Page-Speed: neem geen zoekreeks op in de URL voor statische bronnen.
De meeste proxy’s, met name Squid tot en met versie 3.0, cachen bronnen niet met een “?” in hun URL, zelfs als een Cache-control: public header aanwezig is in het antwoord. Als u proxycaching voor deze bronnen wilt inschakelen, verwijdert u queryreeksen van verwijzingen naar statische bronnen en codeert u in plaats daarvan de parameters in de bestandsnamen zelf.

In dit geval kunt u de versie opnemen in de URL, bijvoorbeeld: http://abc.com/v1.2/script.js en gebruik apache mod_rewrite om de link om te leiden naar http://abc.com/script.js. Wanneer u de versie wijzigt, zal de clientbrowser het nieuwe bestand bijwerken.


Antwoord 4, autoriteit 6%

Dit gebruik is beëindigd:
https://developer.mozilla.org/en-US/docs/ Web/HTML/Using_the_application_cache

Dit antwoord is slechts 6 jaar te laat, maar ik zie dit antwoord niet op veel plaatsen… HTML5 heeft Applicatiecachedie wordt gebruikt om dit probleem op te lossen. Ik ontdekte dat de nieuwe servercode die ik aan het schrijven was oude javascript in de browsers van mensen crashte, dus ik wilde een manier vinden om hun javascript te laten verlopen. Gebruik een manifestbestand dat er als volgt uitziet:

CACHE MANIFEST
# Aug 14, 2014
/mycode.js
NETWORK:
*

en genereer dit bestand met een nieuwe tijdstempel telkens wanneer u wilt dat gebruikers hun cache bijwerken. Als een kanttekening, als u dit toevoegt, zal de browser nietopnieuw laden (zelfs wanneer een gebruiker de pagina ververst) totdat het manifest dit aangeeft.


Antwoord 5, autoriteit 6%

Hoe zit het met het toevoegen van de bestandsgrootte als laadparameter?

<script type='text/javascript' src='path/to/file/mylibrary.js?filever=<?=filesize('path/to/file/mylibrary.js')?>'></script>

Dus elke keer dat u het bestand bijwerkt, verandert de parameter “filever”.

Hoe zit het als u het bestand bijwerkt en uw update resulteert in dezelfde bestandsgrootte? wat zijn de kansen?


Antwoord 6, autoriteit 3%

Niet alle browsers cachen bestanden met ‘?’erin. Wat ik deed om ervoor te zorgen dat het zoveel mogelijk in de cache werd opgeslagen, heb ik de versie in de bestandsnaam opgenomen.

Dus in plaats van stuff.js?123deed ik stuff_123.js

Ik gebruikte mod_redirect(denk ik) in apache om have stuff_*.jste hebben om naar stuff.js

te gaan


Antwoord 7, autoriteit 2%

Voor ASP.NET-pagina’s gebruik ik het volgende

VOOR

<script src="/Scripts/pages/common.js" type="text/javascript"></script>

NA (herladen geforceerd)

<script src="/Scripts/pages/common.js?ver<%=DateTime.Now.Ticks.ToString()%>" type="text/javascript"></script>

Het toevoegen van DateTime.Now.Ticks werkt erg goed.


Antwoord 8, autoriteit 2%

Het is tegenwoordig gebruikelijk om een ​​inhoud-hashcode te genereren als onderdeel van de bestandsnaam om de browser, met name IE, te dwingen de javascript- of css-bestanden opnieuw te laden.

Bijvoorbeeld

verkoper.a7561fb0e9a071baadb9.js
hoofd.b746e3eb72875af2caa9.js

Het is over het algemeen de taak voor de bouwtools zoals webpack. Hier zijn meer detailsals iemand wil uitproberen of je een webpack gebruikt.


Antwoord 9

Voor ASP.NET veronderstel ik volgende oplossing met geavanceerde opties (debug/release-modus, versies):

Js- of Css-bestanden die op een dergelijke manier zijn opgenomen:

<script type="text/javascript" src="Scripts/exampleScript<%=Global.JsPostfix%>" />
<link rel="stylesheet" type="text/css" href="Css/exampleCss<%=Global.CssPostfix%>" />

Global.JsPostfix en Global.CssPostfix worden op de volgende manier berekend in Global.asax:

protected void Application_Start(object sender, EventArgs e)
{
    ...
    string jsVersion = ConfigurationManager.AppSettings["JsVersion"];
    bool updateEveryAppStart = Convert.ToBoolean(ConfigurationManager.AppSettings["UpdateJsEveryAppStart"]);
    int buildNumber = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Revision;
    JsPostfix = "";
#if !DEBUG
    JsPostfix += ".min";
#endif      
    JsPostfix += ".js?" + jsVersion + "_" + buildNumber;
    if (updateEveryAppStart)
    {
        Random rand = new Random();
        JsPosfix += "_" + rand.Next();
    }
    ...
}

Antwoord 10

Als u de pagina genereert die naar de JS-bestanden linkt, is een eenvoudige oplossing om het tijdstempel van de laatste wijziging van het bestand toe te voegen aan de gegenereerde links.

Dit lijkt erg op Huppie’s antwoord, maar werkt in versiecontrolesystemen zonder trefwoordvervanging. Het is ook beter dan de huidige tijd toe te voegen, omdat dat caching zou voorkomen, zelfs als het bestand helemaal niet is gewijzigd.


Antwoord 11

In PHP:

function latest_version($file_name){
    echo $file_name."?".filemtime($_SERVER['DOCUMENT_ROOT'] .$file_name);
}

In HTML:

<script type="text/javascript" src="<?php latest_version('/a-o/javascript/almanacka.js'); ?>">< /script>

Hoe het werkt:

In HTML, schrijf het filepathen de naam zoals je zou doen, maar alleen in de functie.
PHP haalt de filetimevan het bestand op en retourneert het filepath+name+"?"+timevan de laatste wijziging


Antwoord 12

We hebben een SaaS voor gebruikers gemaakt en hen een script gegeven om aan hun websitepagina toe te voegen, en het was niet mogelijk om een ​​versie met het script toe te voegen, aangezien de gebruiker het script voor functionaliteit aan hun website zal toevoegen en ik kan’ hen niet dwingen om de versie te wijzigen elke keer dat we het script bijwerken

We hebben dus een manier gevonden om de nieuwere versie van het script te laden telkens wanneer de gebruiker het originele script aanroept

de scriptlink die aan de gebruiker is verstrekt

<script src="https://thesaasdomain.com/somejsfile.js" data-ut="user_token"></script>

het scriptbestand

if($('script[src^="https://thesaasdomain.com/somejsfile.js?"]').length !== 0) {
   init();
} else {
   loadScript("https://thesaasdomain.com/somejsfile.js?" + guid());
}
var loadscript = function(scriptURL) {
   var head = document.getElementsByTagName('head')[0];
   var script = document.createElement('script');
   script.type = 'text/javascript';
   script.src = scriptURL;
   head.appendChild(script);
}
var guid = function() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}
var init = function() {
    // our main code
}

Uitleg:

De gebruiker heeft het aan hem verstrekte script op zijn website bijgevoegd en we hebben gecontroleerd of het unieke token dat bij het script is gevoegd, bestaat of niet met behulp van jQuery-selector en zo niet, laad het dan dynamisch met een nieuwere token (of versie)

Dit is hetzelfde script twee keer aanroepen, wat een prestatieprobleem zou kunnen zijn, maar het lost echt het probleem op om het script te dwingen niet uit de cache te laden zonder de versie in de daadwerkelijke scriptlink te plaatsen die aan de gebruiker of client is gegeven

p>

Disclaimer: niet gebruiken als prestaties in uw geval een groot probleem zijn.


Antwoord 13

De jQuery-functie getScript kan ook worden gebruikt om ervoor te zorgen dat er inderdaad een js-bestand wordt geladen telkens wanneer de pagina wordt geladen.

Dit is hoe ik het deed:

$(document).ready(function(){
    $.getScript("../data/playlist.js", function(data, textStatus, jqxhr){
         startProgram();
    });
});

Controleer de functie op http://api.jquery.com/jQuery.getScript/

Standaard stelt $.getScript() de cache-instelling in op false. Dit voegt een queryparameter met tijdstempel toe aan de verzoek-URL om ervoor te zorgen dat de browser het script downloadt telkens wanneer het wordt aangevraagd.


Antwoord 14

Mijn collega vond net een verwijzing naar die methode nadat ik (met verwijzing naar css) had gepost op http://www.stefanhayden.com/blog/2006/04/03/css-caching-hack/. Goed om te zien dat anderen het gebruiken en het lijkt te werken. Ik neem aan dat er op dit moment geen betere manier is dan zoeken-vervangen om deze “versienummers” in alle scripttags te verhogen?


Antwoord 15

In asp.net mvc kunt u @DateTime.UtcNow.ToString()gebruiken voor het versienummer van het js-bestand. Versienummer automatisch gewijzigd met datum en u dwingt de browser van de klant om het js-bestand automatisch te vernieuwen. Ik gebruik deze methode en dit werkt goed.

<script src="~/JsFilePath/[email protected]()"></script>

Antwoord 16

Een oplossing is om een ​​queryreeks met een tijdstempel erin toe te voegen aan de URL bij het ophalen van de bron. Dit maakt gebruik van het feit dat een browser geen bronnen in de cache opslaat die zijn opgehaald van URL’s met queryreeksen erin.

U wilt waarschijnlijk niet dat de browser deze bronnen helemaal niet in de cache opslaat; het is waarschijnlijker dat u ze in de cache wilt, maar u wilt dat de browser een nieuwe versie van het bestand ophaalt wanneer deze beschikbaar wordt gemaakt.

De meest gebruikelijke oplossing lijkt te zijn om een ​​tijdstempel of revisienummer in de bestandsnaam zelf in te voegen. Dit is wat meer werk, omdat je code moet worden aangepast om de juiste bestanden op te vragen, maar het betekent dat b.v. versie 7 van uw snazzy_javascript_file.js(dwz snazzy_javascript_file_7.js) wordt in de browser opgeslagen totdat u versie 8 uitbrengt, waarna uw code verandert om snazzy_javascript_file_8.jsin plaats daarvan.


Antwoord 17

Het voordeel van het gebruik van een file.js?V=1boven een fileV1.jsis dat u niet meerdere versies van de JavaScript-bestanden op de server.

Het probleem dat ik zie met file.js?V=1is dat er afhankelijke code in een ander JavaScript-bestand kan zijn die breekt bij gebruik van de nieuwe versie van de bibliotheekhulpprogramma’s.

Omwille van achterwaartse compatibiliteit denk ik dat het veel beter is om jQuery.1.3.jste gebruiken voor je nieuwe pagina’s en bestaande pagina’s jQuery.1.1.js, totdat u klaar bent om de oudere pagina’s te upgraden, indien nodig.


Antwoord 18

Gebruik een versie GETvariabele om browsercaching te voorkomen.

Het toevoegen van ?v=AUTO_INCREMENT_VERSIONaan het einde van uw url voorkomt browsercaching – het vermijden van alle in de cache opgeslagen scripts.


Antwoord 19

Cache-busting in ASP.NET Core via een tag-helper zal dit voor u afhandelen en uw browser toestaan ​​scripts/css in de cache te bewaren totdat het bestand verandert. Voeg eenvoudig de tag helper asp-append-version=”true” toe aan uw script (js) of link (css) tag:

<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true"/>

Dave Paquette heeft hier een goed voorbeeld en uitleg van cachebusting (onderaan de pagina) Cache-busting


Antwoord 20

location.reload(true);

zie https://www.w3schools.com/jsref/met_loc_reload.asp

Ik roep deze regel code dynamisch aan om ervoor te zorgen dat javascript opnieuw is opgehaald van de webserver in plaats van uit de cache van de browser om aan dit probleem te ontsnappen.


Antwoord 21

Hoewel het framework specifiek is, heeft Django 1.4 de staticfiles app-functionaliteitdie op een vergelijkbare manier werkt als de ‘greenfelt’-site in de bovenstaand antwoord


Antwoord 22

Een eenvoudige manier.
htaccess bewerken

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} \.(jpe?g|bmp|png|gif|css|js|mp3|ogg)$ [NC]
RewriteCond %{QUERY_STRING} !^(.+?&v33|)v=33[^&]*(?:&(.*)|)$ [NC]
RewriteRule ^ %{REQUEST_URI}?v=33 [R=301,L]

Antwoord 23

U kunt een bestandsversie aan uw bestandsnaam toevoegen, zodat deze er zo uitziet:

https://www.example.com/script_fv25.js

fv25 => bestand versie nr. 25

En in je .htaccess plaats dit blok dat het versiegedeelte van de link zal verwijderen:

RewriteEngine On
RewriteRule (.*)_fv\d+\.(js|css|txt|jpe?g|png|svg|ico|gif) $1.$2 [L]

dus de laatste link is:

https://www.example.com/script.js

Antwoord 24

Een simpele truc die voor mij prima werkt om conflicten tussen oudere en nieuwere javascript-bestanden te voorkomen. Dat betekent: als er een conflict is en er een fout optreedt, wordt de gebruiker gevraagd om op Ctrl-F5 te drukken.

Voeg bovenaan de pagina iets toe als

<h1 id="welcome"> Welcome to this page <span style="color:red">... press Ctrl-F5</span></h1>

ziet eruit als

voer hier de afbeeldingsbeschrijving in

Laat deze regel javascript de laatste zijn die wordt uitgevoerd bij het laden van de pagina:

document.getElementById("welcome").innerHTML = "Welcome to this page"

In het geval dat er geen fout optreedt, zal de welkomstgroet hierboven nauwelijks zichtbaar zijn en vrijwel onmiddellijk worden vervangen door

voer hier de afbeeldingsbeschrijving in


Antwoord 25

Als u PHP en Javascript gebruikt, zou het volgende voor u moeten werken, vooral in de situatie waarin u meerdere keren wijzigingen aanbrengt in het bestand. Dus elke keer dat u de versie niet kunt wijzigen. Het idee is dus om een ​​willekeurig getal in PHP te maken en dit vervolgens toe te wijzen als een versie van het JS-bestand.

$fileVersion = rand();
<script src="addNewStudent.js?v=<?php echo $fileVersion; ?>"></script>

Antwoord 26

FRONT-END-OPTIE

Ik heb deze code specifiekgemaakt voor degenen die geen instellingen in de backend kunnen wijzigen. In dit geval is de beste manier om een ​​erg lange cache te voorkomen met:

new Date().getTime()

Voor de meeste programmeurs kan de cache echter een paar minuten of uren duren, dus de eenvoudige code hierboven dwingt alle gebruikers om “elke pagina die wordt bekeken” te downloaden. Om aan te geven hoe lang dit item zal blijven zonder opnieuw te laden, heb ik deze code gemaakt en hieronder verschillende voorbeelden achtergelaten:

// cache-expires-after.js v1
function cacheExpiresAfter(delay = 1, prefix = '', suffix = '') { // seconds
    let now = new Date().getTime().toString();
    now = now.substring(now.length - 11, 10); // remove decades and milliseconds
    now = parseInt(now / delay).toString();
    return prefix + now + suffix;
};
// examples (of the delay argument):
// the value changes every 1 second
var cache = cacheExpiresAfter(1);
// see the sync
setInterval(function(){
    console.log(cacheExpiresAfter(1), new Date().getSeconds() + 's');
}, 1000);
// the value changes every 1 minute
var cache = cacheExpiresAfter(60);
// see the sync
setInterval(function(){
    console.log(cacheExpiresAfter(60), new Date().getMinutes() + 'm:' + new Date().getSeconds() + 's');
}, 1000);
// the value changes every 5 minutes
var cache = cacheExpiresAfter(60 * 5); // OR 300
// the value changes every 1 hour
var cache = cacheExpiresAfter(60 * 60); // OR 3600
// the value changes every 3 hours
var cache = cacheExpiresAfter(60 * 60 * 3); // OR 10800
// the value changes every 1 day
var cache = cacheExpiresAfter(60 * 60 * 24); // OR 86400
// usage example:
let head = document.head || document.getElementsByTagName('head')[0];
let script = document.createElement('script');
script.setAttribute('src', '//unpkg.com/[email protected]/dist/sweetalert.min.js' + cacheExpiresAfter(60 * 5, '?'));
head.append(script);
// this works?
let waitSwal = setInterval(function() {
    if (window.swal) {
        clearInterval(waitSwal);
        swal('Script successfully injected', script.outerHTML);
    };
}, 100);

Antwoord 27

Eenvoudigste oplossing? Laat de browser helemaal niet cachen. Voeg de huidige tijd (in ms) toe als een vraag.

(U bevindt zich nog in de bètafase, dus u kunt er redelijkerwijs voor pleiten niet te optimaliseren voor prestaties. Maar YMMV hier.)


Antwoord 28

Hieronder werkte voor mij:

<head>
<meta charset="UTF-8">
<meta http-equiv="cache-control" content="no-cache, must-revalidate, post-check=0, pre-check=0" />
<meta http-equiv="cache-control" content="max-age=0" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
<meta http-equiv="pragma" content="no-cache" />
</head>

Other episodes