【问题标题】:How to clear template cache?如何清除模板缓存?
【发布时间】:2016-01-15 09:31:10
【问题描述】:

在 Angular 2 中,如何清除模板缓存? Angular 1 有很多答案,但 2 没有。

我遇到的问题是,当我在任何组件上更改 templateUrl 引用的 html 页面的内容时,浏览器中的 html 页面不会更改,直到我在浏览器中手动导航到 templateUrl并点击重新加载。我知道你可以在开发过程中禁用浏览器缓存来解决这个问题,但我担心的是,当我用 Angular 2 更新网站时,如果用户将过时的 html 页面缓存在浏览器中,他们会看到过时的 html 页面。

这里是 Angular 1 的堆栈溢出问题的链接 AngularJS disable partial caching on dev machine

下面是一个 sn-p,我在 app.html 更新其内容时遇到问题。

@Component({
    selector: 'photogallery-app',
    templateUrl: './app/app.html',
    directives: [ROUTER_DIRECTIVES, CORE_DIRECTIVES]
})

【问题讨论】:

  • 这可能有效,但我希望有一个全局方法来解决这个问题,而不是为我网站中的每个组件都这样做。
  • 据我所知,您不必这样做,除非您特别说明应该通过实现 routerCanReuse 并返回 true 来重用它们,否则它们总是会被重建,对吗?
  • 我现在遇到了这个问题,那就是没有实现 routerCanReuse 并返回 true。
  • 在进一步阅读 routerCanReuse 以及我观察到的一些行为之后,我可以看到该组件被丢弃并重新使用,因为每次导航到页面时都会进行我的 ajax 调用,但是templateUrl 装饰器属性引用的 html 没有正确更新。

标签: angular


【解决方案1】:

首先导入 TemplateCompiler。

import { TemplateCompiler } from 'angular2/src/compiler/template_compiler';

接下来在你的构造函数中注入 TemplateCompiler。

constructor(private _templateCompiler: TemplateCompiler)

最后用它来清除缓存。请注意,这会清除所有模板。

this._templateCompiler.clearCache();

更新:Angular 2 Beta 17

首先导入 RuntimeCompiler。

import { RuntimeCompiler} from 'angular2/src/compiler/runtime_compiler';

接下来在你的构造函数中注入 RuntimeCompiler。

constructor(private _runtimeCompiler: RuntimeCompiler)

最后用它来清除缓存。请注意,这会清除所有模板。

this._runtimeCompiler.clearCache();

更新:Angular 2 RC 1

首先导入 RuntimeCompiler。

import { RuntimeCompiler} from '@angular/compiler/src/runtime_compiler';

接下来在你的构造函数中注入 RuntimeCompiler。

constructor(private _runtimeCompiler: RuntimeCompiler)

最后用它来清除缓存。请注意,这会清除所有模板。

this._runtimeCompiler.clearCache();

更新:Angular 2 RC 4

首先导入 RuntimeCompiler。

注意 RC1 的路径变化。如果与 RC4 一起使用,则为 RC1 列出的路径在调用 .ClearCache() 时会引发错误

import { RuntimeCompiler} from '@angular/compiler';

接下来在你的构造函数中注入 RuntimeCompiler

constructor(private _runtimeCompiler: RuntimeCompiler)

最后用它来清除缓存。请注意,这会清除所有模板。

this._runtimeCompiler.clearCache();

更新:Angular 2.0.0 (RTM)

这是不可能的。我有一个应用程序,为登录用户提供一组模板,为未登录用户提供另一组模板。升级到 2.0.0 后,我看不出有办法完成相同的任务。虽然我试图找出重新构建应用程序的最佳方法,但我却采用了这种方法:

location.reload();

这有效(但显然会重新加载整个页面)。

【讨论】:

  • 很好的解决方案。我只是在登录时进行此调用,因此用户始终使用最新的会话。
  • 我也用它来登录/注销,所以清除所有模板就可以了。
  • 我在 github 上读到了这个“@angular/compiler/src/runtime_compiler 是一个私有/未导出的路径,因此不应该使用(换句话说,你应该在你的Angular2 公共 API 的导入路径);"
  • 您能否发布更完整的示例。
  • 不使用location.reload();。这是个坏主意,请在 this answer 中观察我的解决方案
【解决方案2】:

Angular 2.0.2中,我们可以如下清除模板缓存:

进口:

import { Compiler } from '@angular/core';

依赖注入器:

constructor(private _compiler: Compiler) {
}

用法:

this._compiler.clearCache();

注意:我相信此解决方案适用于 Angular 2.0.0 (RTM)

更新

在 Angular clearCache() 的当前版本 (4.x) 中不再工作。这已经是reported in the Angular Github(@Olezt),将来可能会更正。

clearcache()方法的功能用途说明:

另一个不清楚的问题是clearCache()方法的功能用途,clearCache()有责任去除@Component中指定的templateUrlstylesUrl等。 (我用它来丢弃templateUrl 中加载的视图并请求服务器的更新视图,在我的项目中,此请求产生的视图会根据交换用户/权限进行更改。因此需要丢弃以前的视图已加载。)

clearCache() 对浏览器缓存或 Angular 之外的任何东西没有任何作用,它只对 @Component@NgModule 等有作用。Angular 缓存,仅此而已。

