-
Notifications
You must be signed in to change notification settings - Fork 875
feat(prod-deploy): add prod deploy chapter #3043
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job! I reviewed the doc and here is my feedback.
* [Server configuration](#server-configuration) | ||
* [Why fallback to `index.html`?](#why-fallback-to-index-html-) | ||
* [Fallback configuration examples](#fallback-configuration-examples) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great way to organize this content!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
After creating your brand new Angular app you'll want to put it online for the world to see. | ||
|
||
Your development setup is optimized for build speed and rapid iteration, but when | ||
deployment to production you'll want to optimize for loading speed and payload size. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should "deployment" be "deploying" here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right you are, fixing.
It is already working locally after all, so it should work live. | ||
|
||
1. Copy over your local project folder to your server. | ||
2. In your server, edit `index.html` to have the right `<base href="/">` tag. If you are |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using "correct" instead of "right" here since right could mean right/left.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
The simplest possible way to deploy your app is to use your development environment. | ||
It is already working locally after all, so it should work live. | ||
|
||
1. Copy over your local project folder to your server. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my daughter's case, she had a limited amount of allocated space on the server and could not copy all of the node_module folder. Consider mentioning using npm install --production
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added note about production installs.
There are several techniques for achieving a smaller payload for your app: | ||
|
||
- Bundling: concatenating several modules into a single file (bundle). | ||
- Inlining: add html and css as strings inside components. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be "adding" to match the other "-ing" words used here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That one was added later and I forgot to do just that, good catch!
|
||
That is why the server needs to be configured to fallback to `index.html`. | ||
When a user asks the server for any route (that isn't a file), you want the server to *always* | ||
return default page that boots up Angular. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"return the" (missing "the")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
That is why the server needs to be configured to fallback to `index.html`. | ||
When a user asks the server for any route (that isn't a file), you want the server to *always* | ||
return default page that boots up Angular. | ||
After Angular is loaded and bootstrapped the router will look at the address bar and take |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"will look" -> "looks" and "take" -> "takes"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
When a user asks the server for any route (that isn't a file), you want the server to *always* | ||
return default page that boots up Angular. | ||
After Angular is loaded and bootstrapped the router will look at the address bar and take | ||
the user where he needs to go. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we be avoiding he/she? Either "he" -> "they" or change to "takes the user to the appropriate route".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
works everywhere. | ||
|
||
Following are configurations for some of the most popular servers. | ||
The list is by no means exhausting, but should provide you with a good starting point. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exhausting -> exhaustive
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
These APIs need to send the `Access-Control-Allow-Origin: *` header on their HTTP responses, | ||
otherwise the SPA will not be able to call them. | ||
You can read more about how to enable CORS for specific servers in | ||
[enable-cors.org](http://enable-cors.org/server.html) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really good info here! Great job pulling this together!
Thanks for the review @DeborahK, I've incorporated all your feedback now. I think I touched everything you once listed as questions your users had. If there's something missing let me know. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great chapter!
:marked | ||
## Overview | ||
|
||
After creating your brand new Angular app you'll want to put it online for the world to see. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest removing the word brand and just saying After creating your new Angular app.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I may not want it to be online for the world to see. I may be building a corporate internal app. Recommend just saying deploy it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Your development setup is optimized for build speed and rapid iteration, but when | ||
deploying to production you'll want to optimize for loading speed and payload size. | ||
|
||
In this chapter you'll see how to deploy your app right now, techniques to reduce your |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove right now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
## Simplest deploy possible | ||
|
||
The simplest possible way to deploy your app is to use your development environment. | ||
It is already working locally after all, so it should work live. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest It is working locally, so it will work when published to a web server, too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
3. Configure your server to redirect requests for missing files to `index.html` instead. | ||
[More on this later](#server-configuration). | ||
|
||
And this is all you need to publish your app! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove And
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
And this is all you need to publish your app! | ||
|
||
It's not a very good production deploy though. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of negative prose, I suggest ... You've deployed your app, but we can do better for production to optimize the app! Let's learn how.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
This allows Tree-Shaking to further remove exports. | ||
|
||
You can read more about AoT Compilation in our [dedicated cookbook chapter](aot-compiler.html), | ||
where you'll also find instructions on how to use Rollup to perform all the optimizations shown here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest removing the word Rollup
from here. Why? Because we may use something else later and it would be easier to edit just that doc later and not this one too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
The Angular Router allows you to configure NgModules as being | ||
[Lazy Loaded](https://angular.io/docs/ts/latest/guide/router.html#!#asynchronous-routing), | ||
which means that particular NgModule (and all it's code) is not loaded on the very first load. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's
when possessive it its
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
are needed. | ||
|
||
A common mistake to make while lazy loading a module is to *also* have that module imported via | ||
a ES6 import. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a
--> an
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
it to be imported directly instead of being imported via the Router. | ||
|
||
It's important to note that your bundling configuration must take lazy loading into consideration. | ||
Since there is no ES6 import for that module, bundlers don't know that they should also |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we should just use ES import
instead of ES6
import. That safeguards us for future versions ... it is also what I do for all of my material :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, across the doc.
Angular apps are | ||
[Single Page Applications](https://en.wikipedia.org/wiki/Single-page_application) (SPAs), | ||
which makes them the perfect candidates to be served by a simple static HTML server. | ||
No preprocessors required! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know what this means, but will the reader know what a preprocessor
is? either explain or remove.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reworded to
There is no need to have a server-side language composing the pages because
Angular will do it on the client-side.
WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
I very much like the tone, direction, and brevity of this cookbook! I'll put copy edits elsewhere. Here are some stream-of-consciousness questions.
|
@wardbell I edited your comment with my replies so as to not bloat this thread unnecessarily. My replies look like this:
|
I can't edit the comment so I will respond here ...
I've seen many examples of this making a huge difference even on 4G. A large portion of our users use desktop/laptop on WiFi and the difference in 2 seconds to usability vs 3 has quantifiable effects on abandonment and revenue (per some companies I have seen stats from). We don't need to state this. 2 seconds is the bar that most folks I have spoken to have to deal with for public sites. Even with internal apps, there is a focus (though more relaxed) on the speed. I'm sure many companies dont care ... but just as many do. |
I would really like to see this come out sooner rather than later for several reasons:
|
I agree its not a cookbook .. but the content is very valuable. I think we are have a very confusing organization of docs anyway ... we should focus on good content and simply create a master list of the topics. My short term point is that we should publish this sooner rather than later wherever it goes. I highly doubt anyone knows the diff between cookbook and advanced and regular docs :) |
Well I know the difference between a cookbook and guide :-) For sure a cookbook contains detailed instructions you can follow. For sure it contains sample code. This PR offers neither.
Imagine a cookbook recipe called "Boil an egg" that talked about how chickens come from eggs (it might or might not mention that eggs come from chickens), and the relative merits of cooking in hot water versus steam, and how most people used gas stoves ... but never told you what to do. That is a guide at best, not a cookbook recipe at all. At some point we have to go beyond musing about the factors and give people some real instructions. That isn't happening here to my satisfaction. There is one place that comes close to giving actual instruction for deploying to a server - the "Simplest possible deploy" - and even that omits crucial details or an example for even one server. There is no accompanying code, nothing you can run, nothing you can see that looks like a production app.
Having said that, so pressing is the need for something that I agree to completing the review and copy-editing this week ... as a preliminary guide. Hold me to it! |
So there's good news and bad news. 👍 The good news is that everyone that needs to sign a CLA (the pull request submitter and all commit authors) have done so. Everything is all good there. 😕 The bad news is that it appears that one or more commits were authored by someone other than the pull request submitter. We need to confirm that they're okay with their commits being contributed to this project. Please have them confirm that here in the pull request. Note to project maintainer: This is a terminal state, meaning the |
1 similar comment
So there's good news and bad news. 👍 The good news is that everyone that needs to sign a CLA (the pull request submitter and all commit authors) have done so. Everything is all good there. 😕 The bad news is that it appears that one or more commits were authored by someone other than the pull request submitter. We need to confirm that they're okay with their commits being contributed to this project. Please have them confirm that here in the pull request. Note to project maintainer: This is a terminal state, meaning the |
3158397
to
3c083a7
Compare
723d1a6
to
b8d91ab
Compare
CLAs look good, thanks! |
1 similar comment
CLAs look good, thanks! |
|
||
The `node_modules` folder is huge and slow to upload to the server. | ||
It's typically 20,500+ files and 180+ MB. | ||
The application itself requires a tiny fraction of that to run. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see what you mean with this, but my first impression (even when I know what you mean) is that we need like a mini node_modules
folder in our deploy to make it work. Like... let's remove a bunch of files that we don't need and leave what we need.
So there's good news and bad news. 👍 The good news is that everyone that needs to sign a CLA (the pull request submitter and all commit authors) have done so. Everything is all good there. 😕 The bad news is that it appears that one or more commits were authored by someone other than the pull request submitter. We need to confirm that they're okay with their commits being contributed to this project. Please have them confirm that here in the pull request. Note to project maintainer: This is a terminal state, meaning the |
1 similar comment
So there's good news and bad news. 👍 The good news is that everyone that needs to sign a CLA (the pull request submitter and all commit authors) have done so. Everything is all good there. 😕 The bad news is that it appears that one or more commits were authored by someone other than the pull request submitter. We need to confirm that they're okay with their commits being contributed to this project. Please have them confirm that here in the pull request. Note to project maintainer: This is a terminal state, meaning the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
other notes:
- we should probably mention the thing about Rx operators (importing them directly vs the entirety of Rx?)
- maybe mention WebPageTest for verifying perf / succesful deployment>
This guide describes techniques for preparing and deploying an Angular application to a server running remotely. | ||
The techniques progress from _easy but suboptimal_ to _more optimal and more involved_. | ||
|
||
* The [simple way](#dev-deploy "Simplest deployment possible") is to copy the development environment to the server. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably not something we want to recommend, ever?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is value is describing how to deploy your dev code with the minimum set of changes. This is a question that comes up a couple of times every week.
I'll add a note that this isn't recommended per se, but rather a fallback.
|
||
1. Enable production mode as [described below](#enableprodmode) (optional). | ||
|
||
That's all it takes to publish your app! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above. Concerned people will stop here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will reword to avoid that.
:marked | ||
### Load npm packages from the web (SystemJS) | ||
|
||
The `node_modules` folder of _npm packages_ is huge and slow to upload to the server. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets avoid pejorative words like "huge" and "slow: :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix.
|
||
Load the _npm packages_ from the web instead. | ||
|
||
(1) Make a copy of `index.html` for deployment and replace all `node_module` scripts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think here, we want to use SystemJS builder instead. UMD bundles are a less optimal option and straight out won't work with AoT
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This section is meant to show the simplest possible deploy. Adding a build step would go against that. I'll clarify that further.
There is also the concern of adding another interim build step that isn't further detailed or documented. It's better to jump directly to the rollup+aot configuration for optimization.
+makeExample('index.html', 'systemjs-config', '')(format=".") | ||
:marked | ||
(3) Add `systemjs.config.server.js` (shown in the code sample below) to the root folder. | ||
This alternative version configures _SystemJS_ to load _UMD_ versions of Angular |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto. UMD !== deployment.
the app takes longer to launch than it would if you optimized it. | ||
Several seconds may pass (or worse) before the user can see or do anything userful. | ||
|
||
Does it matter? That depends upon business and technical factors you must evaluate for yourself. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a hard time with this. I can't see a scenario where it's beneficial to deploy to production without these things. Why even ask the question?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the docs meetings a couple of real world scenarios came up. Deploying demos was one, and for some projects there is no time/feature budget to actually produce an optimized deployment since the business does not need it.
- Minification: removes excess whitespace, comments, and optional tokens. | ||
- Uglification: rewrites code to use short, cryptic variable and function names. | ||
- Dead code elimination: removes unused code. | ||
- Tree shaking: removes unreferenced modules. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dead code elimination is basically the same as Treeshaking, for the purposes of this doc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Tree shaking with rollup
section talks a bit more about it, and links to an article that elaborates on the differences.
df7e961
to
6ec5f5c
Compare
@robwormald I added a commit addressing your suggestions:
|
This PR LGTM. couple of notes, more to @wardbell than anyone:
As of today, script parsing time (which is a function of how much JS you ship to browser) is the #1 (by far) cost of getting angular apps booted, especially on mobile devices. This is worse with mega-vendor bundles.
This is more server dependent (does your server support HTTP2 (push?) - if it does, somewhat counterintuitively, its much faster to load a bunch of smaller scripts over the single connection than one large script (!). This whole pattern is changing and I want to be cautious about getting overly prescriptive about these sorts of things while stuff is in flux. |
@robwormald Thanks for the perf feedback and for demonstrating these points to me personally (Stephen did so too). I understand much better. I think we're silent on which factors are "more important" ... and silence is golden. Thanks for your help! |
This PR adds the Deployment Chapter.
This PR adds the Production Deployment Cookbook.
/cc @wardbell @Foxandxss @DeborahK