-
Notifications
You must be signed in to change notification settings - Fork 125
Host and deploy topic #15
Changes from 4 commits
3632ed2
d0192f7
d9124b0
a10c9d0
705e749
a1865bb
ae3a4de
24794f8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
--- | ||
title: Host and deploy Blazor | ||
author: guardrex | ||
description: Discover how to host and deploy Blazor apps using ASP.NET Core, Content Delivery Networks (CDN), file servers, and GitHub Pages. | ||
manager: wpickett | ||
ms.author: riande | ||
ms.custom: mvc | ||
ms.date: 04/09/2018 | ||
ms.prod: asp.net-core | ||
ms.technology: aspnet | ||
ms.topic: article | ||
uid: client-side/blazor/host-and-deploy/index | ||
--- | ||
# Host and deploy Blazor | ||
|
||
By [Luke Latham](https://github.com/guardrex) and [Rainer Stropek](https://www.timecockpit.com) | ||
|
||
[!INCLUDE[](~/includes/blazor-preview-notice.md)] | ||
|
||
## Publishing | ||
|
||
Blazor apps are published for deployment in Release configuration with the [dotnet publish](https://docs.microsoft.com/dotnet/core/tools/dotnet-publish) command: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just as a general point, is the passive tone considered house style? I would normally write something like "You can publish a Blazor app for deployment using the following command..." There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, we avoid 2nd person whenever possible, which often leads to passive voice. It's more of a repo rule than a MS style manual guideline. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we need to clarify a bit what "publish" means in this context. Publishing in the .NET Core world means something pretty specific that I believe is different from what most people think of as publishing. Publishing for us means preparing the app to be deployed. You can't just deploy the built output. So maybe say something like: "To prepare a Blazor app for deployment it first needs to be published. Publishing the app packs the application and its dependencies into a folder for deployment to a hosting system. Blazor apps are published for deployment using the [dotnet publish]((https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish) command. . ." There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have an idea that given how much I just ripped the guts out of this that I should try to work that back in on the following commit (after the next one). I'm performing a big overhaul of the layout here. Let's see where "publish" fits after the next commit, and then I can roll that language into it. I think that in an IDE one can build/publish and probably (?) get to the assets (dist folder) without running the |
||
|
||
```console | ||
dotnet publish -c Release | ||
``` | ||
|
||
The .NET linker strips unused [Intermediate Language (IL)](https://docs.microsoft.com/dotnet/standard/managed-code) when the app is built in Release configuration. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of saying it strips unused IL, could we say it strips unused methods? (which BTW is the actual level of granularity it works on) Example: As part of the build process, the .NET linker removes any unused methods and assemblies. This makes the resulting application payload much smaller than it would have been if the entire .NET Base Class Library (BCL) was packaged with it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The link is actually run on every build, not just on publish. I would also prefer not to use the made up name ".NET linker". Instead how about: "When the app is published it will first be built (if it hasn't been already). As part of the build any used methods and assemblies will be removed to reduce app download size and speed up load times." |
||
|
||
The deployment is created in the */bin/Release/netstandard2.0/publish* folder. The assets in the *publish* folder are moved to the web server. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That's misleading as it implies it happens automatically. Just running There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yep ... let's make a new section for this remark called Deployment. We can expand the language from there on the next commit if needed. |
||
|
||
## Rewrite URLs for correct routing | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is good content but we should be clear it's only applicable to publishing standalone (not ASP.NET-hosted) Blazor apps. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think most of the content in this section belongs in the routing doc, not here. It's really only the last two paragraphs that address the host concern of dealing with requests to specific pages. |
||
|
||
Routing requests for page components in a client-side app isn't as simple as routing requests to a server-side, hosted app. Consider a client-side app with two pages: | ||
|
||
* **_Main.cshtml_**: Loads at the root of the app and contains a link to the About page (`href="/About"`). | ||
* **_About.cshtml_**: About page. | ||
|
||
When the app's default document is requested using the browser's address bar (for example, `https://www.contoso.com/`): | ||
|
||
1. The browser makes a request. | ||
1. The default page is returned, which is usually *index.html*. | ||
1. *index.html* bootstraps the app. | ||
1. Blazor's router loads and the Razor Main page (*Main.cshtml*) is displayed. | ||
|
||
On the Main page, selecting the link to the About page loads the About page. Selecting the link to the About page works on the client because the Blazor router stops the browser from making a request on the Internet to `www.contoso.com` for `/About` and serves the About page itself. All of the requests for internal pages *within the client-side app* work the same way: Requests don't trigger browser-based requests to server-hosted resources on the Internet. The router handles the requests internally. | ||
|
||
If a request is made using the browser's address bar for `www.contoso.com/About`, the request fails. No such resource exists on the app's Internet host, so a *404 Not found* response is returned. | ||
|
||
Because browsers make requests to Internet-based hosts for client-side pages, hosts of hosted Blazor apps must rewrite all requests to the *index.html* page. When *index.html* is returned, the app's client-side router takes over and responds with the correct resource. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
A bit awkward |
||
|
||
Not all hosting scenarios permit the enforcement of rewrite rules. Additional information is provided in the hosting configuration examples that follow. | ||
|
||
## Host with ASP.NET Core | ||
|
||
ASP.NET Core apps that host Blazor apps configure the server-side app's middleware pipeline with the `UseBlazor` extension method on [IApplicationBuilder](https://docs.microsoft.com/dotnet/api/microsoft.aspnetcore.builder.iapplicationbuilder) in `Startup.Configure`: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest starting this section with: "Blazor integrates with ASP.NET Core to handle single-page application routing and to host the Blazor app as static files. ASP.NET Core apps host Blazor apps by first referencing them as dependencies and then configuring each app in the server-side app's middleware pipeline with the |
||
|
||
```csharp | ||
public void Configure(IApplicationBuilder app, IHostingEnvironment env) | ||
{ | ||
if (env.IsDevelopment()) | ||
{ | ||
app.UseDeveloperExceptionPage(); | ||
} | ||
|
||
app.UseBlazor<Client.Program>(); | ||
} | ||
``` | ||
|
||
The `UseBlazor` extension method performs the following tasks: | ||
|
||
* Reads the Blazor configuration file (*.blazor.config*) from the `ClientAssemblyPath`, which is either an option provided to the `UseBlazor` extension method or defaulted to the app's assembly file location. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's not mention the |
||
* Configures [Static File Middleware](https://docs.microsoft.com/aspnet/core/fundamentals/static-files) to serve Blazor's static assets from the *dist* folder. In the Development environment, the files in *wwwroot* are served. | ||
* Configure live reloading when in the Development environment and Debug configuration. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No live reloading in 0.2.0 any more |
||
* Configure single-page application routing for files outside of the *_framework* folder, which serves the default page (*index.html*) for any request that hasn't been served by a prior Static File Middleware instance. | ||
|
||
For general information on ASP.NET Core app hosting and deployment, see: | ||
|
||
* [Host and deploy ASP.NET Core](https://docs.microsoft.com/aspnet/core/host-and-deploy) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this first link is sufficient. |
||
* [Host ASP.NET Core on Azure App Service](https://docs.microsoft.com/aspnet/core/host-and-deploy/azure-apps/) | ||
* [.NET Core application deployment](https://docs.microsoft.com/dotnet/core/deploying/) | ||
* [Deploying .NET Core apps with command-line interface (CLI) tools](https://docs.microsoft.com/dotnet/core/deploying/deploy-with-cli) | ||
* [Deploying .NET Core apps with Visual Studio](https://docs.microsoft.com/dotnet/core/deploying/deploy-with-vs) | ||
|
||
## Docker/Linux hosting | ||
|
||
The first line of the Blazor config file (*.blazor.config*) configures the source MSBuild path to `.`. A consequence of this setting is that the webroot path is set to `.\wwwroot`, which results in published files being split between *wwwroot* and *dist* folders. For an unsupported workaround, see [On linux UseBlazor extension method fails with "The path must be absolute"](https://github.com/aspnet/Blazor/issues/376). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This bug is fixed, but in any case developers shouldn't have to know about the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this section should be removed. |
||
|
||
## Static deployment strategies | ||
|
||
The following static deployment strategies make the Blazor deployment's static assets available directly for download. Conceptually, other static hosting system configurations are similar. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This phrasing feels overcomplicated. Suggestion: If you're deploying a standalone Blazor application, you can use any web server that serves static files. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, can't use "you" (unless it can't be avoided). How about ...
Although, we'll eat those words with Azure CDN AFAICT. I might need to take a little more time with it. I noted that |
||
|
||
### IIS | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder how useful it is really to describe how to configure IIS to serve static content. Might there be some external IIS documentation we could link to instead? It's not Blazor-specific. What do you think @danroth27? If we were going to put in detailed instructions, I'd suggest focusing on Azure app service deployment would be a much higher priority. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @rstropek says he has direct experience with Blazor client-server apps on Azure App Service, and he can link our aspnet/Docs content to help explain and handle troubleshooting. We have an issue open to cover it: #18 RE: IIS static file server I looked ... the coverage isn't as clear and focused as I would've liked. My (biased) impression is that following these instructions makes IIS config simple and fast. I'll check their IIS topic again and report back. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ugh .....
Yeah ... that's what I saw a few days ago. I'd prefer NOT to link those for several reasons, including missing info and references to WS1012. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would prefer to not document how to install and setup a site with IIS. That should be documented in the IIS docs. I do however agree that piecing together the full set of steps listed here from the IIS docs is not easy. @shirhatti You should consider working with @guardrex to make the IIS docs better so he doesn't have to keep documenting all these steps 😃 I do think we need to document that we generate a web.config file with the right mime type mappings and URL rewrite rules, and that you nee to install the URL rewrite module. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also think documenting Azure App Service is required. At a minimum we should document that from VS you can right-click -> Publish. |
||
|
||
IIS is a capable static file server for Blazor apps. To configure IIS to host Blazor, follow these steps provided. | ||
|
||
In the following configuration examples, the app name, and thus the app folder name, is *MyBlazorApp*. The *MyBlazorApp* folder and *web.config* file are in the *publish* folder. | ||
|
||
**Public hosting with Windows Server operating systems** | ||
|
||
> [!NOTE] | ||
> When working with an Azure VM, open either or both HTTP (80) and HTTPS (443) ports to allow HTTP/HTTPS traffic to the VM. In the Azure portal, use the VM's **SETTINGS** > **Networking** > **Add inbound port rule** to open ports. For more information, see [How to open ports to a virtual machine with the Azure portal](https://docs.microsoft.com/azure/virtual-machines/windows/nsg-quickstart-portal). | ||
|
||
1. Use the **Add Roles and Features** wizard from the **Manage** menu or select the **Add Roles and Features** link in **Server Manager** to enable the **Web Server (IIS)** server role. In the **Server Roles** step, check the box for **Web Server (IIS)**. | ||
1. After the **Features** step, the **Role services** step loads for Web Server (IIS). Accept the default role services provided. The default role services include **Web Server** > **Common HTTP Features** > **Static Content** and **Web Server** > **Performance** > **Static Content Compression**. | ||
1. Proceed through the **Confirmation** step to install the web server role and services. A server/IIS restart isn't required after installing the **Web Server (IIS)** role. | ||
1. Use the Web Platform Installer to install the [URL Rewrite Module](https://www.iis.net/downloads/microsoft/url-rewrite): | ||
1. Locally, navigate to the [URL Rewrite Module downloads page](https://www.iis.net/downloads/microsoft/url-rewrite#additionalDownloads). For English, select **WebPI** to download the WebPI installer. For other languages, select the appropriate architecture for the server (x86/x64) to download the installer. | ||
1. Copy the installer to the server. Run the installer. Select the **Install** button and accept the license terms. A server restart isn't required after the install completes. | ||
1. Open the **Internet Information Services (IIS) Manager** by selecting its link in the **Tools** menu of **Server Manager**. | ||
1. In the **Connections** sidebar (left side of the window), open the server's node. Right-click the **Sites** folder and select **Add Website** from the menu. | ||
1. Configure the website: | ||
1. Set the **Physical path** to the *publish* folder of the deployed Blazor app. The *publish* folder contains: | ||
* The *web.config* file that IIS uses to configure the website, including required redirect rules and file content types. | ||
* The app's folder, *MyBlazorApp*. | ||
1. Configure the **Binding**. Note that the **Default Web Site** is configured to use port 80 at the server's IP address. To use port 80 for the Blazor app, change the **Binding** of the **Default Web Site** to a port other than 80, such as 8000, before setting the binding for the Blazor app (or remove the **Default Web Site** from the server). When testing with the server's public IP address, the app is reachable at `http://<server-IP-address>`. Alternatively, the port of the Blazor app can be set to some other port than 80. Don't forget to set an inbound security rule for the same port if the site is hosted by an Azure VM. | ||
1. Select **OK** to add the website. | ||
1. Navigate to the Blazor app on the Internet using the binding information configured for the website. | ||
|
||
**Local hosting on Windows desktop operating systems** | ||
|
||
1. Navigate to **Control Panel** > **Programs** > **Programs and Features** > **Turn Windows features on or off** (left side of the window). | ||
1. Open the **Internet Information Services** node. Open the **Web Management Tools** node. | ||
1. Check the box for **IIS Management Console**. | ||
1. Check the box for **World Wide Web Services**. | ||
1. Accept the default features for **World Wide Web Services**. The default features include **Common HTTP Features** > **Static Content** and **Performance Features** > **Static Content Compression**. Select the **OK** button to install the IIS features. | ||
1. Use the Web Platform Installer to install the [URL Rewrite Module](https://www.iis.net/downloads/microsoft/url-rewrite): | ||
1. Navigate to the [URL Rewrite Module downloads page](https://www.iis.net/downloads/microsoft/url-rewrite#additionalDownloads). For English, select **WebPI** to download the WebPI installer. For other languages, select the appropriate architecture for the server (x86/x64) to download the installer. | ||
1. Run the installer. Select the **Install** button and accept the license terms. A restart isn't required after the install completes. | ||
1. Open the **Internet Information Services (IIS) Manager** by executing **inetmgr.exe** from a run command prompt or by searching for **IIS** and selecting the app's link in the search results. | ||
1. In the **Connections** sidebar (left side of the window), open the server's node. Right-click the **Sites** folder and select **Add Website** from the menu. | ||
1. Configure the website: | ||
1. Provide a **Site name**. | ||
1. Set the **Physical path** to the *publish* folder of the deployed Blazor app. The *publish* folder contains: | ||
* The *web.config* file that IIS uses to configure the website, including required redirect rules and file content types. | ||
* The app's folder, *MyBlazorApp*. | ||
1. Configure the **Binding**. Provide a high numbered port (for example, 8000) and leave the **Host name** blank or set it to `localhost`. | ||
1. Select **OK** to add the website. | ||
1. Select the website in the **Sites** folder. | ||
1. Navigate to the Blazor app: In the IIS Manager's **Action** sidebar (right side of the window), select the link under **Browse Website** to open the app in the default browser. If the port was set to 8000, the Blazor app is available at `http://localhost:8000`. | ||
|
||
### Nginx | ||
|
||
The following *nginx.conf* file is simplified to show how to configure Nginx to send the *Index.html* file whenever it cannot find a corresponding file on disk. | ||
|
||
``` | ||
events { } | ||
http { | ||
server { | ||
listen 80; | ||
|
||
location / { | ||
root /usr/share/nginx/html; | ||
try_files $uri $uri/ /Index.html =404; | ||
} | ||
} | ||
} | ||
``` | ||
|
||
For more information on production Nginx web server configuration, see [Creating NGINX Plus and NGINX Configuration Files](https://docs.nginx.com/nginx/admin-guide/basic-functionality/managing-configuration-files/). | ||
|
||
### Nginx in Docker | ||
|
||
Add one line to the Dockerfile, as shown in the following example: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This says to modify a Dockerfile that I didn't even know I had yet. Can we add a sentence before this that provides some context? Maybe say something like: "To host Blazor in Docker using Nginx, setup your Dockerfile to use the Alpine based Nginx image. Then update the Dockerfile to copy your |
||
|
||
``` | ||
FROM nginx:alpine | ||
COPY ./bin/Release/netstandard2.0/publish /usr/share/nginx/html/ | ||
COPY nginx.conf /etc/nginx/nginx.conf | ||
``` | ||
|
||
### GitHub Pages | ||
|
||
Blazor apps can be hosted on [GitHub Pages](https://pages.github.com/). For an unsupported example approach, see [Rafael Pedicini's](http://www.rafaelpedicini.com/) [Single Page Apps for GitHub Pages](http://spa-github-pages.rafrex.com/) ([rafrex/spa-github-pages on GitHub](https://github.com/rafrex/spa-github-pages#readme)). Another example using the same approach can be seen at [blazor-demo/blazor-demo.github.io | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We shouldn't documented "unsupported" things. But it's OK to describe work that needs to be done and then to give example solutions. For example: "To handle URL rewrites you can add a There also an issue if you use a project site, instead of an org site. Project sites have a path, so I think you need to update the base tag in |
||
on GitHub](https://github.com/blazor-demo/blazor-demo.github.io) ([live site](https://blazor-demo.github.io/)). |
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 structure of this doc might be a bit confusing. I think we should make clear the two different hosting models (standalone and hosted-on-ASP.NET) and explain what you need to do to deploy in each case. Example:
This "Publishing" subheading relates to standalone but not to the hosted-on-ASP.NET model. We don't want to confuse people doing hosted-on-ASP.NET by implying they should be running
dotnet publish
on the client app.The "Rewrite URLs for correct routing" content applies to standalone publishing only.
People using the "Blazor hosted" template (i.e., the hosted-on-ASP.NET publishing model) don't need to do anything other than the normal ASP.NET server-side publishing process, so I hope we can just link to those docs. We just need to emphasise that it's the server project you need to publish, not the client one (which automatically gets included with the server).