【问题标题】:Render initial Angular ng-view on server-side and take it from there在服务器端渲染初始 Angular ng-view 并从那里获取
【发布时间】:2015-10-16 01:50:41
【问题描述】:

我想避免初始 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>

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

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

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

【问题讨论】:

  • 尝试搜索预编译的 angularjs 模板。有很多解决方案。
  • 将您的初始数据和内容放入 run 块内的角度缓存中
  • 这似乎是一个毫无意义的微优化,除非您的初始模板非常复杂;目前还不清楚为什么您会立即拒绝为此目的的预编译模板,因为这与您所描述的内容基本相同。
  • 加载 Angular 时要加载的预编译模板不是我想要的。在连接速度较慢的移动设备上,Angular 启动前可能需要 6 到 10 秒。可能存在误解或我没有正确解释自己。

标签: angularjs server-side angularjs-routing angular-routing ngroute


【解决方案1】:

在任何移动设备上 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;
}

【讨论】:

    【解决方案2】:
    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

    【讨论】:

    • 谢谢。我已经在应用程序的另一部分上使用了ng-cloak,但它并没有解决我试图通过在服务器端呈现完整内容来解决的问题。
    猜你喜欢
    • 2016-08-27
    • 1970-01-01
    • 2017-09-23
    • 2018-03-21
    • 2019-09-07
    • 1970-01-01
    • 2020-12-22
    • 1970-01-01
    • 2016-04-03
    相关资源
    最近更新 更多