在服务器端渲染初始 Angular ng-view 并从那里获取它

Render initial Angular ng-view on server-side and take it from there

提问人:mikegertrudes 提问时间:7/25/2015 最后编辑:mikegertrudes 更新时间:7/27/2015 访问量:882

问:

我想避免显示初始 JavaScript 呈现视图的延迟。我希望用户立即看到内容并让 Angular 从那里获取它。我不想在 Angular ngRoute 启动时替换这个 ng-view,因为可能会发生眨眼。我只希望它在用户到达另一条路线时替换它。

让我们想象一下这是基本路线。这已经存在于我的 HTML 中,从服务器呈现。'/'

<div ng-view>
<h1>Welcome. I am the first view.</h1>
<p>Please do not replace me until a user has triggered another route.</p>
</div>

我知道一种常见的方法是在 an 中加入一些服务器端代码,当 Angular 加载时,它只是替换它。这不是我想要做的。我希望 Angular 加载并理解这实际上已经是我的第一个视图。ng-view

关于如何做到这一点,有什么创意吗?我看过源代码 - 没有运气。也许甚至有一种让 Angular 只替换 HTML 的方法,如果它不同。

编辑: 我不想在服务器端渲染模板以用作 Angular 模板。我希望在服务器端渲染我的整个过程,并且已经包含用户需要看到的初始基本路由的所有内容。index.html

angularjs 服务器端 angularjs-routing angular-routing ngroute

评论

0赞 Erti-Chris Eelmaa 7/25/2015
尝试搜索预编译的 angularjs 模板。有很多解决方案。
0赞 charlietfl 7/25/2015
将初始数据和内容放入块内的 Angular 缓存中run
0赞 Claies 7/25/2015
这似乎是一个相当毫无意义的微优化,除非您的初始模板非常复杂;目前尚不清楚为什么您会为此目的立即拒绝预编译的模板,因为这与您所描述的本质上是一回事。
0赞 mikegertrudes 7/26/2015
加载 Angular 时要加载的预编译模板不是我要找的。在移动设备上,连接速度较慢,可能需要 6-10 秒才能启动 Angular。也许有误会,或者我没有正确解释自己。

答:

-2赞 Bilal 7/26/2015 #1
ngCloak

ngCloak 指令用于防止浏览器在加载应用程序时以原始(未编译)形式短暂显示 Angular html 模板。使用此指令可避免 html 模板显示导致的不良闪烁效果。

https://docs.angularjs.org/api/ng/directive/ngCloak

<body ng-cloak>

您应该阅读这篇文章 http://sc5.io/posts/how-to-implement-loaders-for-an-angularjs-app

评论

0赞 mikegertrudes 7/27/2015
谢谢。我已经在应用程序的另一部分上使用,但它并不能解决我在这里试图通过在服务器端呈现完整内容来解决的问题。ng-cloak
-1赞 Erti-Chris Eelmaa 7/27/2015 #2

在任何手机上 6-10 秒都是非常糟糕的。我不会在这里责怪 angular,angular 只有 30kb,如果仍然太慢,那么你选择了错误的任务框架。

使用分析工具了解正在发生的事情。

  • 您正在处理的应用程序有多大?
  • 您可以将应用程序拆分为子应用程序吗?
  • 你已经在为CSS和JS做缩小了吗?
  • 您是否懒惰地加载所有视图和控制器?
  • 你在压缩一切吗?(gzip)

无论如何,可以在服务器端为您的index.html进行预处理

例如,您可以使用 nodejs 进行预处理,并缓存预处理index.html。

你的 nodejs 预处理器可以做(伪代码):

function preprocessIndexHtml(queryString) {
   if(cached[queryString])) return cached[queryString];

   // assume angular.js is loaded
   // routeConfiguration is an object that holds controller & url.
   var routeConfiguration = $routeProvider.
       figureOutRouteConfigurationFor(queryString);

  var domTree = $(file('index.html'));
  var $rootScope = $injector.get('$rootScope');

  // find ng-view and clone it
  var yourNgView = $($("attribute[ng-view='']").outerHTML);

  // le's get rid of existing ng-view attribute
  // and configure new ng-view with templateUrl & controller.
  yourNgView.RemoveNgViewAttribute();
  yourNgView.AddAttribute("ng-controller", routeConfiguration.controller);
  yourNgView.AddAttribute("ng-view", routeConfiguration.templateUrl);

  // compile the view & pass the rootScope.
  $compile(yourNgView)($rootScope);

  // replace the existing dom element with our compiled variant
  $("attribute[ng-view='']").replaceHtmlWith(yourNgView);

  // we can now cache the resulted html.
  return cached[queryString] = domTree.html;
}