【讨论】:

  • 此解决方案是否需要将编译器单独导入每个组件?
  • @Tyron,是的,在您要执行此例程的所有组件上。我不认为这是一个问题,这对你来说是个问题吗?
  • 这对我来说不适用于 v.4.2.3,即使 clearCache 似乎存在于官方文档中。
  • @Olezt,我们能否提供Plunker 以便我们分析可能的更新解决方案?
  • @Olezt。未定义函数的返回并不意味着它不起作用,只是它没有设置返回。您可能会注意到该方法在current versions of the Compiler object of the Angular 中。尝试检查是否有可能缓存 html 的角度以外的其他内容。目前我不能保证这是有效的,因为这是在一个原型项目中实现的,该项目在旧版本的 Angular 中停止。
【解决方案3】:

在 Angular 5.X 中,我们可以像 2.0 一样使用编译器。

导入编译器:

从'@angular/core'导入{编译器};

在你的组件构造函数中注入依赖:

构造函数(私有_compiler:编译器){ }

清除缓存:

this._compiler.clearCache();

【讨论】:

  • 此解决方案是否需要将编译器单独导入每个组件?
【解决方案4】:

下面的堆栈溢出问题提供了一个很好的策略来解决这个问题,方法是在 URL 中附加一个版本参数。

Force browser to clear cache

理论上,这对于生产版本应该很有效。然后为了开发,我可以简单地禁用浏览器缓存。

【讨论】:

  • 我可以确认这个策略可以使用 fiddler;但是,现在我需要弄清楚如何在 Angular JS 2.0 中为模板内容重写 url
【解决方案5】:

gulpfile.js

var gulp = require('gulp'),
    replace = require('gulp-replace');

    gulp.task('release', function() {
        // cache busting for html
        gulp.src([app/**'])
            .pipe(replace(/\.html.*'/g, '.html?v' + Date.now() + "'"))
            .pipe(gulp.dest('web/app'));

        // cache busting for js
        gulp.src(['main.html'])
            .pipe(replace(/version = (\d+)/g, 'version = ' + Date.now()))
            .pipe(gulp.dest('src/AppBundle/Resources/views'));
    });

main.html

<html>
    <head>
        <script src="{{ asset('js/systemjs.config.js') }}"></script>
        <script>
            var systemLocate = System.locate,
                version = 1477001404442;
            System.locate = function(load) {
                var System = this;

                return Promise.resolve(systemLocate.call(this, load)).then(function(address) {
                    return address + System.cacheBust;
                });
            };
            System.cacheBust = '?v=' + version;

            System.import('app').catch(function(err){ console.error(err); });
        </script>
    </head>
</html>

任何组件.ts

@Component({
    selector: 'any-selector',
    templateUrl: '/app/template.html'
})

然后执行 gulp release 就可以上线了

【讨论】:

    【解决方案6】:

    我有一个类似的question。作为一个快速破解,我通过在像export var fileVersion = '?tmplv=' + Date.now(); 这样的模块中引入一个全局变量来解决这个问题 - 在开发时并将其更改为生产 - 并在组件中使用它:

    @Component({
        selector: 'my-component',
        templateUrl: '/app/templates/my-component.html' + fileVersion,
    })
    

    所以我只需刷新浏览器即可查看更改。在生产中使用export var fileVersion = '?tmplv=v1.3.7yourVersionNumber';

    【讨论】:

    • 我必须在哪里声明变量“fileVersion”?目前我正在为 Angular 2 应用程序使用 Angular cli。我已经在环境文件中定义了 fileVersion 并在组件中导入并尝试在 temlateUrl 中使用。但它给出了错误“fileVerison is undefined”
    • 使用它之前的任何地方。并且应该全局声明,作为包的顶级变量(因此是export)。但我认为这个答案可能来自 Angular 2.0 Beta,甚至在发布之后,路由和库以及可能许多其他事情都发生了很大变化。所以在我看来 Angular(现在是 4 个?)可能有更好的解决方案。我不再使用 Angular。这些天我使用 VueJS。
    【解决方案7】:

    我只是将一个字符串附加到 templateUrl 以避免缓存。这是我的解决方案:https://csjdpw.atlassian.net/wiki/x/gCGWAg

    【讨论】:

      【解决方案8】:

      更好的解决方案是捆绑所有必需的文件并生成单个 .js 文件,使用路径末尾的简单查询字符串 (?v=1.x) 可以很容易地使该文件无效。有关更多信息,请查看此官方文档: Webpack 简介https://angular.io/docs/ts/latest/guide/webpack.html

      【讨论】:

      • 模块不是加载捆绑的替代方案吗?或者更确切地说,它的继任者
      【解决方案9】:

      我认为最简单的做法是使用隐身模式打开一个新会话,因为没有任何内容被缓存,所以它总是会强制重新加载。

      【讨论】:

      • 如果我是唯一使用该网站的人,这将起作用;但是,有很多用户正在使用该网站,如果我引入了需要回滚的错误,那么要求用户使用隐身模式将非常困难。我敢打赌 IE 也没有隐身模式。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-28
      • 1970-01-01
      • 2016-02-20
      • 2012-11-12
      • 2011-05-10
      • 1970-01-01
      相关资源
      最近更新 更多