Skip to content

feat: app-shell-friendly script loading #428

Closed

Description

@jeffbcross

In order to support App Shell style apps, we need to be able to only inline the JS necessary to render a basic "shell" page, and load the remaining scripts asynchronously, i.e.:

<body>
  <!-- inlined app shell html and CSS -->
  <script>
    // necessary to render shell page
  </script>
  <script src="everything-app-needs.js" async></script>
</body>

If any scripts are included without the async attribute, they would block the app shell from rendering, and render it useless.

The current scripts that are loaded are:

  • es6-shim/es6-shim.js
  • systemjs/dist/system-polyfills.js
  • angular2/bundles/angular2-polyfills.js
  • systemjs/dist/system.src.js
  • rxjs/bundles/Rx.js
  • angular2/bundles/angular2.dev.js
  • angular2/bundles/http.dev.js
  • angular2/bundles/router.dev.js

Plus the System configuration is inlined

I think we could just combine System.js libs, polyfills, system configuration, and initial System.import into a single script file, that could be included with the async attribute. And instead of loading libraries like angular, http, router, and rxjs via <script> tags, they would be loaded by System.

@hansl says "looks good" but he's going to give it more thought.

But this assumes the user doesn't manually add script tags to the html. Deserves some more thought.

Activity

  1. filipesilva commented on Apr 21, 2016

    @filipesilva
    Contributor

    Heya @jeffbcross, I hadn't been looking at this issue but I think I inadvertently covered it in #481. Can you confirm?

  2. jeffbcross commented on Apr 21, 2016

    @jeffbcross
    ContributorAuthor

    @filipesilva it's closer, but app shell requires that all external scripts be loaded asynchronously, including system, es6-shim, polyfills. The next step after your PR would be to concatenate all vendor scripts into a single file, as well as system-config and a file to kick off the system import. I'm doing this in my project using the broccoli-concat plugin:

    var concatExtrasTree = new Funnel('src/client', {
      include: [
        'system.config.js',
        'auto-start.js'
      ]
    });
    var jsBundleTree = concat(mergeTrees([ngTree, concatExtrasTree]), {
        headerFiles: [
          'vendor/es6-shim/es6-shim.js',
          'vendor/systemjs/dist/system-polyfills.js',
          'vendor/angular2/bundles/angular2-polyfills.js',
          'vendor/systemjs/dist/system.src.js',
          'vendor/rxjs/bundles/Rx.js',
          'vendor/angular2/bundles/angular2.dev.js',
          'vendor/angular2/bundles/http.dev.js',
          'vendor/angular2/bundles/router.dev.js'
        ],
        inputFiles: ['system.config.js'],
        header: ';(function() {',
        footer: '}());',
        footerFiles: ['auto-start.js'],
        sourceMapConfig: { enabled: true },
        allowNone: false,
        outputFile: '/app-concat.js'
      });

    And my index page only has one async script tag:

    <body>
      <issue-cli-app>Loading...</issue-cli-app>
      <script src="app-concat.js" async></script>
    </body>
  3. filipesilva commented on Apr 21, 2016

    @filipesilva
    Contributor

    Well I was going to work on the bundling next, using SystemJS builder. We could bundle up everything individually for production builds (vendor, app, app barrels) and then do the concat you suggested.

    It would also have the added benefit of tree shaking, since I think SystemJS builder is doing it.

  4. jeffbcross commented on Apr 21, 2016

    @jeffbcross
    ContributorAuthor

    Roll-up is the new hotness in terms of bundling with unused-module-shaking.

    As an aside, with offline compilation having landed in angular/angular, using that with a combination of rollup will likely be the biggest bang for buck in terms of getting payload size down, as well as reduced bootstrap time.

  5. filipesilva commented on Apr 21, 2016

    @filipesilva
    Contributor

    SystemJS builder seems to be using rollup, or at least it's in the dependencies https://github.com/systemjs/builder/blob/master/package.json#L11

    Is there some docs that I could look at for offline compilation Jeff?

  6. jeffbcross commented on Apr 21, 2016

    @jeffbcross
    ContributorAuthor

    SystemJS builder seems to be using rollup, or at least it's in the dependencies https://github.com/systemjs/builder/blob/master/package.json#L11

    Cool!

    Is there some docs that I could look at for offline compilation Jeff?

    Not yet. I think @robwormald is working on some examples, but don't quote me on that.

  7. kylecordes commented on Jun 2, 2016

    @kylecordes

    I think maybe the "dream" section at the end of #987 I just entered would achieve this also. I was coming at it from a different point of view (just attempt to satisfy the Google page speed tool, it will teach you so much about making a page load very very soon...), but I think it ends up the same place.

  8. added
    P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
    on Jun 4, 2016
  9. filipesilva commented on Jul 27, 2016

    @filipesilva
    Contributor

    @jeffbcross I think #1455 fixed this, can you verify?

  10. adamduren commented on Jul 27, 2016

    @adamduren

    @filipesilva If would have time it'd be nice for some clarification about the differences between SystemJS and Webpack (supported in #1455). It seems like SystemJS is the default. Are they separate or complementary tools? What is the recommended way when using angular-cli going forward or does it depend on circumstances?

  11. filipesilva commented on Jul 27, 2016

    @filipesilva
    Contributor

    @adamduren as a user, our policy is that you shouldn't have to care about the build system. The CLI might be using Webpack, Broccoli, SystemJS - but you shouldn't have to care. For the user, the CLI is the build system.

    #1455 brings us one step closer to that. I don't think it would make any difference going over the overall differences between Webpack and SystemJS now because both are well hidden and you can't really interact with them.

  12. modified the milestone: on Nov 11, 2016
  13. hansl commented on Dec 8, 2016

    @hansl
    Contributor

    Mobile and Universal have taken a different direction; closing this in favor of the custom blueprints and addons which will come later next year.

  14. angular-automatic-lock-bot commented on Sep 6, 2019

    @angular-automatic-lock-bot

    This issue has been automatically locked due to inactivity.
    Please file a new issue if you are encountering a similar or related problem.

    Read more about our automatic conversation locking policy.

    This action has been performed automatically by a bot.

  15. locked and limited conversation to collaborators on Sep 6, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgenteffort3: hard (weeks/months)needs: more infoReporter must clarify the issue

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions