Giter Site home page Giter Site logo

fastboot's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fastboot's Issues

`$ ember-fastboot fastboot-config.js`: TypeError: next is not a function

I'm trying to start FastBoot server from command line providing this config file:

fastboot-config.js

module.exports = {
  port: 8000,
  appFile: "/app/app.js",
  vendorFile: "fastboot-dist/assets/vendor.js",
  htmlFile: "app/index.html"
};

and this is the output:

2015-12-29T06:57:16.243Z [Server 0] Server listening on port 8000
2015-12-29T06:57:16.252Z [Server 0] Starting rendering engine
2015-12-29T06:57:16.253Z [Renderer 0] Engine starting up (phantom)
/usr/local/lib/node_modules/ember-fastboot/lib/plugins/removeScriptTags.js:6
    next();
    ^

TypeError: next is not a function
    at Object.module.exports.beforeInit (/usr/local/lib/node_modules/ember-fastboot/lib/plugins/removeScriptTags.js:6:5)
    at next (/usr/local/lib/node_modules/ember-fastboot/lib/renderer.js:245:14)
    at PrerenderRenderer.pluginEvent (/usr/local/lib/node_modules/ember-fastboot/lib/renderer.js:252:3)
    at Request._callback (/usr/local/lib/node_modules/ember-fastboot/lib/renderer.js:36:13)
    at Request.self.callback (/usr/local/lib/node_modules/ember-fastboot/node_modules/request/request.js:198:22)
    at emitTwo (events.js:87:13)
    at Request.emit (events.js:172:7)
    at Request.<anonymous> (/usr/local/lib/node_modules/ember-fastboot/node_modules/request/request.js:1035:10)
    at emitOne (events.js:82:20)
    at Request.emit (events.js:169:7)

Ember Version:

DEBUG: -------------------------------
DEBUG: Ember       : 2.4.0-canary+2d622f12
DEBUG: Ember Data  : 2.4.0-canary+24fdc95d73
DEBUG: jQuery      : 1.11.3
DEBUG: -------------------------------
Ember Inspector Active

Problems starting ember fastboot server

I have tried running fastboot server both from command line and as a middleware and both of them failed

As command
ember-fastboot --port 4301 --app-file app/app.js --vendor-file dist/assets/vendor.js --html-file app/index.html
throws an error: cannot find module '/Users/<username>/apps/myApp/--port'

As middleware:

var server = new FastBootServer({
  appFile: path.join(root, 'app/app.js'),
  vendorFile: path.join(root, 'dist/assets/vendor.js'),
  htmlFile: path.join(root, 'app/index.html'),
  ui: ''
});

