AngularJS最佳实践 - 模板与Javascript

时间:2015-02-27 15:34:20

标签: javascript angularjs

默认情况下,Angular在用户导航到路径时从服务器获取HTML模板。考虑到这一点,想象一下这种情况:

  • 用户加载Angular应用。主视图有一个名为" Order"。
  • 的子页面
  • 当用户正在研究主视图时,将在生产中推出新版本的应用程序。新版本使用新的Javscript和HTML完全重写了Order页面。
  • 用户导航到“订单”页面。浏览器已在步骤1中加载Javascript,因此用户处于旧版本,直到重新加载应用程序。 但新模板是从导航服务器上获取的。所以现在Javascript和模板是我们的同步!

我的假设是Javascript / HTML不同步,对吗?

如果有,是否有与此问题相关的最佳做法?

我想一个解决方案是让Angular在app初始化时获取所有模板。但如果应用程序有数百个HTML视图,这可能会降低性能。

7 个答案:

答案 0 :(得分:2)

我自己从未想过这个问题。一种可能的想法是重用称为资产版本控制的模式,在新版本中,您重命名所有资产。

例如,您不是login.html而是使用login-xyz.html作为模板的名称。 xyz可以是随机值,也可以是文件的校验和。校验和可能是一个稍好的选择,因为如果新版本很小(即你只修复了一个文件中的一些小错误),如果用户加载任何页面而不是固定版本,他/她将不会被重新加载 - 所有其他文件将具有相同的校验和,它们不会中断。

这样,当过时的Anguar应用尝试获取模板时,它会收到HTTP 404错误。除此之外,您还可以编写一个简单的$http interceptor来检测404响应,并自动重新加载页面(或者为用户提供这样做的选项)。

有些模块能够重命名资产,例如gulp-rev - 但我从未听说过将其用于Angular模板。不过,你可以自己实现类似的东西。

当然,您可能希望保留新旧版本的文件,以允许用户在不中断刷新的情况下工作。取决于您的要求。不过,我认为你会试图避免这种情况。


示例404拦截器(CoffeScript,我现在很方便):

m.factory 'notFoundInterceptor', ($q) ->
  return {
    responseError: (response) ->
        if response?.status == 404
            # Reload, or warn user
            return $q.defer()

        # Not a 404, so handle it elsewhere
        $q.reject response
  }

m.config ($httpProvider) ->
  $httpProvider.interceptors.push 'notFoundInterceptor'

答案 1 :(得分:1)

感谢您的回答。

事实证明,这个问题为我们解决了。每次我们推出新版本时,所有用户会话都将被删除,用户将被发送到登录页面。这将触发页面加载并加载新的JavaScript / HTML。

答案 2 :(得分:0)

我很久以前就读过这个问题了,其中一个选项就是对已更改的网页和application.js文件进行版本控制。

例如,在您的应用程序版本1上,您可以在您的html文件中使用以下内容:

<script src="js/angular_app_v1.js"></script>

您的路线内部还会对templateURL进行版本

templateUrl: 'templates/view_product_v1.html'

因此,当您推出新版本时,您将不会覆盖模板,已经工作的用户将拥有旧版本,直到他们重新加载浏览器,但不会出现版本不一致。

答案 3 :(得分:0)

即使是中端应用程序,使用文件名对资产进行版本控制也无法维护。

尽管对于网络资产来说这是一种重量级方法,但您可以查看内容协商。这是对资源的调用,通常是REST api返回资源的版本Content-Type: application/vnd.contentful.delivery.v1+json.。在客户端上,您可以检查版本是否符合预期。因此,如果客户端只知道如何使用v1.2加载v1.1和资源响应,那么UI会知道它无法处理它并且应该重新加载页面。

另一种可能性是在UI中预先加载所有模板。您可以运行Grunt中的构建过程,例如https://github.com/ericclemmons/grunt-angular-templates,它将所有模板组合到一个文件中进行传递,然后将它们加载到$ templateCache中,这样就不会有任何请求到达服务器。

答案 4 :(得分:0)

如果你有某种服务器端语言,可以在(.NET,Rails,Java或其他)中构建过滤器,并传递带有模板请求的版本号。如果客户端请求的版本比部署的版本旧,则您向客户端发送错误。您的客户端将监视该错误($ http拦截器)并强制页面刷新以下拉新的JavaScript代码。 (可能先向用户显示警告,以便他们了解正在进行的操作)。

答案 5 :(得分:0)

您可以将所有模板预加载到$ templateCache中,并将它们作为一个templates.js文件提供。这个https://www.npmjs.com/package/gulp-angular-templatecache有一个gulp任务。然后,您的应用程序将在启动时将所有模板与应用程序脚本一起加载到单个请求中,从而它们将同步。请阅读http://www.johnpapa.net/angular-and-gulp/了解详情。

答案 6 :(得分:0)

拥有版本号并在同步资源时使用它总是有意义的。它不仅是您描述的用例的良好实践,也适用于其他情况,例如回滚到特定版本或具有两个版本的实时和可用(例如,为了让一些用户预览下一个版本)