根据时间在脚本标签和样式表中添加动态版本(变量)

10
<script src="/assets/abc.js?v='+new Date.getTime();" type="text/javascript"></script>

<link href="/assets/cder.css?v='+new Date.getTime();"  rel="stylesheet"></link>
或者,
var myVariable = Math.floor(Math.random() * 999999999999);
<script src="/assets/abc.js?v='+myVariable ;" type="text/javascript"></script>

<link href="/assets/cder.css?v='+new Date.getTime();"  rel="stylesheet"></link>

我已经按照以下方式尝试,但脚本在网络选项卡上没有加载。

<script type="text/javascript>
    var script = document.createElement('script');
    script.setAttribute('src', '/assets/abc.js?v=' + new Date.getTime());
    var head1 = document.getElementsByTagName("head")[0];
    head1.appendChild(script);
</script>

我正在尝试在脚本标签和样式表中添加动态版本(变量),基于当前时间或某些动态变量?

如果可能,请帮助我找到最短和高效的解决方案。

如何实现?


1
日期和时间是否必要?我有一个类似的解决方案,但使用版本号而不是日期和时间。 - Luke Walker
请问您能否展示一下,变量应该是动态的,并且在脚本或样式表加载后不应与先前的变量值匹配。 - Mahi
啊,我明白了。我的版本在每次推送代码时都能够很好地用于生产环境,而不是基于“重新加载”的基础上使用。 - Luke Walker
你需要这个用于生产版本,以防止您的网站的新版本缓存还是只是在开发中使用?如果您指定了想要的目的,我可以帮助您。 - molikh
@molikh,我在想,上述标签所在的是index.html,是否与该index.html是用于生产还是开发有关。如果你能帮我解决其中任意一个问题,那就可以解决我的问题了。 - Mahi
9个回答

8
如果你正在寻找最短的解决方案,那么这个怎么样?
<script>document.write('<link href="/assets/cder.css?v=' + Date.now() + '" rel="stylesheet" />');</script>

一个值得考虑的替代方案应该是:
<script>
    var link = document.createElement('link');
    link.rel = 'stylesheet';
    link.href = '/assets/cder.css?v=' + Date.now();
    document.body.appendChild(link);
</script>

好的,您必须按照以下方式转义闭合脚本标记:

<script>document.write('<script src="/assets/abc.js?v=' + Date.now() + '"><\/script>');</script>

如何添加多个脚本的示例:

<script>
  var scripts = [
    '/assets/abc.js',
    '/assets/def.js',
  ];

  for (var i = 0; i < scripts.length; i++) {
    var script = document.createElement('script');
    script.onerror = function() {
      alert('Could not load ' + this.src);
    };
 
    script.src = scripts[i] + '?v=' + Date.now();
    document.body.appendChild(script);
  }
</script>


谢谢,您能否提供一些脚本的类似解决方案呢?我在头部标签中加载了7个脚本,而我需要的两个脚本与样式表类似。 - Mahi
1
请检查我的更新。顺便说一句,在询问这样基本的问题之前,似乎您需要使用搜索功能。 - Victor
<script> var link = document.createElement('script'); link.type= 'text/javascript'; link.src= '/assets/cder.js?v=' + Date.now(); document.body.appendChild(link); </script> <script> var link1 = document.createElement('script'); link1.type= 'text/javascript'; link1.src= '/assets/abc.js?v=' + Date.now(); document.body.appendChild(link1);</script> - Mahi
也许这是一个基本问题。但是,我不知道它的答案。如果我尝试运行我的两个脚本,我在评论中提供的解决方案无法工作。请问我做错了什么? - Mahi
然而,你的两个最短的解决方案都有效,但是另一种解决方案在网络选项卡上不可见。这是我一直面临的问题。 - Mahi
显示剩余3条评论

3
你可以通过 JavaScript 动态地完成这个操作。
<script>
var my_awesome_script = document.createElement('script');
my_awesome_script.setAttribute('src', '/assets/abc.js?v='+new Date.getTime()); //was missing single quote
document.head.appendChild(my_awesome_script);
</script>

taken from Stack overflow answer


我已经尝试过了,但是脚本在网络选项卡上没有被加载。 - Mahi
这个怎么样?https://dev59.com/fHI-5IYBdhLWcg3wbHm-#1867135 - Vaggelis Ksps
我认为这会对你有所帮助,但对我来说,如果可能的话,最好的方法是从后端完成所有这些工作。Javascript在浏览器中运行,因此用户必须等待所有这些计算和请求完成,才能获得dom的正确视图。我不确定如果一个脚本或css文件在页面加载后加载,用户体验是否相同。 - Vaggelis Ksps

1

看起来你对 htmljavascript 感到困惑。

使用混淆了 javascripthtml 来实现某些功能是不可能的。


使用 SSR(服务器端渲染)

使用像 Handlebars 或其他模板引擎。

时间戳(以及您的版本标记)应在生成html之前在服务器端呈现。

<script src="/assets/abc.js?v='+new Date.getTime();" type="text/javascript"></script>

