如何在自托管环境中压缩 ASP.NET Core 中的静态内容
How to gzip static content in ASP.NET Core in a self host environment
在使用自托管环境发布 ASP.NET 核心网站时,是否有办法提供 gzip 静态内容?
如果客户端支持,您可以实施压缩响应内容的操作过滤器。
这是 MVC5 中的示例。您应该能够修改它以使用 MVC 6:
http://www.erwinvandervalk.net/2015/02/enabling-gzip-compression-in-webapi-and.html
@Ilya 的回答非常好,但如果您不使用 Gulp,这里有两种选择。
ASP.NET 核心响应压缩中间件
在ASP.NET核心BasicMiddlware repository, you can find (at time of writing) a pull request (PR) for Response Compression Middleware。您可以下载代码并将其添加到您 IApplicationBuilder
中(在撰写本文时):
public void Configure(IApplicationBuilder app)
{
app.UseResponseCompression(
new ResponseCompressionOptions()
{
MimeTypes = new string[] { "text/plain" }
});
// ...Omitted
}
IIS(Internet 信息服务器)
IIS(Internet 信息服务器)有一个本机静态文件模块,它独立于您在本文中了解的 ASP.NET 静态文件中间件组件。由于 ASP.NET 模块在 IIS 本机模块之前 运行,因此它们优先于 IIS 本机模块。从 ASP.NET Beta 7 开始,IIS 主机已更改,因此 ASP.NET 未处理的请求将 return 清空 404 响应,而不是允许 IIS 本机模块 运行 .要选择 运行 启用 IIS 本机模块,请将以下调用添加到 Startup.Configure 的末尾。
public void Configure(IApplicationBuilder app)
{
// ...Omitted
// Enable the IIS native module to run after the ASP.NET middleware components.
// This call should be placed at the end of your Startup.Configure method so that
// it doesn't interfere with other middleware functionality.
app.RunIISPipeline();
}
然后在您的 Web.config 中使用以下设置打开 GZIP 压缩(请注意,我添加了一些额外的行来压缩诸如 .json 之类的文件,否则这些文件将被 IIS 未压缩):
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<!-- httpCompression - GZip compress static file content. Overrides the server default which only compresses static
files over 2700 bytes. See http://zoompf.com/blog/2012/02/lose-the-wait-http-compression and
http://www.iis.net/configreference/system.webserver/httpcompression -->
<!-- minFileSizeForComp - The minimum file size to compress. -->
<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files" minFileSizeForComp="1024">
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />
<dynamicTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/x-javascript" enabled="true" />
<!-- Compress XML files -->
<add mimeType="application/xml" enabled="true" />
<!-- Compress JavaScript files -->
<add mimeType="application/javascript" enabled="true" />
<!-- Compress JSON files -->
<add mimeType="application/json" enabled="true" />
<!-- Compress SVG files -->
<add mimeType="image/svg+xml" enabled="true" />
<!-- Compress RSS feeds -->
<add mimeType="application/rss+xml" enabled="true" />
<!-- Compress Atom feeds -->
<add mimeType="application/atom+xml" enabled="true" />
<add mimeType="*/*" enabled="false" />
</dynamicTypes>
<staticTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/x-javascript" enabled="true" />
<add mimeType="application/atom+xml" enabled="true" />
<add mimeType="application/xaml+xml" enabled="true" />
<!-- Compress ICO icon files (Note that most .ico files are uncompressed but there are some that can contain
PNG compressed images. If you are doing this, remove this line). -->
<add mimeType="image/x-icon" enabled="true" />
<!-- Compress XML files -->
<add mimeType="application/xml" enabled="true" />
<add mimeType="application/xml; charset=UTF-8" enabled="true" />
<!-- Compress JavaScript files -->
<add mimeType="application/javascript" enabled="true" />
<!-- Compress JSON files -->
<add mimeType="application/json" enabled="true" />
<!-- Compress SVG files -->
<add mimeType="image/svg+xml" enabled="true" />
<!-- Compress EOT font files -->
<add mimeType="application/vnd.ms-fontobject" enabled="true" />
<!-- Compress TTF font files - application/font-ttf will probably be the new correct MIME type. IIS still uses application/x-font-ttf. -->
<!--<add mimeType="application/font-ttf" enabled="true" />-->
<add mimeType="application/x-font-ttf" enabled="true" />
<!-- Compress OTF font files - application/font-opentype will probably be the new correct MIME type. IIS still uses font/otf. -->
<!--<add mimeType="application/font-opentype" enabled="true" />-->
<add mimeType="font/otf" enabled="true" />
<!-- Compress RSS feeds -->
<add mimeType="application/rss+xml" enabled="true" />
<add mimeType="application/rss+xml; charset=UTF-8" enabled="true" />
<add mimeType="*/*" enabled="false" />
</staticTypes>
</httpCompression>
<!-- Enable gzip and deflate HTTP compression. See http://www.iis.net/configreference/system.webserver/urlcompression
doDynamicCompression - enables or disables dynamic content compression at the site, application, or folder level.
doStaticCompression - enables or disables static content compression at the site, application, or folder level.
dynamicCompressionBeforeCache - specifies whether IIS will dynamically compress content that has not been cached.
When the dynamicCompressionBeforeCache attribute is true, IIS dynamically compresses
the response the first time a request is made and queues the content for compression.
Subsequent requests are served dynamically until the compressed response has been
added to the cache directory. Once the compressed response is added to the cache
directory, the cached response is sent to clients for subsequent requests. When
dynamicCompressionBeforeCache is false, IIS returns the uncompressed response until
the compressed response has been added to the cache directory.
Note: This is set to false in Debug mode to enable Browser Link to work when debugging.
The value is set to true in Release mode (See web.Release.config).-->
<urlCompression doDynamicCompression="true" doStaticCompression="true" dynamicCompressionBeforeCache="false" />
</system.webServer>
</configuration>
[编辑 2016-11-13]
还有另一种方法来提供替代步骤 2 和 3 的 gzip 文件。它基本上是完全相同的想法,但是有一个 nuget package that does it all for you readily available. It basically checks if the is .gz
or .br
file that matches the requested one. If it exists it returns it with the appropriate headers. It does verify that the request has a header for the corresponding algorithm. Github code if you want to compile it yourself is here。
在官方 repository 中也有支持的问题,所以我真的希望微软有标准插件来做到这一点,因为现在使用它是相当普遍和合乎逻辑的。
我想我找到了提供压缩内容的最优化方式。主要思想是 pre-compress 文件,因为默认的 ASP.NET 5 方法是使用 gulp 构建 js,所以这样做很容易:
1. 添加一个 gulp 步骤来 gzip 捆绑的库:
gulp.task("buildApplication:js", function () {
return gulp.src(...)
...
.pipe(gzip())
...
});
这将在您的包文件夹中生成类似 libraries.js.gz 的内容
2. 在 cshtml 文件中引用 libraries.js.gz 而不是 libraries.js
3.修改静态文件处理程序以修复返回的headers
我们需要添加 Content-Encoding
并将 Content-Type
从默认的 application/x-gzip
更改为 application/javascript
因为并非所有浏览器都足够智能,可以从 [=18 正确读取 js =]
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = context =>
{
if (headers.ContentType.MediaType == "application/x-gzip")
{
if (context.File.Name.EndsWith("js.gz"))
{
headers.ContentType = new MediaTypeHeaderValue("application/javascript");
}
else if (context.File.Name.EndsWith("css.gz"))
{
headers.ContentType = new MediaTypeHeaderValue("text/css");
}
context.Context.Response.Headers.Add("Content-Encoding", "gzip");
}
}
});
现在所有的 CPU 周期都没有浪费在 gzip 相同的内容上,这是提供文件的最佳性能。为了进一步改进它,所有的 js 都必须在 gzip 之前打包和缩小。另一个升级是在同一个OnPrepareResponse中设置CacheControl max age缓存一年,并在cshtml中添加asp-append-version="true"
。
P.S。如果您将托管在 IIS 之后,您可能需要关闭 js 的静态压缩并且 css 不要双重压缩,我不确定在这种情况下它会如何表现。
这是来自 Ilyas 答案的方法 3 的固定版本,适用于 ASP.NET Core 1 RTM,它提供预压缩的 javascript 文件:
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = context =>
{
IHeaderDictionary headers = context.Context.Response.Headers;
string contentType = headers["Content-Type"];
if (contentType == "application/x-gzip")
{
if (context.File.Name.EndsWith("js.gz"))
{
contentType = "application/javascript";
}
else if (context.File.Name.EndsWith("css.gz"))
{
contentType = "text/css";
}
headers.Add("Content-Encoding", "gzip");
headers["Content-Type"] = contentType;
}
}
});
在使用自托管环境发布 ASP.NET 核心网站时,是否有办法提供 gzip 静态内容?
如果客户端支持,您可以实施压缩响应内容的操作过滤器。
这是 MVC5 中的示例。您应该能够修改它以使用 MVC 6:
http://www.erwinvandervalk.net/2015/02/enabling-gzip-compression-in-webapi-and.html
@Ilya 的回答非常好,但如果您不使用 Gulp,这里有两种选择。
ASP.NET 核心响应压缩中间件
在ASP.NET核心BasicMiddlware repository, you can find (at time of writing) a pull request (PR) for Response Compression Middleware。您可以下载代码并将其添加到您 IApplicationBuilder
中(在撰写本文时):
public void Configure(IApplicationBuilder app)
{
app.UseResponseCompression(
new ResponseCompressionOptions()
{
MimeTypes = new string[] { "text/plain" }
});
// ...Omitted
}
IIS(Internet 信息服务器)
IIS(Internet 信息服务器)有一个本机静态文件模块,它独立于您在本文中了解的 ASP.NET 静态文件中间件组件。由于 ASP.NET 模块在 IIS 本机模块之前 运行,因此它们优先于 IIS 本机模块。从 ASP.NET Beta 7 开始,IIS 主机已更改,因此 ASP.NET 未处理的请求将 return 清空 404 响应,而不是允许 IIS 本机模块 运行 .要选择 运行 启用 IIS 本机模块,请将以下调用添加到 Startup.Configure 的末尾。
public void Configure(IApplicationBuilder app)
{
// ...Omitted
// Enable the IIS native module to run after the ASP.NET middleware components.
// This call should be placed at the end of your Startup.Configure method so that
// it doesn't interfere with other middleware functionality.
app.RunIISPipeline();
}
然后在您的 Web.config 中使用以下设置打开 GZIP 压缩(请注意,我添加了一些额外的行来压缩诸如 .json 之类的文件,否则这些文件将被 IIS 未压缩):
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<!-- httpCompression - GZip compress static file content. Overrides the server default which only compresses static
files over 2700 bytes. See http://zoompf.com/blog/2012/02/lose-the-wait-http-compression and
http://www.iis.net/configreference/system.webserver/httpcompression -->
<!-- minFileSizeForComp - The minimum file size to compress. -->
<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files" minFileSizeForComp="1024">
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />
<dynamicTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/x-javascript" enabled="true" />
<!-- Compress XML files -->
<add mimeType="application/xml" enabled="true" />
<!-- Compress JavaScript files -->
<add mimeType="application/javascript" enabled="true" />
<!-- Compress JSON files -->
<add mimeType="application/json" enabled="true" />
<!-- Compress SVG files -->
<add mimeType="image/svg+xml" enabled="true" />
<!-- Compress RSS feeds -->
<add mimeType="application/rss+xml" enabled="true" />
<!-- Compress Atom feeds -->
<add mimeType="application/atom+xml" enabled="true" />
<add mimeType="*/*" enabled="false" />
</dynamicTypes>
<staticTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/x-javascript" enabled="true" />
<add mimeType="application/atom+xml" enabled="true" />
<add mimeType="application/xaml+xml" enabled="true" />
<!-- Compress ICO icon files (Note that most .ico files are uncompressed but there are some that can contain
PNG compressed images. If you are doing this, remove this line). -->
<add mimeType="image/x-icon" enabled="true" />
<!-- Compress XML files -->
<add mimeType="application/xml" enabled="true" />
<add mimeType="application/xml; charset=UTF-8" enabled="true" />
<!-- Compress JavaScript files -->
<add mimeType="application/javascript" enabled="true" />
<!-- Compress JSON files -->
<add mimeType="application/json" enabled="true" />
<!-- Compress SVG files -->
<add mimeType="image/svg+xml" enabled="true" />
<!-- Compress EOT font files -->
<add mimeType="application/vnd.ms-fontobject" enabled="true" />
<!-- Compress TTF font files - application/font-ttf will probably be the new correct MIME type. IIS still uses application/x-font-ttf. -->
<!--<add mimeType="application/font-ttf" enabled="true" />-->
<add mimeType="application/x-font-ttf" enabled="true" />
<!-- Compress OTF font files - application/font-opentype will probably be the new correct MIME type. IIS still uses font/otf. -->
<!--<add mimeType="application/font-opentype" enabled="true" />-->
<add mimeType="font/otf" enabled="true" />
<!-- Compress RSS feeds -->
<add mimeType="application/rss+xml" enabled="true" />
<add mimeType="application/rss+xml; charset=UTF-8" enabled="true" />
<add mimeType="*/*" enabled="false" />
</staticTypes>
</httpCompression>
<!-- Enable gzip and deflate HTTP compression. See http://www.iis.net/configreference/system.webserver/urlcompression
doDynamicCompression - enables or disables dynamic content compression at the site, application, or folder level.
doStaticCompression - enables or disables static content compression at the site, application, or folder level.
dynamicCompressionBeforeCache - specifies whether IIS will dynamically compress content that has not been cached.
When the dynamicCompressionBeforeCache attribute is true, IIS dynamically compresses
the response the first time a request is made and queues the content for compression.
Subsequent requests are served dynamically until the compressed response has been
added to the cache directory. Once the compressed response is added to the cache
directory, the cached response is sent to clients for subsequent requests. When
dynamicCompressionBeforeCache is false, IIS returns the uncompressed response until
the compressed response has been added to the cache directory.
Note: This is set to false in Debug mode to enable Browser Link to work when debugging.
The value is set to true in Release mode (See web.Release.config).-->
<urlCompression doDynamicCompression="true" doStaticCompression="true" dynamicCompressionBeforeCache="false" />
</system.webServer>
</configuration>
[编辑 2016-11-13]
还有另一种方法来提供替代步骤 2 和 3 的 gzip 文件。它基本上是完全相同的想法,但是有一个 nuget package that does it all for you readily available. It basically checks if the is .gz
or .br
file that matches the requested one. If it exists it returns it with the appropriate headers. It does verify that the request has a header for the corresponding algorithm. Github code if you want to compile it yourself is here。
在官方 repository 中也有支持的问题,所以我真的希望微软有标准插件来做到这一点,因为现在使用它是相当普遍和合乎逻辑的。
我想我找到了提供压缩内容的最优化方式。主要思想是 pre-compress 文件,因为默认的 ASP.NET 5 方法是使用 gulp 构建 js,所以这样做很容易:
1. 添加一个 gulp 步骤来 gzip 捆绑的库:
gulp.task("buildApplication:js", function () {
return gulp.src(...)
...
.pipe(gzip())
...
});
这将在您的包文件夹中生成类似 libraries.js.gz 的内容
2. 在 cshtml 文件中引用 libraries.js.gz 而不是 libraries.js
3.修改静态文件处理程序以修复返回的headers
我们需要添加 Content-Encoding
并将 Content-Type
从默认的 application/x-gzip
更改为 application/javascript
因为并非所有浏览器都足够智能,可以从 [=18 正确读取 js =]
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = context =>
{
if (headers.ContentType.MediaType == "application/x-gzip")
{
if (context.File.Name.EndsWith("js.gz"))
{
headers.ContentType = new MediaTypeHeaderValue("application/javascript");
}
else if (context.File.Name.EndsWith("css.gz"))
{
headers.ContentType = new MediaTypeHeaderValue("text/css");
}
context.Context.Response.Headers.Add("Content-Encoding", "gzip");
}
}
});
现在所有的 CPU 周期都没有浪费在 gzip 相同的内容上,这是提供文件的最佳性能。为了进一步改进它,所有的 js 都必须在 gzip 之前打包和缩小。另一个升级是在同一个OnPrepareResponse中设置CacheControl max age缓存一年,并在cshtml中添加asp-append-version="true"
。
P.S。如果您将托管在 IIS 之后,您可能需要关闭 js 的静态压缩并且 css 不要双重压缩,我不确定在这种情况下它会如何表现。
这是来自 Ilyas 答案的方法 3 的固定版本,适用于 ASP.NET Core 1 RTM,它提供预压缩的 javascript 文件:
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = context =>
{
IHeaderDictionary headers = context.Context.Response.Headers;
string contentType = headers["Content-Type"];
if (contentType == "application/x-gzip")
{
if (context.File.Name.EndsWith("js.gz"))
{
contentType = "application/javascript";
}
else if (context.File.Name.EndsWith("css.gz"))
{
contentType = "text/css";
}
headers.Add("Content-Encoding", "gzip");
headers["Content-Type"] = contentType;
}
}
});