预呈现实际上如何运作?

时间:2016-06-19 04:49:28

标签: angular

服务器端渲染的资源很少,事实上,我找不到任何能清楚解释事物实际工作方式的东西。我已经看过一些回购,试图遵循代码,但没有设法弄清楚它的要点。如果我正常运行角度,我基本上知道会发生什么:

  1. 已加载HTML文件:<html><body><my-app>...</my-app><SCRIPTS/></body></html>
  2. 脚本已加载......
  3. Angular处理代码,并将<my-app>替换为内部的所有内容。
  4. 对于这个应用程序:

    @Component({
      selector: 'my-app'
      template: `<p *ngFor="let i of items">{{ i }}</p>`,
    })
    export class AppComponent {
      items = [1, 2, 3];
    }
    

    我可以看到检查html(plunker)并看到:

    <my-app>
      <!--template bindings={
        "ng-reflect-ng-for-of": "1,2,3"
      }-->
      <p>1</p>
      <p>2</p>
      <p>3</p>
    </my-app>
    

    到目前为止一切都清楚了! (:

    但是预渲染会发生什么?如果我创建这样的文件:

    <html>
    <body>
      <my-app>
        <!--template bindings={
            "ng-reflect-ng-for-of": "1,2,3"
          }-->
        <p>1</p>
        <p>2</p>
        <p>3</p>
      </my-app>
      <SCRIPTS/>
    </body>
    </html>
    

    加载脚本后Angular会做什么?我可以使用这个HTML而不是第一个吗?如果有人了解这个过程是如何运作的,请分享(;有关这些内容的任何信息都会有用......我可以 复制outerHTML ,并将其作为我的&#34;预渲染的页面&#34;?...像这样:

    Copy outerHTML

    如果没有,为什么?我正在寻找这个过程的本质,一个可以手工编写的例子......

3 个答案:

答案 0 :(得分:15)

使用服务器端呈现,页面在服务器上呈现两次:所以您可以很早地看到呈现的视图,然后在客户端上 - 在加载应用程序之后。

  • 在服务器端,您使用angular-universal根据路线网址呈现应用的任何视图;
  • 在客户端上,您的应用程序正常引导 - 客户端呈现的视图放入应用程序根标记,替换服务器呈现的视图。客户端发生的唯一魔力是通过通用项目的preboot.js模块将状态转移到客户端应用程序,这是通过记录在服务器呈现的视图上触发的事件然后在客户端上重放它们来完成的。应用程序加载后的渲染视图。因此,如果您在加载应用程序之前在input框中键入内容,则在客户端呈现的视图替换服务器呈现的视图后,preboot.complete()命令将重播键击。

您的问题:

  

加载脚本后Angular会做什么?

您的应用正常启动,<my-app></my-app>标记的内容将被客户端呈现的视图替换。

  

我可以复制outerHTML,并将其作为我的“预渲染页面”吗?

是。但是,最好使用angular-universal模块,因此您可以动态渲染任何路径后面的视图。

对于示例,这里是Angular 2 Universal Starter,它是一个示例应用,用于演示实际的通用内容。玩它:

  • 更改'This was rendered from the server!'中的字符串dist/server/index.js,以便在加载应用时将其恢复原状。这意味着在呈现客户端视图后该语句变为谎言。
  • 启用preboot并推迟preboot.complete()以查看其效果(在input框中输入内容):

    <强>的src / main.node.ts

    let config: ExpressEngineConfig = {
        // ...
        preboot: { appRoot: 'app' } // your top level app component selector
    };
    

    <强>的src / client.ts

    ngApp()
    .then(function() {
      setTimeout(function() {
        preboot.complete();
      }, 5000);
    });
    

这里是客户端预引导静态服务的“预呈现”视图的简单DEMO。在引导app之前有5秒的延迟,以查看预启动的运行情况。

我不是有角度的专家,所以,如果我错了,请纠正我。我的判断依据是阅读以下资源:

答案 1 :(得分:2)

服务器端呈现Angular的过程与在浏览器上呈现它的过程大致相同。唯一的区别是代码在Node的JavaScript运行时上运行而不是浏览器,因此您将错过DOM API提供的一些功能。

请注意,应用程序不会在服务器中呈现(绘制),因此您将无法访问Element.clientWidth等属性。

总而言之,服务器经历了相同的过程:

  1. 加载index.html和所有嵌入式脚本
  2. Bootstraps Angular app
  3. Angular进程代码,进行HTTP调用,绑定模板..
  4. 还有两种类型的服务器端呈现,我引用official site

      

    您可以使用两种不同的方法进行服务器渲染。   第一个选项是预渲染您的应用程序,这意味着   你会使用其中一个通用构建工具(即gulp,grunt,   西兰花,webpack等)为你的所有路线生成静态HTML   在建设时。然后,您可以将该静态HTML部署到CDN。该   这种方法的优点是它具有高度可扩展性   高性能。缺点是它不够灵活   第二种方法。

         

    第二种方法是动态地重新渲染你的应用程序   每个请求的Web服务器。还有几种缓存选项   可用这种方法来提高可扩展性和性能,   但是你将在上下文中运行你的应用程序代码   每个请求的Angular Universal。

答案 2 :(得分:1)

我认为您必须使用angular2-universal-preview才能在服务器端呈现应用程序:

    import * as express from 'express';
    import {ng2engine} from 'angular2-universal-preview';

    // Angular 2
    import {App} from './src/app';

    let app = express();

    // Express View
    app.engine('.ng2.html', ng2engine);
    app.set('views', __dirname);
    app.set('view engine', 'ng2.html');


    // static files
    app.use(express.static(__dirname));


    app.use('/', (req, res) => {
      res.render('index', { App });
    });



    app.listen(3000, () => {
      console.log('Listen on http://localhost:3000');
    });`