Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify fastboot serving with ember-cli #356

Merged
merged 1 commit into from
Apr 7, 2017
Merged

Unify fastboot serving with ember-cli #356

merged 1 commit into from
Apr 7, 2017

Conversation

kratiahuja
Copy link
Contributor

@kratiahuja kratiahuja commented Feb 15, 2017

TL;DR: fixes #274 . This will unblock one of the FastBoot 1.0 blockers.

Motivation

Currently FastBoot provides users to serve the base page and the assets via the ember fastboot command. It primarily spins up an express server that is responsible for serving the request with a fastboot replaced base page and serves other assets from disk. However, this is similar to what ember cli provides via ember serve. Since we are not the infrastructure provided by ember-cli, development with ember fastboot has become very error prone for various reasons. The PR attempts to resolve those development concerns.

How it works

ember-cli@2.12.0-beta.1 and above introduced a public API in ember-cli that allows addons to be responsible for serving the base page and/or assets while still be able to consume the other nice features of ember serve. It does so by splitting the task of watching the build and serving assets into different middleware. Infrastructures like FastBoot can then hook a middleware between the watcher and server middleware and be responsible for serving the base page request.

If apps are using ember-cli@2.12.0-beta.1 and above, they will be able to serve fastboot rendered base page using ember serve and continue using other features of ember serve. For apps running ember-cli version below 2.12.0-beta.1, they will not be able to use ember serve with FastBoot.

With the new serving logic, you can use curl with ember serve:
curl 'http://localhost:4200/' -H 'Accept: text/html'

This PR does the following:

  • Marks ember-cli-fastboot addon to run before broccoli-serve-files addon. broccoli-serve-files is an in-repo addon in ember-cli
  • Uses serverMiddleware API of ember-cli to provide a middleware to use fastboot-express-middleware when there is a base request.
  • Added a message when fastboot is serving the base page
  • Added deprecation message in ember fastboot
  • For any other requests other than base page, it forwards the request to the next middleware in the chain.
  • Live reloads the FastBoot sandbox with rebuilt app and vendor files whenever there is a rebuild.
  • Fixed existing tests
  • Added new tests that test the same functionality as ember fastboot

Advantages

With using ember serve to have FastBoot serve the initial base page request we get the following features for free:

  • Ability to show build errors when the initial page request is made so the development is easier and better
  • Not requiring any infrastructure to explicitly build an express app just for serving.
  • Ability to have other assets served by ember cli as it does for vanilla app
  • Ability to use a proxy server for serving any API requests or any other requests using ember serve --proxy=http://localhost:3000
  • Ability to have live reload in the browser using ember-cli live reload functionality.
  • Ability to load the built assets from tmp directory instead of dist.

Deprecation of ember fastboot

Since this PR does similar to what ember fastboot --watch --serve-assets provides, we will be deprecating ember fastboot command.

Future TODOs

Following are the minor enhancements that I would like to fix on after this PR lands. They do not block this PR.

  • Make FastBoot live reloading much smarter. We do not need to reload the sandbox if there are only CSS changes. Therefore, we could use fs-tree-diff to see if any of the app/vendor files have changed on rebuild and only load it sandbox then.
  • Allow developers to provide sandboxGlobals and/or custom sandbox class when serving using FastBoot in development. No one seems to be using this so just added a TODO for now.
  • Provide a way to turn off fastboot serving at runtime without needing to remove ember-cli-fastboot

cc: @rwjblue @tomdale @danmcclain @stefanpenner @josemarluedke @arjansingh

@kratiahuja kratiahuja changed the title [WIP]: Unify fastboot serving with ember-cli Unify fastboot serving with ember-cli Feb 21, 2017
@kratiahuja
Copy link
Contributor Author

This is now ready for review.

@kratiahuja
Copy link
Contributor Author

kratiahuja commented Feb 21, 2017

Note to self:

  • Test an app with containing broccoli-asset-rev and make sure it still uses fingerprinted assets in manifest.

index.js Outdated
// TODO: we can do a smarter reload here by running fs-tree-diff on files loaded
// in sandbox (explore later).
this.ui.writeLine('Reloading FastBoot...');
this.fastboot.reload({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is fastboot reload synchronous? If it is asynchronous, we may need to do more work to ensure no requests during this period are served.

Copy link
Contributor Author

@kratiahuja kratiahuja Feb 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is synchronous. I confirmed that 😄 Though I plan to make it promise friendly when I take a stab at the smarter reload handling.

Copy link
Member

@rwjblue rwjblue Feb 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can implement the instrumentation hook (ember-cli@2.13+) and detect the output files that have changed, to see if we need to reload fastboot here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. That will eliminate a lot of boiler plate code that I planned to write :)

fastboot: this.fastboot
});

fastbootMiddleware(req, resp, next);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the conditional on line 160 suggests we only serve fastbootMiddelware for the first request, subsequent requests will fallback to the else case.

Copy link
Contributor Author

@kratiahuja kratiahuja Feb 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that is correct (I assume you meant line 158 and not 160). If I understand correctly, FastBoot is only meant for initial requests and that too for the base page request (basically have your app be server side rendered for the initial request). Once the base page request is served, the browser will request for assets which should be served by ember-cli's asset serving. Same also applies for subsquent page transitions in Ember (for lazy engines/lazy template loading usecase).

Do you think that is a wrong assumption? Is there a usecase that I might have missed?

Copy link
Contributor