(What should be the ui variable set to? didn't find it readme)

throws this error: Cannot read property 'userAgent' of undefined

any help?

Better hints for JSON serialization errors

When using the shoebox, it would seem that the following would make sense

let response = await fetch(...);
let jsonData = await response.json();
shoeboxStore.currentUser = jsonData;
shoebox.put('user-data', myShoeboxStore);

In my case, I ended up getting a cryptic error message (in fastboot only)
screen shot 2016-11-30 at 1 11 49 am

Upon investigating this, it turns out that the jsonData I am given by way of fetch is likely modified at some point downstream (in my case a DS.Store#push), and it then becomes a circular JSON structure as relationships are wired up.

The end result is that, at the time I call shoebox.put, my object is serializable, but by the time the page is resolved (and the fastboot visit completes), it becomes partially resolved into a much more complex (and circular) structure.

Some ideas for improving this experience:

  • Better error messages around shoebox serialization
  • Add info to the readme about when the shoebox serialization takes place

document.title should take precedence over the <head> HTML

Relevant code from ember-fastboot-server:

FastBootServer.prototype.insertIntoIndexHTML = function(title, body, head) {
  var html = this.html.replace("<!-- EMBER_CLI_FASTBOOT_BODY -->", body);

  if (title) {
    html = html.replace("<!-- EMBER_CLI_FASTBOOT_TITLE -->", "<title>" + title + "</title>");
  }
  if (head) {
    html = html.replace("<!-- EMBER_CLI_FASTBOOT_HEAD -->", head);
  }

  return html;
};

If I am not missing something, a title set by document.title would be overridden by the more "general" <head> tag. Shouldn't this order be reversed or am I missing something?

If so, I'll make a PR.

Use X-Forwarded-Proto header as FastbootRequest protocol

I'm not sure if this is the right repo to open this issue, please let me know if it should be moved.

Currently the fastboot.request.protocol is used when determining the ember data host to use for ED requests made from fastboot. See: https://github.com/ember-fastboot/ember-cli-fastboot/blob/5ecfe8e90ff07f2318eccecedce19c083b58bd21/fastboot/initializers/ajax.js#L9

It's common for load balancers to do SSL termination before sending a request to the fastboot app server. When this happens the protocol would be HTTP, but the LB would also add an X-Forwarded-Proto header to the request.

This creates a problem because the fastboot-app-server thinks the protocol is HTTP, so when the fastboot run Ember app runs an Ember data query it will request data from http://${host}, which will most likely 301 to https://${host}. Since Ember data is running in fastboot/node, it will not follow redirects, and this leads to Ember data ending up with an empty request that throws an error.

One suggestion is to run the fastboot app server using only HTTPS and not have the LB terminate SSL. While this will fix the problem, not all of us have control over our load balancers. Currently, heroku does SSL termination before forwarding the request, so if you're running fastboot-app-server on heroku you'll always end up with an HTTP protocol + X-Forwarded-Proto: https header.

My suggestion would be to have fastboot.request.protocol check for an X-Forwarded-Proto header in the request and use that. I think this would lead to less surprises.

cc @kratiahuja @krasnoukhov since I know y'all were discussing this earlier today.

Drop support for Node 0.12?

Given that Node 0.12 is not longer LTS, should we officially drop support for this in FastBoot? I believe ember-cli dropped support for it. We also probably need to make an annoucement for the same so that users are not unhappy.

Add 'ember-fastboot' class to rendered body

I'm writing a plugin where I want to conditionally inject a loading UI dependent upon whether the page has already been rendered in Fastboot, or is initializing for the first time in the browser. For this use case, it'd be handy to be able to check for Fastboot rendered content in an instance initializer.

@arjansingh suggested using Fastboot response headers, but that involves firing off a blank XMLHttpRequest to detect the page's initial HTTP headers, which seems a little messy.

I'm currently checking for Fastboot markup by injecting a bare component with a class .fastbooted in a fastboot-targeted instance initializer, then in a browser-targeted instance initializer, using Ember.$('.fastbooted').length > 0. Also messy.

My suggestion is to add an .ember-fastboot class to the rendered body here, in the same way Ember adds an .ember-application class to its body.

Better still, allow any attributes set on the Simple DOM body node to be passed through to the final HTML.

undefined value in shoebox throws error

If you accidentally provide an undefined as a shoebox value, you get the stack trace:

 TypeError: Cannot read property 'replace' of undefined
    at escapeJSONString (/xxx/node_modules/fastboot/src/ember-app.js:478:16)
    at createShoebox (/xxx/node_modules/fastboot/src/ember-app.js:453:17)
    at visitRoute.then.then (/xxx/node_modules/fastboot/src/ember-app.js:316:11)

It would be easy to handle undefined and ignore them.

transitionTo under https

I'm trying to transition fastboot under the https, it's works with redirection to http version.

For example application.js route

export default Ember.Route.extend({
  model: function(param){
    this.transitionTo('login');
  }
});

request: https://domain.com --> http://domain.com:3001/login
where 3001 fastboot port

How I can solve this problem?

FastBoot should emit metrics

This issue is an enhancement for future purposes.

Post FastBoot 1.0, we should look at emmitting some useful metrics like server side latency, memory used by the node processes so that apps using FastBoot can listen to these metrics and create useful operational dashboard.

This probably will need an RFC at some point IMO.

this.ui should be optional?

DEBUG: -------------------------------
DEBUG: Ember           : 2.3.1
DEBUG: Ember Data      : 2.3.3
DEBUG: Model Fragments : 2.1.0
DEBUG: -------------------------------
/login
TypeError: Cannot read property 'writeLine' of undefined
    at FastBootServer.log (/node_modules/ember-fastboot-server/lib/server.js:32:10)
    at FastBootServer.handleSuccess (/node_modules/ember-fastboot-server/lib/server.js:46:8)
    at success (/node_modules/ember-fastboot-server/lib/server.js:85:14)
    at Timer.listOnTimeout (timers.js:119:15)`

This.ui comes from options.ui. (server.js line 20)

A) I have not found a reference to ui in the docs, so I'm not sure what to pass in.
B) According to #13, I should pass in distPath to new FastBootServer and nothing else

var server = new FastBootServer({
     distPath: '../ember-test-app/fastboot-dist'
});

Should UI be completely optional?

Allow chunked transfer encoding

I've been looking into ways to easily get chunked transfer encoding with FastBoot, the main motivation being that I'd like to have a mechanism where big shoeboxes don't unnecessarily delay initial rendering of the page.

I believe a really easy way to get this should be to send the response in 3 chunks:

  • everything until </head>
  • everything until the first shoebox if present (or the complete rest of the document if not)
  • the shoebox(es) if present and the final </body></html>

Of course being able to send chunks of the document as it is rendered on the server side would be ideal but I guess that's a bigger change in the FastBoot internals so the above solution might be a good start?

I looked at the code and I guess it should be straight forward to add a chunks() method (or so) to https://github.com/ember-fastboot/fastboot/blob/master/src/result.js and modify https://github.com/ember-fastboot/fastboot-express-middleware so that it writes each of the chunks instead of the complete HTML at once but I wanted to get some feedback before creating a PR.

Shoebox doesn't work when using ember-fastboot-server

When I run my app using ember fastboot the shoebox works as expected, but when I run ember build and then ember-fastboot dist/ the shoebox is never populated. I can see that fastboot.isFastBoot is set to true when the response is rendered, but there's no <script> tags containing the shoebox data in the response.

Warn if base HTML payload is missing BODY and/or HEAD insertion comments

A non-fastbooted payload is served if the insertion comments are missing from the base HTML. For those using an older version of ember-cli-html-minifier, these comments (and all comments!) are stripped and fastboot fails silently.

The aforementioned addon has added in fastboot compatibility, but I think a warning on the fastboot side is prudent as well.

Here's the offending fastboot code: https://github.com/ember-fastboot/fastboot/blob/master/src/result.js#L116-L122

Install fails on Windows

ember install ember-cli-fastboot fails because of ember-fastboot-server postInstall script on Windows

npm ERR! [email protected] postinstall: `scripts/is-not-legacy-vm || npm install contextify@^0.1.11`
npm ERR! Exit status 1
`scripts/is-not-legacy-vm || npm install contextify@^0.1.11`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] postinstall script 'scripts/is-not-legacy-vm || npm install contextify@^0.1.11'.

scripts/is-not-legacy-vm won't run just by using #!/usr/bin/env node as first line of scripts/is-not-legacy-vm on Windows, so it tries to include contextify, which is not needed on recent node anyway, and requiring it is a kind of PITA because of prerequisites like specific version of Visual Studio installed. Changing postInstall to node scripts/is-not-legacy-vm || npm install contextify@^0.1.11 works on Windows, but perhaps something more universal would be a better idea.

ApplicationInstance Boot Errors are being swallowed

I ran into a particularly vicious error, where a stray window reference caused the ApplicationInstance to fail booting:

  _bootPromise:
   Promise {
     _id: 14,
     _label: undefined,
     _state: 2,
     _result: [TypeError: window.addEventListener is not a function],
     _subscribers: [],
     _onError: null } }

The failure was silent and I only detected it when I logged this.instance inside of src/result.js.

We should be logging these events (not swallowing them silently).

Of course, I'll open a PR but I want to know if result._finalize is the place to do the error handling. Suggestions welcome.

`visit` never finishing can cause Node to be wedged

We hit this scenario at LinkedIn in production and we would like to push a similar fix to fastboot as well.

Consider the following scenario:

  1. You made a visit request to a route
  2. As part of the visit request, fastboot makes API request
  3. Now after the api requests, as part of the transition promise the app code calls setTimeout and keeps calling it based on some business logic. Instead of calling clearTimeout, your app accidentally calls clearInterval. Also your app is polling again and again and scheduling something with setTimeout.
  4. Fastboot only contains setTimeout and clearTimeout in its sandbox.
  5. Since the timeout will never be cleared and you were already polling, your visit promise may have never been resolved and the polling may cause your node process to be wedged and unresponsive. Thereafter, fastboot will be unresponsive to the next set of incoming requests.

I think to handle such scenarios, we need to timeout the visit and destroy the app instance forcefully in such scenarios and send down a Fastboot response to let the client know.

Opening this issue so that it gets tracked.

cc: @tomdale @danmcclain @arjansingh

Allow consuming ember apps to specify the name of the client-side global require() function

In order to avoid conflicts w/ Dojo's require() my addon (and others) have to change the name of the global require() function used by Ember.

When running an example app that uses my addon in FastBoot, I see this error when I load the page: TypeError: ctx.require is not a function, which comes from this line:

return ctx.require('~fastboot/app-factory');

I've been able to get around that and get the app working by passing in requireFunctionName as one of the sandboxGlobals and changing the above line to:

      const requireFunctionName = ctx.requireFunctionName || 'require';
      return ctx[requireFunctionName]('~fastboot/app-factory');

There's probably a better way, but that does work, and doesn't break any of FastBoot's existing tests.

Would you accept a PR that adds and documents that change? If not, would you recommend a different way that I can achieve the same?

Support Prototype Extensions

fastboot currently builds the application instance outside of the vm from within visitRoute

visitRoute currently utilizies the sandbox indirectly, via this.app which is created from an app factory returned from the sandbox.

If, instead, visitRoute delegated its work to a function run within the sandbox context, prototype extensions would work (or at least an impediment to their working would be removed).

Body & Head Tags Duplicated

As first discovered here the way fastboot serializes the body and head elements includes the tags themselves. Thus when the string substitution is performed to insert body & head into index.html the resulting content is a head within a head and body within body:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>HeadT</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <base href="/" />
<!-- EMBER_CLI_FASTBOOT_TITLE --><head><meta name="ember-cli-head-start"><!-- `app/templates/head.hbs` -->
<!-- Add content you wish automatically added to the documents head -->
<!-- here. The 'model' available in this template can be populated by -->
<!-- setting values on the 'head-data' service. -->

<meta property="og:title" content="Demo App">
<meta name="ember-cli-head-end">
</head>

    <link rel="stylesheet" href="assets/vendor.css">
    <link rel="stylesheet" href="assets/head-t.css">


  </head>
  <body>
    <body><div id="ember385" class="ember-view"><h2 id="title">Welcome to Ember</h2>

<!---->

</div></body>

    <script src="assets/vendor.js"></script>
    <script src="assets/head-t.js"></script>


  </body>
</html>

Support for route error substate

Expected behaviour

When the application route model rejects and the app enters an error substate, FastBoot should render a user-friendly error page and set a desired status code on the response.

Actual behaviour

FastBoot throws an error and renders empty page with status code 503.

Workaround

Enter the error substate manually and prevent bubbling the error up:

routes/application.js

actions: {
  error(err) {
    const fastboot = this.get('fastboot');

    if (fastboot.get('isFastBoot')) {
      fastboot.set('response.statusCode', err.code);
      this.intermediateTransitionTo('application_error', err);
      
      return false;
    }

    return true;
  }
}

header splitting on ', ' corrupts some headers

Can someone explain the header splitting here?

this.headers[header] = headers[header].split(', ');

this.headers[header] = headers[header].split(', ');

I noticed that it destroys the user agent in the header. Turns

'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36'

into

[
  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML',
  'like Gecko) Chrome/55.0.2883.95 Safari/537.36'
]

which causes me to need this code in Ember:

        let headers = get(this, 'fastboot.request.headers');
        let userAgent = headers.get('user-agent');

        if (userAgent instanceof Array) {
            userAgent = userAgent.join(', ');
        }

Cannot affect root <html> element

It appears that you can update the body or head to be rendered by FastBoot, but even if you have added attributes to the documentElement ( tag) that they are ignored. If I am reading the code correctly the html is just the template html file from the ember app, head, and body are serialized from simpledom (but not documentElement).

https://github.com/ember-fastboot/fastboot/blob/master/src/result.js#L128

function insertIntoIndexHTML(html, head, body) {
  if (!html) { return Promise.resolve(html); }

  if (body) {
    let isBodyReplaced = false;
    html = html.replace("<!-- EMBER_CLI_FASTBOOT_BODY -->", function() {
      isBodyReplaced = true;
      return body;
    });

    if (!isBodyReplaced) {
      return missingTag('<!--EMBER_CLI_FASTBOTT_BODY-->');
    }
  }

  if (head) {
    let isHeadReplaced = false;
    html = html.replace("<!-- EMBER_CLI_FASTBOOT_HEAD -->", function() {
      isHeadReplaced = true;
      return head;
    });

    if (!isHeadReplaced) {
      return missingTag('<!--EMBER_CLI_FASTBOTT_HEAD-->');
    }
  }

  return Promise.resolve(html);
}

Is this by design or could this be something to work on? It would address the following:
ember-fastboot/ember-cli-fastboot#331

Deprecate doc.title?

doc.title was implemented pre ember-cli-head. Since we are pre-1.0, I think we should consider deprecating doc.title in favor of ember-cli-head.

Headers persist through multiple requests

This is an issue with najax (najaxjs/najax#50) but based on the project's activity level, a proper fix does not look likely in the near future. It may be worth forking+patching it under ember-fastboot. We solved this with npm shrinkwrap for now but a proper downstream fix would be nice as this blocks a production release of our fastboot app.

Unable to fetch assets after Ember 2.7 upgrade

After upgrading to Ember 2.7 (which included the deprecation of baseURL) and starting an Ember app using Fastboot, the app tries to retrieve assets based on the rootURL specified, e.g.

  • rootURL/assets/vendor.css
  • rootURL/assets/appName.js

However, Fastboot is still serving these assets from

  • assets/vendor.css
  • assets/appName.js

This causes the assets not to be loaded.

I mentioned the issue here too, but am wondering if it's an issue with Fastboot itself.

`TypeError: FastBoot.config is not a function` on initial app load

I believe I've followed the README's usage instructions

Setup procedure

$ cd <app-dir>
$ ember install ember-cli-fastboot
$ # ... add dependencies to fastbootDependencies
$ ember build --environment production
$ cd ../new-dir
$ npm install fastboot

but I'm getting and error when I try to initialize the app:
TypeError: FastBoot.config is not a function

Full traceback

$ node --harmony
> const FastBoot = require('fastboot');
undefined
> let app = new FastBoot({distPath: '../appdir/dist'});
TypeError: FastBoot.config is not a function
    at r.callback (/path/to/appdir/dist/fastboot/chexec-4b43a9d50d6c4ddb7a7238f13ffeb126.js:3:11339)
    at r.exports (/path/to/appdir/dist/fastboot/vendor-a977a12b034745a0caa0ac14c4319f53.js:1:1991)
    at r.build (/path/to/appdir/dist/fastboot/vendor-a977a12b034745a0caa0ac14c4319f53.js:1:2753)
    at a (/path/to/appdir/dist/fastboot/vendor-a977a12b034745a0caa0ac14c4319f53.js:1:926)
    at r.reify (/path/to/appdir/dist/fastboot/vendor-a977a12b034745a0caa0ac14c4319f53.js:1:2466)
    at r.build (/path/to/appdir/dist/fastboot/vendor-a977a12b034745a0caa0ac14c4319f53.js:1:2740)
    at a (/path/to/appdir/dist/fastboot/vendor-a977a12b034745a0caa0ac14c4319f53.js:1:926)
    at r.reify (/path/to/appdir/dist/fastboot/vendor-a977a12b034745a0caa0ac14c4319f53.js:1:2466)
    at r.build (/path/to/appdir/dist/fastboot/vendor-a977a12b034745a0caa0ac14c4319f53.js:1:2740)
    at a (/path/to/appdir/dist/fastboot/vendor-a977a12b034745a0caa0ac14c4319f53.js:1:926)
    at Object.requireModule (/path/to/appdir/dist/fastboot/vendor-a977a12b034745a0caa0ac14c4319f53.js:1:3030)
    at Object.<anonymous> (/path/to/appdir-cli/node_modules/fastboot/lib/ember-app.js:129:18)
    at Sandbox.VMSandbox.run (/path/to/appdir-cli/node_modules/fastboot/lib/vm-sandbox.js:18:13)
    at EmberApp.retrieveSandboxedApp (/path/to/appdir-cli/node_modules/fastboot/lib/ember-app.js:128:30)
    at new EmberApp (/path/to/appdir-cli/node_modules/fastboot/lib/ember-app.js:41:21)
    at FastBoot._buildEmberApp (/path/to/appdir-cli/node_modules/fastboot/index.js:101:17)
    at new FastBoot (/path/to/appdir-cli/node_modules/fastboot/index.js:47:10)
    at repl:1:-51
    at sigintHandlersWrap (vm.js:32:31)
    at sigintHandlersWrap (vm.js:96:12)
    at ContextifyScript.Script.runInContext (vm.js:31:12)
    at REPLServer.defaultEval (repl.js:308:29)
    at bound (domain.js:280:14)
    at REPLServer.runBound [as eval] (domain.js:293:12)
    at REPLServer.<anonymous> (repl.js:489:10)
    at emitOne (events.js:101:20)
    at REPLServer.emit (events.js:188:7)
    at REPLServer.Interface._onLine (readline.js:232:10)
    at REPLServer.Interface._line (readline.js:574:8)
    at REPLServer.Interface._ttyWrite (readline.js:851:14)
    at ReadStream.onkeypress (readline.js:119:10)
    at emitTwo (events.js:106:13)
    at ReadStream.emit (events.js:191:7)
    at emitKeys (internal/readline.js:385:14)
    at next (native)
    at ReadStream.onData (readline.js:947:36)
    at emitOne (events.js:96:13)
    at ReadStream.emit (events.js:188:7)
    at readableAddChunk (_stream_readable.js:177:18)
    at ReadStream.Readable.push (_stream_readable.js:135:10)
    at TTY.onread (net.js:542:20)

I'm likely doing something silly, but strangely, grepping for Fastboot.config deosn't seem to turn up anything so it's not clear how I should go about debugging this...

Please add more descriptive error message for hostWhitelist property in environment.js

Hi I've no idea what that means. I struggled to understand where this hostWhitelist should be defined without success.

My currently dirty environment.js has this:

  var ENV = {
    modulePrefix: 'gitconfig-client',
    environment: environment,
    baseURL: '/',
    locationType: 'auto',
      hostWhitelist: ['localhost'],
    EmberENV: {
      hostWhitelist: ['localhost'],
      FEATURES: {
      hostWhitelist: ['localhost'],
        // Here you can enable experimental features on an ember canary build
        // e.g. 'with-controller': true
      },
      EXTEND_PROTOTYPES: {
      hostWhitelist: ['localhost'],
        Date: false,
      }
    },

    APP: {
      hostWhitelist: ['localhost'],
      // Here you can pass flags/options to your application instance
      // when it is created
    }
  };

And the erro I get when starting FastBoot with:

ember fastboot --port 4200 --host localhost

Is this:

500 Unknown Error: Error: You are using Ember Data with no host defined in your adapter. This will attempt to use the host of the FastBoot request, which is not configured for the current host of this request. Please set the hostWhitelist property for in your environment.js. FastBoot Error: You must provide a hostWhitelist to retrieve the host

TypeError: Cannot read property 'createComment' of undefined

Hi there ๐Ÿ‘‹

I'm currently working with the Ember Learning team to turn the Ember Guides into an Ember App (yay), but I have come across something that I thought was intermittent but I have been able to consistently recreate it now for the first time.

To recreate just checkout https://github.com/ember-learn/guides-app/tree/bug/fastboot-createComment-error npm i and npm start and you should have the new guides-app running locally. Navigate to http://localhost:4200/v2.17.0/tutorial/routes-and-templates/ and you will see an error on the command line.

Here is the stack trace:

There was an error running your app in fastboot. More info about the error:
 TypeError: Cannot read property 'createComment' of undefined
    at ListBlockOpcode.evaluate (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/tmp/broccoli_merge_trees-output_path-FClrsTXr.tmp/assets/@glimmer/runtime.js:6761:1)
    at UpdatingVM.execute (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/tmp/broccoli_merge_trees-output_path-FClrsTXr.tmp/assets/@glimmer/runtime.js:6497:1)
    at RenderResult.rerender (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/tmp/broccoli_merge_trees-output_path-FClrsTXr.tmp/assets/@glimmer/runtime.js:6855:1)
    at RootState._this.render (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/tmp/broccoli_merge_trees-output_path-FClrsTXr.tmp/assets/ember-glimmer/renderer.js:65:1)
    at TransactionRunner.runInTransaction (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/tmp/broccoli_merge_trees-output_path-FClrsTXr.tmp/assets/ember-metal.js:826:1)
    at InertRenderer._renderRoots (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/tmp/broccoli_merge_trees-output_path-FClrsTXr.tmp/assets/ember-glimmer/renderer.js:293:1)
    at InertRenderer._renderRootsTransaction (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/tmp/broccoli_merge_trees-output_path-FClrsTXr.tmp/assets/ember-glimmer/renderer.js:323:1)
    at InertRenderer._revalidate (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/tmp/broccoli_merge_trees-output_path-FClrsTXr.tmp/assets/ember-glimmer/renderer.js:360:1)
    at invokeWithOnError (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/tmp/broccoli_merge_trees-output_path-FClrsTXr.tmp/assets/backburner.js:267:1)
    at Queue.flush (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/tmp/broccoli_merge_trees-output_path-FClrsTXr.tmp/assets/backburner.js:151:1)
    at DeferredActionQueues.flush (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/tmp/broccoli_merge_trees-output_path-FClrsTXr.tmp/assets/backburner.js:329:1)
    at Backburner.end (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/tmp/broccoli_merge_trees-output_path-FClrsTXr.tmp/assets/backburner.js:462:1)
    at Backburner._run (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/tmp/broccoli_merge_trees-output_path-FClrsTXr.tmp/assets/backburner.js:793:1)
    at Backburner._join (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/tmp/broccoli_merge_trees-output_path-FClrsTXr.tmp/assets/backburner.js:775:1)
    at Backburner.join (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/tmp/broccoli_merge_trees-output_path-FClrsTXr.tmp/assets/backburner.js:529:1)
    at Function.run.join (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/tmp/broccoli_merge_trees-output_path-FClrsTXr.tmp/assets/ember-metal.js:4453:1)
    at Object.hash.success (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/tmp/broccoli_merge_trees-output_path-FClrsTXr.tmp/assets/addon-tree-output/modules/ember-data/adapters/rest.js:619:1)
    at fire (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/node_modules/jquery-deferred/lib/jquery-callbacks.js:78:30)
    at Object.fireWith (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/node_modules/jquery-deferred/lib/jquery-callbacks.js:188:7)
    at Object.fire [as resolve] (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/node_modules/jquery-deferred/lib/jquery-callbacks.js:195:10)
    at dataHandler (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/node_modules/najax/lib/najax.js:167:13)
    at IncomingMessage.<anonymous> (/Users/mansona/git/stonecircle/opensource/ember-guides/guides-app/node_modules/najax/lib/najax.js:198:9)
    at emitNone (events.js:110:20)
    at IncomingMessage.emit (events.js:207:7)
    at endReadableNT (_stream_readable.js:1059:12)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)
    at process._tickDomainCallback (internal/process/next_tick.js:218:9)

My first thoughts are something to do with nesting {{#each}} blocks because when you remove this line it all starts working again. I thought at first that it was the recursive component calls but the if you uncomment the following componentless implementation it still breaks.

This is what leads me to think it was the nested {{#each}} that is causing the problem.

This issue does not happen in the browser, just in the fastboot environment.

Always needs vendor.js

Using ember-cli-concat to concatenate all JS to a single app.js is not respected by fastboot.
It always requires a vendor.js file to be present

children elements are rendered outside of parent

In the new ember-api-docs, there is this template:

<p class="attributes">
    {{#if model.extends}}
      <div class="attribute">
     ...
      </div>
    {{/if}}
    {{#if model.uses}}
      <div class="attribute">
     ...
      </div>
    {{/if}}
    {{#if model.file}}
      <div class="attribute">
       ...
      </div>
    {{/if}}
    {{#if model.module}}
      <div class="attribute">
       ...
      </div>
    {{/if}}
  </p>

Fastbooot renders the .attribute outside the .attributes. On client side render it is OK.

Server side render (incorrect)
screen shot 2017-03-17 at 21 10 54
Client side render (correct)
screen shot 2017-03-17 at 21 10 43

Changing the tag name of .attributes from p to div solved the issue there: https://github.com/ember-learn/ember-api-docs/pull/162/files

FastbootHeaders.get trolled me hard.

This is me whining, but I thought that if I got trolled so hard by such a subtle thing, other might be and it could be a way of mitigating it.

A coworker of mine made this change in an ember-data adapter:

          // Check that the returned data is of the expected format
 -        let headers = this.get('fastboot.request.headers');
 -        let contentType = headers.get('Content-Type');
 +        let headers = get(this, 'fastboot.request.headers');
 +        let contentType = get(headers, 'Content-Type');

By all means this seemed like a very reasonable code, it passed the review and got merged.

However, despite of what its so engrained in the mind of any Ember developer, headers.get(key) and get(headers, key) are not equivalent in this context.
See

get(header) {
return this.getAll(header)[0] || null;
}

If there is a way we could prevent other developers to pull their hair, I'd be happy to help

Make sense to prime shoebox from express?

It would be terribly useful if I could start adding to the shoebox in express before my app starts rendering in fastboot. Possible API could be:

let app = new FastBoot({
  distPath: 'path/to/dist',
  shoebox: {
    // ...
  }
});

or

app.visit('/photos', {
  shoebox: {
    // ...
  }
}).then(// ...

Does this make sense? Is there an existing alternative way to do this?

HTTP Redirection in Ember FastBoot

HTTP Redirection in Ember FastBoot

Contributors

@pwfisher, @marcoow, and @briangonzalez. Many thanks for your help!

Summary

Redirects should not break the "Back" button. Redirecting with transitionTo breaks the "Back" button by adding to browser history. replaceWith replaces the current location in the browser's history so that the browser "Back" button will behave as expected.

Accordingly, FastBoot should disallow transitionTo because it breaks the "Back" button. Instead, FastBoot should support replaceWith for redirection.

FastBoot can extend replaceWith to pass HTTP redirect status codes back to FastBoot Server, which would add it to the response along with the updated URL.

This could be implemented by 1) reopening Ember.Router and modifying replaceWith directly; 2) utilizing the willTransition hook for Routes; or 3) adding a replaceWith method to the FastBoot service and requiring developers to explicitly use that to opt in to FastBoot.

When do Ember Applications redirect?

Ember navigation methods typically amend navigation history; however, those same methods are occasionally used to redirect the user.

Examples:

  • User State Changes: Sometimes a user's state within the application requires them to be redirected. For example, a user tries to access http://app/protected/page, but is unauthenticated. Here, we redirect them to http://app/login.
  • Impermanent Routes: If a route's existence is temporary, we might redirect the user to a permanent location for better user experience. For example, a user requests http://app/projects/14, but the project with id 14 was deleted. Here, we redirect them to the main projects page, http://app/projects.
  • Permanently Redirected Routes: If our application contains deprecated routes, vanity routes, or aliased routes, we would transition requests to the new routes while preserving navigation conventions for the user. For example if a user requested http://app/projects/14, but the project is now grouped under Organization one, we would redirect them to the new route of http://app/organization/1/projects/14.

How should FastBoot Server redirect users?

Transitions can break the "Back" Button

Redirection should not break browser history. In Ember, navigation methods alter browser history (via HTML5) as follows:

Method HTML5 History
intermediateTransitionTo none
transitionTo PUSH
transitionToRoute PUSH
Transition#retry PUSH
replaceWith REPLACE

Because transitionTo adds a redirected URL to the browser history, it breaks the "Back" button by not allowing the user to navigate back past the redirect.

FastBoot should redirect with replaceWith

replaceWith should be used for redirection in FastBoot because it does not add a redirected URL to the browser history. This both matches the specified behavior of HTTP 30X status codes and does not break the "Back" button.

FastBoot should never call transitionTo

transitionTo should only be called client-side.

FastBoot should only redirect GET requests

Because FastBoot Server is only concerned with rendering web pages, it should only handle GET requests. Any other HTTP methods should be handled by other middleware or by a different part of the application's front-end stack.

FastBoot should support both temporary and permanent redirection

While there is a compelling case for supporting only only temporary redirection codes, there are many situations where an Ember Application would need to support permanent redirection. In the case of Impermanent Routes, the application would want to signal the browser to update any bookmarked routes. For Permanently Redirected Routes, the same logic applies.

FastBoot should default to temporary redirection since permanent can be harmful.

How should Ember Applications and FastBoot Server divide responsibilities?

Redirects in the Ember Application should:

  1. Abort the rendering of the page,
  2. Generate an appropriate location header,
  3. Generate an appropriate HTTP status code header, and
  4. Pass the headers back to the server middleware layer.

Open Question: How do we abort rendering?

Redirects that FastBoot Server receives should be sent back to the browser, so that it can update itself accordingly and request the new URL.

Because FastBoot Server is middleware, developers can always intercept the request and handle the redirection before it reaches the client, though this is less desirable because it hides the redirection from the browser.

Potential Implementations

Reopen Ember.Router and modify replaceWith

One way to implement this functionality is to reopen Ember.Router and modify Router#replaceWith to take an optional status code, abort rendering, and have it determine the new location. This solution is the most transparent to the Ember Application, but opens up a hard dependency on Ember.Router internals.

Hook into Router#willTransition

Another way to implement this functionality is to hook into willTransition, as the point where we abort rendering, generate a status code, and determine a new location. This is not as tightly coupled to Ember.Router, but does present a less optimal interface for passing along the status code and determining the new location.

Implement FastBoot#redirect

A third way is to create a redirect method on the FastBoot service that would abstract client-side vs server-side complexity from developers. FastBoot#redirect would take the transition arguments plus an optional redirect status code.

This approach would not tightly couple FastBoot code with Ember.Router. But it would result in FastBooted Applications having to modify their application to use FastBoot#redirect everywhere they might use a Route#replaceWith.

Appendix

HTTP Redirection Codes

All responses must provide a target URI to the client.

Permanent redirection requires the client to update all cached references with the provided URI. Temporary redirection requires the client to not remember the provided URI and send all subsequent requests to the original URI.

Clients can redirect without user permission for GET and HEAD request methods. Other request methods require user permission.

Code Status Text Redirect Type Redirecting Request Method
301 Moved Permanently Permanent May be changed
302 Found Temporary Cannot change*
303 See Other Temporary Must be GET
307 Temporary Redirect Temporary Cannot change
308 Permanent Redirect Permanent Cannot change

* 302 status codes are not reliably implemented across browsers. Some browsers implement the request method specification properly. Others require the provided resource to be requested via GET similar to 303.

Further Reading

Accomodate changes to the index without a server restart

since the index will generally point to fingerprinted assets, when i deploy updates to my ember application, the updated index will not be read by the fastboot server until i restart node. it would be really great if there was some way by which the fastboot server could detect a change to the index file on disk and re-read the index from disk--or if there was some means by which i could inform the fastboot server to re-read the index from disk (via redis or something?). or maybe fastboot could read the index from something like redis?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.