Angular's PRE-Gzipped files are not served via

2019-02-16 13:00发布

问题:

I have prepared all the settings (at my home , Windows 10) for creating and serving js as gz files , but still - I get only the regular js files (with the original size).

Configuration

Angular's webpack file :

new CompressionPlugin({
      asset: "[path].gz[query]",
     algorithm: "gzip",
     test: /\.js$|\.css$|\.html$/,
     threshold: 10240,
     minRatio: 0.8
 })

Output files for that configuration:

Index.html file:

...
<body>
  <app-root>Loading...</app-root> 
  <script src="/dist/polyfills.bundle.js"></script>
  <script src="/dist/main.bundle.js"></script>
</body>
...

Diagnostics

When I navigate to http://kkk.com/index.html , I get the full size files :

Also - looking at the request headers , I do send the Accept-Encoding:gzip, deflate header :

Question

Why doesn't the GZ files served ?


Additional info :

  • There is no 304 responses , I set .
  • At my work , windows 7 , same files - I DO(!) see the gziped files :

  • Disabled Antivirus
  • Permissions : Everyone : full control on the file's folder.
  • Comparison between request headers :

  • Since I don't want real time zipping , but PRE-ZIPPING ( files which already gzipped by angular) - I tried enabling AND disabling compression(just to see if it affects something - but it doesn't - I still get the big files) :

回答1:

OK. After searching a lot - I've managed to do it with URLREWRITE and with some IIS configuration.

First - I've disabled this :

Because I don't need CPU here. I already have the pre zipped files.

OK - the key here is those two sections:

1) Set contentType to application/javascript
2) Set contentEncoding to gzip.

So I've written these 2 urlrewrite rules :

The first section is to rewrite all js files to js.gz and the second rule which is an outboundrule is for adding the content encoding header with gzip value.

This is the config file :

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="https" enabled="true" stopProcessing="false">
                    <match url="(.*).js" />
                    <conditions></conditions>
                    <action type="Rewrite" url="{R:1}.js.gz" appendQueryString="true" logRewrittenUrl="true" />
                </rule>
            </rules>
            <outboundRules>
                <rule name="Rewrite content-encoding header" preCondition="IsGZ" stopProcessing="false">
                    <match serverVariable="RESPONSE_CONTENT_ENCODING" pattern=".*" />
                    <action type="Rewrite" value="gzip" />
                </rule>
                <preConditions>
                    <preCondition name="IsGZ">
                        <add input="{URL}" pattern="\.gz$" />
                    </preCondition>


        </preConditions>
        </outboundRules>
    </rewrite>
    <urlCompression doStaticCompression="false" />
</system.webServer>

Just paste it in the web.config file (even if you don't use Asp.net).

Also - you have to add this to the mime types :

Now , as you can see the response I do get the right size :

Going deeper :

Which is the one I have as preziiped :

That's all.



回答2:

IIS does not support pre-compressed files. you could workaoround this fairly simply by using a solution from here: https://github.com/aspnet/StaticFiles/issues/7

the problem is that IIS is serving content as is or it compresses then and the adding the encoding header.

If you add the static compression to IIS it will gzip your files the second time. If you will not add static compression it will send them as is but will not add the encoding header.

so what you want is to hijack the request and manipulate the response grammatically.

here is an OWIN base implementation example. you could as easily use an HTTP handler for older version..

class Startup
{
    private StaticFileOptions StaticFileOptions
    {
        get
        {
            return new StaticFileOptions
            {
                OnPrepareResponse = OnPrepareResponse
            };                
        }
    }

    private void OnPrepareResponse(StaticFileResponseContext context)
    {
        var file = context.File;
        var request = context.Context.Request;
        var response = context.Context.Response;

        if (file.Name.EndsWith(".gz"))
        {
            response.Headers[HeaderNames.ContentEncoding] = "gzip";
            return;
        }

        if (file.Name.IndexOf(".min.", StringComparison.OrdinalIgnoreCase) != -1)
        {
            var requestPath = request.Path.Value;
            var filePath = file.PhysicalPath;

            if (IsDevelopment)
            {
                if (File.Exists(filePath.Replace(".min.", ".")))
                {
                    response.StatusCode = (int)HttpStatusCode.TemporaryRedirect;
                    response.Headers[HeaderNames.Location] = requestPath.Replace(".min.", ".");
                }
            }
            else
            {
                var acceptEncoding = (string)request.Headers[HeaderNames.AcceptEncoding];
                if (acceptEncoding.IndexOf("gzip", StringComparison.OrdinalIgnoreCase) != -1)
                {
                    if (File.Exists(filePath + ".gz"))
                    {
                        response.StatusCode = (int)HttpStatusCode.MovedPermanently;
                        response.Headers[HeaderNames.Location] = requestPath + ".gz";
                    }
                }
            }
        }
    }

   public void Configure(IApplicationBuilder application)
   {
        application
            .UseDefaultFiles()
            .UseStaticFiles(StaticFileOptions)
    }
}