@stefanpenner stefanpenner Feb 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think that is a wrong assumption? Is there a usecase that I might have missed?

Ya, that isn't quite correct. If a user hard reloads (or issues curl repeatedly), they should once again get a fastboot rendered page.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stefanpenner They will get a fastboot rendered page. FastBoot is just responsible for serving the index.html with the rendered content. I did test both use cases on a test app. I am not sure I am following what is not correct.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your right. for some reason i read line 174 being within the if statement of 161. Not sure how that happened, my bad.

@mfazekas
Copy link

mfazekas commented Feb 22, 2017

@kratiahuja with this change ember serve will be serving fastboot version if i point my browser to http://localhost:4200/. Is there a way to ask for regular (non fastboot) version. Other than remove ember-cli-fastboot from package.json? Usecase is that you see some error with fastboot and want to check if it happens in non fastboot version too.

@danmcclain
Copy link
Member

Just spitballing: what if we could skip injected middleware via query params

index.js Outdated
// forward the request to the next middleware (example other assets, proxy etc)
next();
}
}.bind(this))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can use arrow functions instead of .bind(this).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I totally forgot ember-cli allows arrow functions now. Will update this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to use arrow functions.

@kellyselden
Copy link
Member

@mfazekas @danmcclain https://github.com/ember-fastboot/ember-cli-fastboot#double-build-times-and-no-incremental-builds this is how you can run a normal build without removing the ember-cli-fastboot package.

@danmcclain
Copy link
Member

@kellyselden I was thinking of a way that wouldn't require you to restart the server (and also double build times are going away 🙌 )

@simonihmig simonihmig mentioned this pull request Feb 22, 2017
38 tasks
@kratiahuja
Copy link
Contributor Author

kratiahuja commented Feb 22, 2017

@mfazekas @danmcclain I agree this is a valid usecase but not scoped to this PR. I want to first get base functionality in and then work on this enhancement and others (see future section). I also like the idea of the query param to switch fastboot serving on/off at run time. I was also thinking of providing it via .embercli config file if possible. Mind opening a separate issue for this and I will be happy to address it once this is merged? I would like to evaluate all options on the table and implement the best feasible one.

fastboot: this.fastboot
});

fastbootMiddleware(req, resp, next);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your right. for some reason i read line 174 being within the if statement of 161. Not sure how that happened, my bad.

@kratiahuja
Copy link
Contributor Author

kratiahuja commented Mar 2, 2017

Tested this PR with fastboot-website app on ember-cli version 2.12.0-beta.1 and 2.11.0 (this is the current one) and both worked as expected with ember fastboot --serve-assets and ember serve commands.

cc: @rwjblue

@mfazekas
Copy link

mfazekas commented Mar 2, 2017

We also tested with our app percy-web and it was working great, we needed it for proxy support. (Only issue is FASTBOOT_DISABLED is broken with this PR as it disables fb build but this PR tries to serve it, but that should be addressed in #358).

@kratiahuja
Copy link
Contributor Author

@rwjblue could you please review this? 😄

@josemarluedke
Copy link
Contributor

josemarluedke commented Mar 4, 2017

Awesome work @kratiahuja!

I tested this branch in our application as well as in brand new ember app and it works as a charm. 🎉

Looking forward to have this merged and available to users.

@mirague
Copy link

mirague commented Mar 15, 2017

This looks good!

@bcardarella
Copy link
Contributor

Is there anything else blocking this PR?

@kratiahuja
Copy link
Contributor Author

@bcardarella Nope nothing is blocking this PR except someone reviewing it. I'll ping @rwjblue or someone else again after the ember conference.

@bcardarella
Copy link
Contributor

Didn't @stefanpenner already approve?

@kratiahuja
Copy link
Contributor Author

@bcardarella Yes but I think @rwjblue also wanted to review before merging. Unfortunately I don't have merge powers so we will have to wait for someone with merge powers to review and merge.

@kratiahuja
Copy link
Contributor Author

Bumping this again. @rwjblue could you please review?

@@ -20,7 +20,8 @@ module.exports = {
project: this.project
});

deprecate("Use of ember fastboot:build is deprecated. Please use ember build instead.");
deprecate('ember fastboot:build will be deprecated and removed after FastBoot 1.0 is released.');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why we need to add this extra deprecation here. It seems like the preexisting one should already cover the case we care about, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah but I just wanted to update the deprecation to say we will be dropping this command too.

var checker = new VersionChecker(this);
var dep = checker.for('ember-cli', 'npm');

this.ui.writeWarnLine('`ember fastboot` will no longer work after FastBoot 1.0 is released.');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets only emit this deprecation when ember-cli is less than 2.12.0-beta.1 (basically the else case of the if just below).

@rwjblue
Copy link
Member

rwjblue commented Apr 7, 2017

Only two super minor changes around messaging, then this is good to go...

@kratiahuja
Copy link
Contributor Author

@rwjblue This is good to merge now. Travis is 💚

@rwjblue rwjblue merged commit 38892b1 into ember-fastboot:master Apr 7, 2017
@rwjblue
Copy link
Member

rwjblue commented Apr 7, 2017

Thank you for all your hard work on this @kratiahuja!

@kratiahuja kratiahuja deleted the serve-refactor branch April 7, 2017 14:40
@simonihmig
Copy link
Contributor

Awesome, thanks indeed! 🎉

This was referenced May 21, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

unify ember fastboot --watch + ember server
10 participants