<link href="/assets/cder.css?v='+new Date.getTime();"  rel="stylesheet"></link>

没有服务器端渲染(SSR)

我们可以在HTTP请求返回html后使用javascript来实现。

let script = document.createElement('script');

script.setAttribute('src', `somefile?v=${Date.now()}`);

document.head.appendChild(script);

最好封装一个函数来完成这项工作。

0
从我所做的所有测试来看,似乎最终尝试在使用[0]而不是[6]或其他任何值时都能完美运行。另外,为什么你有多个head标签?这是打字错误吗?你是指header吗?它似乎可以适用于任意数量的headers。
但实际上,如果可能的话,这种类型的事情应该通过后端处理。

抱歉,那是一个笔误。问题已更新,之前的描述并没有帮助。 - Mahi

0

虽然其他回答在脚本中正确地描述了如何完成这个任务,但我想指出三件事:

  1. 您应该使用哈希而不是时间戳来构建缓存,否则每次日期更改时都会清除您的缓存。那不是一个很好的用户体验。在何时以及为什么获取数据,请有意识地决定。Webpack 有一个 nifty build plugin 用于在文件名中创建哈希。
  2. 使用 headers 来驱动是否应该获取新文件。
  3. 确保您在任何运行时 <script> 元素上设置了 async 属性,否则会降低性能,有时会显着降低。搜索引擎严重处罚此类行为。

```

```

但请注意,无论是否使用async属性,附加脚本标记都会阻止渲染。阅读此处以获取更多详细信息


嗨,请举个例子以便更好地理解。 - Mahi

0
<script [src]="'/assets/abc.js?v='+new Date.getTime();" type="text/javascript"></script>

如果它没有起作用,请尝试创建模型并像这样操作:
this.someModel = "/assets/abc.js?v='"+new Date.getTime();
<script [src]="script" type="text/javascript"></script>

还有更多的方法可以实现它。


无法工作,脚本未显示在网络选项卡中。 - Mahi
有点奇怪,你试过把脚本放在头部看看它是否真的加载了吗?因为你说的有点奇怪。 - Talg123

0

const time = new Date(2018, 10, 24, 22); // you can provide minutes and seconds if you want
const today = new Date();
const head = document.querySelector('html head');
const body = document.querySelector('html body'); 

const styleFile = '<link href="/assets/cder.css?v=' + today.getTime() + '"  rel="stylesheet"></link>';
const scriptFile = '<script src="/assets/abc.js?v=' + today.getTime() + '" type="text/javascript"></script>';

setInterval(() => {
  if ((time.getDate() === today.getDate()) && (time.getMonth() === today.getMonth()) && (time.getFullYear() === today.getFullYear()) && (time.getHours() === today.getHours())) {
    head.append(styleFile);
    body.append(scriptFile);
  }
}, 60000);
<html>
  <head>
    <!-- here we will append style file -->
  </head>
  <body>
    <div>some dummy text</div>
    <!-- here we will append script file -->
  </body>
</html>

为什么要使用setInterval这是我们告诉浏览器的方法:“请每分钟检查一次条件是否成立”,如果成立,就会添加新的styleFilescriptFile
注意:你也可以在时间中提供分钟,但记得在if(...){}中加入适当的条件。


0

我尝试使用上述一些示例,但性能受到影响,因为js文件将在每次用户登录时加载。

下面的方法将确保仅在提供新版本时加载js。

步骤1:在您的主布局页面中添加一个隐藏/(非隐藏)元素,如下所示,其中包含您的最新构建编号。

<p id="BuildNumber">Build Number : @System.Diagnostics.FileVersionInfo.GetVersionInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", "<yourDllName>.dll")).FileVersion
</p>

步骤2:使用以下脚本标签对您的JS文件进行版本控制,请根据您的使用情况更新脚本类型。

<script>
    var script = document.createElement('script');
    script.setAttribute('src', '/Scripts/Common/<fileName>.min.js?v=' + document.querySelector('#BuildNumber').innerHTML.split(': ')[1]);
    script.type = 'text/babel';
    document.head.appendChild(script);
</script>

0

你的脚本没有加载,因为它不是new Date.getTime(),而是new Date().getTime(),或者使用Date.now()。另外,为了防止浏览器缓存,你可以添加一个no-cache标头,例如使用.htaccess

<filesMatch "\.(js|css)">
  FileETag None
  <ifModule mod_headers.c>
     Header unset ETag
     Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
     Header set Pragma "no-cache"
     Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
  </ifModule>
</filesMatch>

<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/javascript "access plus 1 seconds"
ExpiresByType text/css "access plus 1 seconds"
</IfModule>

对于 JavaScript 函数而言

function appendJS(url) {
  var s = document.createElement('script');
  s.src = url + '?v=' + Date.now();
  document.body.appendChild(s);
}

function appendCSS(url) {
  var s = document.createElement('link');
  s.rel = 'stylesheet';
  s.href = url + '?v=' + Date.now();
  document.body.appendChild(s);
}
appendJS('/assets/abc.js');
appendCSS('/assets/cder.css');

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接