Angular 应用程序必须在新部署后清除缓存

IT技术 javascript angular nginx deployment
2021-01-16 07:02:05

我们有一个 Angular 6 应用程序。它在 Nginx 上提供。并且 SSL 已开启。

当我们部署新代码时,大多数新功能都可以正常工作,但对于某些更改则不行。例如,如果前端开发人员更新服务连接并部署它,用户必须打开隐身窗口或清除缓存才能看到新功能。

哪些类型的更改不会自动更新?为什么他们与其他人不同?

避免该问题的常见解决方案是什么?

3个回答

问题是当一个静态文件被缓存时,它可以在它到期之前存储很长时间。如果您对站点进行更新,这可能会很麻烦,但是,由于文件的缓存版本存储在访问者的浏览器中,他们可能无法看到所做的更改。

Cache-busting通过使用唯一的文件版本标识符来告诉浏览器该文件的新版本可用,从而解决了浏览器缓存问题。因此浏览器不会从缓存中检索旧文件,而是向源服务器请求新文件。

Angular cli 通过为--output-hashingbuild 命令提供一个标志来解决这个问题

检查官方文档:https : //angular.io/cli/build

示例(旧版本)

ng build --prod --aot --output-hashing=all

以下是您可以传入的选项 --output-hashing

  • none:不执行散列
  • 媒体:仅向通过 [url|file]-loaders 处理的文件添加哈希
  • 捆绑包:仅向输出捆绑包添加哈希
  • 全部:向媒体和捆绑包添加哈希

更新

对于较新版本的 angular(例如 Angular 10),该命令现已更新:

ng build --prod --aot --outputHashing=all
谢谢。如果我使用这个命令,它是只影响当前应用程序还是整个浏览器?
2021-03-17 07:02:05
@zhangjinzhou 更新了答案并附有说明,如果对您有帮助,请标记为答案
2021-03-18 07:02:05
有用。谢谢你的解决方案。你能解释一下什么情况会导致这个问题吗?正如我所提到的,并非所有更新都会出现此问题。
2021-03-26 07:02:05
不幸的是,这对我不起作用,最新的 CLI 已经在 angular.json 中为所有环境添加了 outputHashing:all。:(
2021-03-30 07:02:05
感谢您的解释!
2021-04-02 07:02:05

为我补充:

    ng build --aot --output-hashing=all

当您的应用程序位于 CDN 和良好的缓存 nginx 配置后面时,仅构建命令是不够的。

1-第一件事是删除 html 文件的缓存(nginx):

    location ~ \.(html)$ {
        add_header Pragma "no-cache";
        add_header Cache-Control "no-store";
        add_header strict-transport-security "max-age=31536000";
        add_header X-Frame-Options "SAMEORIGIN";
        try_files $uri $uri/ /index.html;
    }

对于静态文件(js/css ...),让缓存工作(网络性能/可用性):

    location ~ \.(css|htc|less|js|js2|js3|js4)$ {
        expires 31536000s;
        add_header Pragma "public";
        add_header Cache-Control "max-age=31536000, public";
        try_files $uri $uri/ /index.html;
    }

2- 保留 dev/prod 构建完全相同,用于测试目的。最终构建 dev 命令:

    ng build --env=dev --aot=true --output-hashing=all --extract-css=true 

3- 我们需要在每次部署时客户端浏览器从服务器而不是从缓存加载所有 javascript 文件,即使部署是一个小更新。就像 angular 有一些错误:https : //github.com/angular/angular-cli/issues/10641 并且发生在我身上。

我结束了使用 bash 的功能,这是我使用 package.json 文件在每个开发(prod/dev)上杀死缓存的脚本:

"scripts": {
 ...
    "deploy_dev": "ng build --env=dev --aot=true --output-hashing=all --extract-css=true && npm run add_date",
    "deploy_prd": "ng build --prod && npm run add_date",
    "add_date": "npm run add_date_js && npm run add_date_css && npm run rm_bak_files",
    "add_date_js": "for i in dist/*; do if [ -f $i ]; then LC_ALL=C sed -i.bak 's:js\":js?'$(date +%H%M%m%d%y)'\":g' $i; fi done",
    "add_date_css": "sed -i.bak 's:css\":css?'$(date +%H%M%m%d%y)'\":g' dist/index.html",
    "rm_bak_files": "find dist -name '*.bak' -exec rm -Rf {} \\;"
},

命令解释:
add_date_js:用“js?{date+%H%M%m%d%y}”查找并替换所有文件“js”
add_date_css:在dist/index.html中查找和替换“css”为“css? {date+%H%M%m%d%y}"
rm_bak_files:删除所有 .bak 文件(网络性能)

这些 sed 命令适用于 GNU/BSD/Mac。

链接:
Angular - Prod Build 不生成唯一的哈希值
sed 就地标志,适用于 Mac (BSD) 和 Linux
RE 错误:Mac OS X 上的非法字节序列
如果 shell 脚本内联
如何循环目录中的文件并更改路径和向文件名添加后缀
是否可以使用 angular-cli 构建单独的 CSS 文件?

你好@k.vincent 你需要检查你的 dist 目录结构,这些命令假设你的 dist 文件夹有应用程序 dist/index.html,如果你有你的 dist/{appName} 命令将失败
2021-03-22 07:02:05
是的,我确实有不同的结构,例如:dist/{appName}/{lang}。这是否意味着它仅适用于以下结构:dist/
2021-03-24 07:02:05
@AlejoJM,我知道……这个答案已经很老了。但是用于重命名 javascript 文件的脚本不起作用。没有重命名没有文件!默默地执行
2021-03-30 07:02:05
Isaac,我没有 Win,但你可以很容易地制作一个 docker 来做到这一点
2021-04-11 07:02:05

虽然上面接受的答案会起作用,但应该angular.jsonconfigurations=> <my-env-name>=> outputHashing=> 下设置为all(对于生产环境)进行此调整

简化示例:

{
  "projects": {
    "<my-project>": {
      "architect": {
        "build": {
          "configurations": {
            "<my-env-name>": {
              "outputHashing": "all"
            }
          }
        }
      }
    }
  }
}

正如所述帖子中所述,此配置的可用选项:

  • none : 不执行散列
  • media : 只向通过 [url|file]-loaders 处理的文件添加哈希
  • bundles:只向输出包添加哈希
  • all:向媒体和捆绑包添加哈希
有关使用 Angular 环境的更多信息,请参阅文档中的此页面
2021-04-05 07:02:05