如何防止Angular 2站点上的浏览器缓存?

Rik*_*121 80 caching cache-control browser-cache angular2-template angular

我们目前正在开发一个新项目,定期更新,我们的客户每天都会使用这些更新.该项目正在使用角度2开发,我们面临缓存问题,即我们的客户没有看到他们的机器上的最新变化.

主要是js文件的html/css文件似乎得到了正确的更新而没有给出太多麻烦.

Jac*_*ack 144

angular-cli通过为build命令提供--output-hashing标志来解决这个问题.用法示例:

ng build --output-hashing=all
Run Code Online (Sandbox Code Playgroud)

Bundling&Tree-Shaking提供了一些细节和背景.运行ng help build,记录标志:

--output-hashing=none|all|media|bundles (String) Define the output filename cache-busting hashing mode.
aliases: -oh <value>, --outputHashing <value>
Run Code Online (Sandbox Code Playgroud)

虽然这仅适用于angular-cli的用户,但它的工作非常出色,不需要任何代码更改或其他工具.

  • 这是正确的方法,应该是选定的答案! (11认同)
  • 如果您的index.html被浏览器缓存了,则此方法将不起作用,因此将看不到JavaScript资源的新哈希名称。我认为将此与@Rossco给出的答案结合起来是有意义的。使它与发送的HTTP标头保持一致也很有意义。 (4认同)
  • 这对我们的应用程序不起作用。遗憾的是带有查询字符串参数的 templateUrl 不能与 CLI 一起使用 (2认同)
  • @stryba这就是为什么html缓存应该有所不同的原因。您应该指定Cache-Control,Pragma和Expires响应头,以便不进行缓存。如果您使用的是后端框架,那么这很容易,但是我相信您也可以在.htaccess文件中为Apache处理此操作(不过,idk在nginx中是如何工作的)。 (2认同)
  • 这个答案为js文件添加了一个哈希,这很棒。但是,正如stryba所说,您还需要确保未缓存index.html。您不应使用html meta标签,而应使用响应标头cache-control:no-cache(或其他标头,用于更高级的缓存策略)。 (2认同)

Rik*_*121 35

找到了一种方法,只需添加一个查询字符串来加载组件,如下所示:

@Component({
  selector: 'some-component',
  templateUrl: `./app/component/stuff/component.html?v=${new Date().getTime()}`,
  styleUrls: [`./app/component/stuff/component.css?v=${new Date().getTime()}`]
})
Run Code Online (Sandbox Code Playgroud)

这应该强制客户端加载服务器的模板副本而不是浏览器的副本.如果您希望仅在一段时间后刷新它,则可以使用此ISOString:

new Date().toISOString() //2016-09-24T00:43:21.584Z
Run Code Online (Sandbox Code Playgroud)

并对一些字符进行子字符串处理,以便它只会在一小时后更改,例如:

new Date().toISOString().substr(0,13) //2016-09-24T00
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助

  • 每次即使不更改代码也要破坏高速缓存时,高速缓存有什么意义呢? (8认同)
  • 所以我的实施实际上并没有结束.缓存是一个奇怪的问题.有时工作,有时不工作.哦,间歇性问题的美丽.所以我实际上调整了你的答案:`templateUrl:'./ app/shared/menu/menu.html?v ='+ Math.random()` (3认同)

Ros*_*sco 17

在每个html模板中,我只在顶部添加以下元标记:

<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
Run Code Online (Sandbox Code Playgroud)

根据我的理解,每个模板都是独立的,因此它不会继承index.html文件中的元无缓存规则设置.

  • 我们已经切换到webpack一段时间了,它负责缓存破坏我们的角度应用程序.很高兴知道你的解决方案有效.谢谢 (3认同)

Nia*_*h14 9

@Jack 的回答和 @ranierbit 的回答相结合应该可以解决问题。

为 --output-hashing 设置 ng build 标志,以便:

ng build --output-hashing=all
Run Code Online (Sandbox Code Playgroud)

然后在服务中或在您的 app.module

@Injectable()
export class NoCacheHeadersInterceptor implements HttpInterceptor {
    intercept(req: HttpRequest<any>, next: HttpHandler) {
        const authReq = req.clone({
            setHeaders: {
                'Cache-Control': 'no-cache',
                 Pragma: 'no-cache'
            }
        });
        return next.handle(authReq);    
    }
}
Run Code Online (Sandbox Code Playgroud)

然后将其添加到您的提供者中app.module

providers: [
  ... // other providers
  {
    provide: HTTP_INTERCEPTORS,
    useClass: NoCacheHeadersInterceptor,
    multi: true
  },
  ... // other providers
]
Run Code Online (Sandbox Code Playgroud)

这应该可以防止在客户端计算机的实时站点上出现缓存问题


小智 7

将其添加到您的 nginx

location ~ /index.html|.*\.json$ {
        expires -1;
        add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
    }

location ~ .*\.css$|.*\.js$ {
   add_header Cache-Control 'max-age=31449600'; # one year
}

location / {
    try_files $uri $uri/ /index.html?$args;
    add_header Cache-Control 'max-age=86400'; # one day
}
Run Code Online (Sandbox Code Playgroud)

  • 如果我不使用 NGINX 怎么办? (2认同)