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.
Webpack is a popular general purpose packaging tool with a rich ecosystem, including plugins for AOT.
The Angular webpack guide can get you started and
this page provides additional optimization advice, but you'll probably have to learn more about webpack on your own.
If you're serving the app out of a subfolder,
edit a version of index.html to set the <base href> appropriately.
For example, if the URL to index.html is www.mysite.com/my/app/, set the base href to
<base href="/my/app/">.
Otherwise, leave it alone.
More on this below.
This is not a production deployment. It's not optimized and it won't be fast for users.
It might be good enough for sharing your progress and ideas internally with managers, teammates, and other stakeholders.
Be sure to read about optimizing for production below.
The node_modules folder of npm packages contains much more code
than is needed to actually run your app in the browser.
The node_modules for the Quickstart installation is typically 20,500+ files and 180+ MB.
The application itself requires a tiny fraction of that to run.
上传这些不需要的文件需要很长时间,而在库的下载期间,用户得进行不必要的等待。
It takes a long time to upload all of that useless bulk and
users will wait unnecessarily while library files download piecemeal.
(1) Make a copy of index.html for deployment and replace all node_module scripts
with versions that load from the web. It might look like this.
<!-- Polyfills --><scriptsrc="https://unpkg.com/core-js/client/shim.min.js"></script><!-- Update these package versions as needed --><scriptsrc="https://unpkg.com/zone.js@0.8.4?main=browser"></script><scriptsrc="https://unpkg.com/systemjs@0.19.39/dist/system.src.js"></script>
(3) Add systemjs.config.server.js (shown in the code sample below) to the src/ folder.
This alternative version configures SystemJS to load UMD versions of Angular
(and other third-party packages) from the web.
In the standard SystemJS config, the npm path points to the node_modules/.
In this server config, it points to
https://unpkg.com,
a site that hosts npm packages,
and loads them from the web directly.
There are other service providers that do the same thing.
If you are unwilling or unable to load packages from the open web,
the inventory in systemjs.config.server.js identifies the files and folders that
you would copy to a library folder on the server.
Then change the config's 'npm' path to point to that folder.
用一个例子实践一下
Practice with an example
下面这个例子展示了所有的修改。
The following trivial router sample app shows these changes.
Inspect the network traffic in the browser developer tools.
Notice that it loads all packages from the web.
You could delete the node_modules folder and the app would still run
(although you wouldn't be able to recompile or launch lite-server
until you restored it).
把范例工程部署到服务器上(但node_modules文件夹除外)
Deploy the sample to the server (minus the node_modules folder!).
掌握这些之后,就可以在你的真实项目中试用这些过程了。
When you have that working, try the same process on your application.
为生产环境优化
Optimize for production
虽然可以直接从开发环境下部署,但是它还远远没有优化。
Although deploying directly from the development environment works, it's far from optimal.
The client makes many small requests for individual application code and template files,
a fact you can quickly confirm by looking at the network tab in a browser's developer tools.
Each small file download can spend more time communicating with the server than tranfering data.
Development files are full of comments and whitespace for easy reading and debugging.
The browser downloads entire libraries, instead of just the parts the app needs.
The volume of code passed from server to client (the "payload")
can be significantly larger than is strictly necessary to execute the application.
The many requests and large payloads mean
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.
如果重要,那么有很多工具和技术可以减少请求数和体积。
If it does matter, there are tools and techniques to reduce the number of requests and the size of responses.
Learn more about AOT Compilation in the AOT Cookbook
which describes running the AOT compiler from the command line
and using rollup for bundling, minification, uglification and tree shaking.
Webpack 2 is another
great option for inlining templates and style-sheets, for bundling, minifying, and uglifying the application.
The "Webpack: an introduction" guide will get you started
using webpack with Angular.
Consider configuring Webpack with the official
Angular Ahead-of-Time Webpack Plugin.
This plugin transpiles the TypeScript application code,
bundles lazy loaded NgModules separately,
and performs AOT compilation — without any changes to the source code.
使用rollup消除死代码
Dead code elimination with rollup
任何永远不会调到的代码就是死代码。
通过移除应用和第三方库中的死代码,可以实质性减小应用的总大小。
Any code that you don't call is dead code.
You can reduce the total size of the application substantially by removing dead code from the application and from third-party libraries.
Tree shaking is a dead code elimination technique that removes entire exports from JavaScript modules.
If a library exports something that the application doesn't import, a tree shaking tool removes it from the code base.
Tree shaking was popularized by
Rollup, a popular tool with an ecosystem of
plugins for bundling, minification, and uglification.
Learn more about tree shaking and dead code elmination in
this post by rollup-creator, Rich Harris.
修剪库
Pruned libraries
不要指望自动移除所有死代码。
Don't count on automation to remove all dead code.
Some libraries offer facilities for building a custom, skinny version with just the features you need.
Other libraries let you import features a la carte.
RxJS is a good example; import RxJS Observable operators individually instead of the entire library.
You can make better decisions about what to optimize and how when you have a clear and accurate understanding of
what's making the application slow.
The cause may not be what you think it is.
You can waste a lot of time and money optimizing something that has no tangible benefit or even makes the app slower.
You should measure the app's actual behavior when running in the environments that are important to you.
The HTML <base href="..."/>
specifies a base path for resolving relative URLs to assets such as images, scripts, and style sheets.
For example, given the <base href="/my/app/">, the browser resolves a URL such as some/place/foo.jpg
into a server request for my/app/some/place/foo.jpg.
During navigation, the Angular router uses the base href as the base path to component, template, and module files.
In development, you typically start the server in the folder that holds index.html.
That's the root folder and you'd add <base href="/"> near the top of index.html because / is the root of the app.
But on the shared or production server, you might serve the app from a subfolder.
For example, when the URL to load the app is something like http://www.mysite.com/my/app/,
the subfolder is my/app/ and you should add <base href="/my/app/"> to the server version of the index.html.
当base标签没有正确配置时,该应用会加载失败,并且浏览器的控制台会对这些缺失的文件显示404 - Not Found错误。
看看它在尝试从哪里查找那些文件,并据此调整base标签。
When the base tag is misconfigured, the app fails to load and the browser console displays 404 - Not Found errors
for the missing files. Look at where it tried to find those files and adjust the base tag appropriately.
启用生产模式
Enable production mode
Angular应用默认运行在开发模式下,正如在浏览器控制台中看到的如下信息:
Angular apps run in development mode by default, as you can see by the following message on the browser
console:
Angular is running in the development mode. Call enableProdMode() to enable the production mode.
(Angular正运行在开发模式下。调用enableProdMode()来启用生产模式)
切换到生产模式可以通过禁用开发环境下特有的检查(比如双重变更检测周期)来让应用运行得更快。
Switching to production mode can make it run faster by disabling development specific checks such as the dual change detection cycles.
It's a common mistake.
You've arranged to lazy load a module.
But you unintentionally import it, with a JavaScript import statement,
in a file that's eagerly loaded when the app starts, a file such as the root AppModule.
If you do that, the module will be loaded immediately.
The bundling configuration must take lazy loading into consideration.
Because lazy loaded modules aren't imported in JavaScript (as just noted), bundlers exclude them by default.
Bundlers don't know about the router configuration and won't create separate bundles for lazy loaded modules.
You have to create these bundles manually.
Angular apps are perfect candidates for serving with a simple static HTML server.
You don't need a server-side engine to dynamically compose application pages because
Angular does that on the client-side.
If the app uses the Angular router, you must configure the server
to return the application's host page (index.html) when asked for a file that it does not have.
A routed application should support "deep links".
A deep link is a URL that specifies a path to a component inside the app.
For example, http://www.mysite.com/heroes/42 is a deep link to the hero detail page
that displays the hero with id: 42.
There is no issue when the user navigates to that URL from within a running client.
The Angular router interprets the URL and routes to that page and hero.
But clicking a link in an email, entering it in the browser address bar,
or merely refreshing the browser while on the hero detail page —
all of these actions are handled by the browser itself, outside the running application.
The browser makes a direct request to the server for that URL, bypassing the router.
静态服务器会在收到对http://www.mysite.com/的请求时返回index.html,但是会拒绝对http://www.mysite.com/heroes/42的请求,
并返回一个404 - Not Found错误,除非,我们把它配置成转而返回index.html。
A static server routinely returns index.html when it receives a request for http://www.mysite.com/.
But it rejects http://www.mysite.com/heroes/42 and returns a 404 - Not Found error unless it is
configured to return index.html instead.
There is no single configuration that works for every server.
The following sections describe configurations for some of the most popular servers.
The list is by no means exhaustive, but should provide you with a good starting point.
RewriteEngineOn# If an existing asset or directory is requested go to it as it isRewriteCond%{DOCUMENT_ROOT}%{REQUEST_URI}-f [OR]RewriteCond%{DOCUMENT_ROOT}%{REQUEST_URI}-d
RewriteRule^-[L]# If the requested resource doesn't exist, use index.htmlRewriteRule^/index.html
GitHub Pages: you can't
directly configure
the GitHub Pages server, but you can add a 404 page.
Copy index.html into 404.html.
It will still be served as the 404 response, but the browser will process that page and load the app properly.
It's also a good idea to
serve from docs/ on master
and to
create a .nojekyll file
Angular developers may encounter a
cross-origin resource sharing error when making a service request (typically a data service request).
to a server other than the application's own host server.
Browsers forbid such requests unless the server permits them explicitly.
There isn't anything the client application can do about these errors.
The server must be configured to accept the application's requests.
Read about how to enable CORS for specific servers at
enable-cors.org.