Skip to content

Commit aa299f8

Browse files
committed
Update Readme content.
1 parent 3bf1044 commit aa299f8

File tree

1 file changed

+150
-72
lines changed

1 file changed

+150
-72
lines changed

Readme.md

Lines changed: 150 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Oh, and one more thing!
2525

2626
AspNetStatic now works with Blazor websites, thanks to the new Blazor SSR capability in ASP.NET Core 8.
2727

28-
> Blazor pages must not rely on any client-side (JS, WASM) behavior for rendering, or behaviors like showing a placeholder (e.g. a spinner) before rendering the actual content. The rule-of-thumb (for any technology you use with AspNetStatic) is that as long as the content has completed rendering by the time AspNetStatic receives it (via its HttpClient request), it will work fine.
28+
> :bulb: Blazor pages must not rely on any client-side (JS, WASM) behavior for rendering, or behaviors like showing a placeholder (e.g. a spinner) before rendering the actual content. The rule-of-thumb (for any technology you use with AspNetStatic) is that as long as the content has completed rendering by the time AspNetStatic receives it (via its HttpClient request), it will work fine.
2929
3030
### No Frameworks. No Engines. No Opinions!
3131

@@ -69,7 +69,7 @@ It's a piece of cake.
6969
new PageResource("/privacy"),
7070
new PageResource("/blog/articles/posts/1") { OutFile = "blog/post-1.html" },
7171
new PageResource("/blog/articles/posts/2") { OutFile = "blog/post-2-dark.html", Query = "?theme=dark" },
72-
new CssResource("/bootstrap/bootstrap.min.css") { OptimizerType = OptimizerType.None },
72+
new CssResource("/bootstrap/bootstrap.min.css") { OptimizationType = OptimizationType.None },
7373
new CssResource("/site.css"),
7474
new JsResource("/site.js"),
7575
new BinResource("/favicon.png")
@@ -104,16 +104,16 @@ Keep the following in mind when specifying routes in the `IStaticResourcesInfoPr
104104
- You can directly specify the pathname of the file to be generated for routes you add to the `PageResources` collection (see `OutFile` property). The only requirement is that the specified path be relative to the destination root folder. If you do not specify a value for `OutFile`, the pathname for the generated file will be determined as demonstrated below.
105105
- You can specify route parameters for routes you add to the `PageResources` collection. The route parameters are treated as part of the route, and are used in constructing the output file pathname.
106106
- You can specify a query string for routes you add to the `PageResources` collection (see `Query` property). You can specify the same `Route` with different `Query` values, but you will need to specify a unique `OutFile` value for each instance of that route.
107-
- You can skip content optimization<sup>1</sup> or choose a specific optimizer type for routes you add to the `PageResources` collection (see `OptimizerType` property). The default optimizer type setting, `OptimizerType.Auto`, automatically selects the appropriate optimizer.
107+
- You can skip content optimization<sup>1</sup> or choose a specific optimizer type for routes you add to the `PageResources` collection (see `OptimizationType` property). The default optimizer type setting, `OptimizationType.Auto`, automatically selects the appropriate optimizer.
108108
- You can set the encoding for content written to output files for routes you add to the `PageResources` collection (see `OutputEncoding` property). Default is UTF8.
109109

110-
> NOTE: All of the above also applies to routes for CSS, JavaScript, and binary (e.g. image) files specified in the `OtherResources` collection property.
110+
> :bulb: All of the above also applies to routes for CSS, JavaScript, and binary (e.g. image) files specified in the `OtherResources` collection property.
111111
112112
> 1: Content optimization options apply only when content optimization is enabled. Please see the __Content Optimization__ section below for details.
113113
114114
### Routes vs. Generated Static Files (page resources)
115115

116-
> Assumes the following:
116+
> #### Assumes the following:
117117
> - Resource Type: PageResource
118118
> - Destination root: "__C:\MySite__"
119119
> - OutFile: __null, empty, or whitespace__
@@ -134,7 +134,7 @@ Url<br/>(route + query) | Always Default<br/>false | Always Default<br/>true
134134

135135
### Routes vs. Generated Static Files (non-page resources)
136136

137-
> Assumes the following:
137+
> #### Assumes the following:
138138
> - Resource Type: __CssResource__, __JsResource__, or __BinResource__
139139
> - Destination root: "__C:\MySite__"
140140
> - OutFile: __null, empty, or whitespace__
@@ -161,7 +161,7 @@ Url<br/>(route + query) | Generated File
161161

162162
### Fallback Middleware: Routes vs. Served Content
163163

164-
> Assumes the following:
164+
> #### Assumes the following:
165165
> - OutFile: __null, empty, or whitespace__
166166
> - Applicable only to __PageResource__ items.
167167
@@ -180,7 +180,7 @@ Url<br/>(route + query) | Is Static Route: false<br/><br/> | Is Static Route: tr
180180
/blog/articles/post1 | /blog/articles/post1.cshtml | /blog/articles/post1.html | /blog/articles/post1/index..html
181181

182182

183-
> #### The same rules apply when links in static files are updated to refer to other generated static pages.
183+
> :bulb: The same rules apply when links in static files are updated to refer to other generated static pages.
184184
185185

186186
__IMPORTANT NOTE__: In ASP.NET Core, UrlHelper (and the asp-* tag helpers) generate link URIs based on the routing configuration of your app, so if you're using them, be sure to specify an appropriate value for `alwaysDefaultFile`, as shown below. (NOTE: Specify the same value if/when configuring the fallback middleware).
@@ -232,7 +232,7 @@ app.GenerateStaticContent(
232232

233233
## Scenarios
234234

235-
> #### In all scenarios, ensure that routes for static content are unincumbered by authentication or authorization requirements.
235+
> :bulb: In all scenarios, ensure that routes for static content are unincumbered by authentication or authorization requirements.
236236
237237
### Static Site Generation (Standalone SSG)
238238

@@ -296,7 +296,7 @@ Now you can use the SSG profile to launch your app in SSG mode (to generate stat
296296

297297
In this scenario, you want some of the pages in your ASP.NET Core app to be static, but still want other routes to be served as dynamic content per request (e.g. pages/views, JSON API's, etc.). When the app runs, static (.html) files will be generated for routes you specify. The website will then serve these static files for the specified routes, and dynamic content (as usual) for others.
298298

299-
> While static files are being generated, requests to routes for which a static file has not yet been generated will be served as dynamicly generated content (using the source .cshtml page). Once the static file for that route has been generated, it will be used to satisfy subsequent requests.
299+
> :bulb: While static files are being generated, requests to routes for which a static file has not yet been generated will be served as dynamicly generated content (using the source .cshtml page). Once the static file for that route has been generated, it will be used to satisfy subsequent requests.
300300
301301
The configuration options are generally the same as for a standalone static site, except the following differences:
302302
- The destination root folder must be `app.Environment.WebRoot` (i.e. wwwroot).
@@ -326,7 +326,7 @@ app.GenerateStaticContent(
326326
app.Run();
327327
```
328328

329-
> #### NOTE: The fallback middleware only re-routes requests for routes that match entries in the `PageResources` collection, and only if a generated static file exists for that route.
329+
> :bulb: The fallback middleware only re-routes requests for routes that match entries in the `PageResources` collection, and only if a generated static file exists for that route.
330330
331331

332332
#### Periodic Regeneration
@@ -345,79 +345,157 @@ app.GenerateStaticContent(
345345

346346
## Content Optimization
347347

348-
AspNetStatic automatically minifies HTML content (and any embedded CSS or Javascript) in generated static files; configuration is not required.
349-
To disable this feature, however, you can specify `true` for the `dontOptimizeContent` parameter.
348+
Before proceeding, let's clarify what an "_optimizer_" is in AspNetStatic. An optimizer is simply a component that performs some sort of processing on the content retrieved for a static resource (_i.e. page, css, js, image, etc._) An optimizer is called by AspNetStatic after the content of a resource is retrieved, but just before that content is written to the destination file.
349+
350+
351+
### Enabling Optimization
352+
353+
The "optimizer" feature in AspNetStatic is enabled by default and requires no configuration to use.
354+
To disable the feature, pass `true` as the argument for the `dontOptimizeContent` parameter in the `GenerateStaticContent` call.
350355
```c#
351356
app.GenerateStaticContent(
352357
...
353358
dontOptimizeContent: true);
354359
```
360+
This will prevent the `IOptimizerSelector` and any optimizers from being called.
355361

356-
> Content optimization does not apply to binary resource types (`BinResource` entries), but is enabled by default (`OptimizerType.Auto`) for all other resource types (`PageResource`, `CssResource`, and `JsResource` entries).
357362

358-
### Configuration
363+
### Optimizer Selector
359364

360-
To override the default minification settings used by AspNetStatic, register the appropriate objects in the DI container, as shown below.
365+
The optimizer to be executed by AspNetStatic for a given resource (_page, css, etc._) is determined by the registered `IOptimizerSelector` component, which by default is `DefaultOptimizerSelector`.
361366

362-
> AspNetStatic uses the excellent WebMarkupMin package to implement the minification feature. For details about the configuration settings, please consult the WebMarkupMin [documentation](https://github.com/Taritsyn/WebMarkupMin/wiki/).
367+
An `IOptimizerSelector` implementation can select an optimizer based on the attributes of the resource (e.g. the resource type, its stated `OptimizationType`, the source or destination file extension or path). `DefaultOptimizerSelector`, for instance, uses the resource type and `OptimizationType` information to select an optimizer.
363368

364-
Content optimization can be customized in one of two ways:
365-
1. Create and register an object that implements `IOptimizerSelector`. In addition to specifying custom optimizer configurations, this option allows you to implement your own custom logic for selecting the optimizer to use for a resource.
366-
```c#
367-
public class MyOptimizerSelector : IOptimizerSelector { ... }
369+
To use your own custom selector, implement the `IOptimizerSelector` interface and register it in the DI container. You can derive from `DefaultOptimizerSelector` and override it's methods, to expedite this task.
370+
371+
```C#
372+
public class MyCustomOptimizerSelector : IOptimizerSelector
373+
{
374+
...
375+
}
376+
...
377+
builder.Services.AddSingleton<IOptimizerSelector, MyCustomOptimizerSelector>();
378+
builder.Services.AddDefaultOptimizers(); // do this if MyCustomOptimizerSelector uses them
379+
```
380+
> :bulb: If your custom `IOptimizerSelector` implementation injects one or more of the default optimizers provided by AspNetStatic, you must register them by calling `AddDefaultOptimizers()`.
381+
382+
383+
### Optimizers
384+
385+
AspNetStatic supports the following optimizer types:
386+
- `IMarkupOptimizer`: Called when processing PageResource objects
387+
- `ICssOptimizer`: Called when processing CssResource objects
388+
- `IJsOptimizer`: Called when processing JsResource objects
389+
- `IBinOptimizer`: Called when processing BinResource objects
390+
391+
AspNetStatic provides the following "default" implementations for these interfaces: `DefaultMarkupOptimizer`, `DefaultCssOptimizer`, and `DefaultJsOptimizer`. There is no default `IBinOptimizer`.
392+
393+
To use a custom optimizer, implement (_and register in DI_) the relevant interface. You can derive and extend the "default" implementation, if you wish.
394+
For instance, if you want to perform some pre and post processing operations on CSS resources (_in addition to the built-in minification_), derive and extend the DefaultCssOptimizer, like so:
395+
396+
```C#
397+
// OPTION 1: Implement from scratch
398+
399+
public MyCustomCssOptimizer : ICssOptimizer
400+
{
401+
public CssOptimizerResult Execute(string content, ...)
402+
{
403+
// your custom processing here...
404+
}
405+
}
406+
407+
// OPTION 2: inherit from DefaultCssOptimizer
408+
409+
public MyCustomCssOptimizer : DefaultCssOptimizer
410+
{
411+
public override CssOptimizerResult Execute(string content, ...)
412+
{
413+
content = DoPreProcessing(content);
414+
var result = base.Execute(content, ...); // do usual minification
415+
result.OptimizedContent = DoPostProcessing(result.OptimizedContent);
416+
return result;
417+
}
418+
private string DoPreProcessing(string css) { ... }
419+
private string DoPostProcessing(string css) { ... }
420+
}
421+
422+
// -- OPTION 3: create decorator over DefaultCssOptimizer
423+
424+
public MyCustomCssOptimizer(
425+
DefaultCssOptimizer defaultCssOptimizer) :
426+
ICssOptimizer
427+
{
428+
public CssOptimizerResult Execute(string content, ...)
429+
{
430+
content = DoPreProcessing(content);
431+
var result = defaultCssOptimizer.Execute(content, ...); // do usual minification
432+
result.OptimizedContent = DoPostProcessing(result.OptimizedContent);
433+
return result;
434+
}
435+
private string DoPreProcessing(string css) { ... }
436+
private string DoPostProcessing(string css) { ... }
437+
}
438+
439+
...
440+
441+
// Register your custom implementation...
442+
builder.Services.AddSingleton<ICssOptimizer, MyCustomCssOptimizer>();
443+
444+
// Call following method if you want DefaultCssOptimizer to use
445+
// the AspNetStatic defaults for these services, otherwise it will
446+
// use the WebMarkupMin internal defaults.
447+
builder.Services.AddDefaultMinifiers();
448+
```
449+
450+
451+
### Configuring Default Optimizers
452+
453+
The default optimizers provided by AspNetStatic (`DefaultMarkupOptimizer`, `DefaultCssOptimizer`, and `DefaultJsOptimizer`) use the `WebMarkupMin` package to minify HTML, CSS and JS content.
454+
To override the default minification settings used by AspNetStatic, register the appropriate objects as described below.
455+
456+
> :flashlight: For details about WebMarkupMin configuration settings, please consult the [WebMarkupMin documentation](https://github.com/Taritsyn/WebMarkupMin/wiki/).
457+
458+
AspNetStatic uses the default `WebMarkupMin` configuration settings (_determined internally by WebMarkupMin_) for minifying HTML, XHTML, and XML content. To override this behavior, register one or more of the following configuration objects:
459+
460+
```c#
461+
using WebMarkupMin.Core;
462+
463+
// HTML minifier settings
464+
builder.Services.AddSingleton(
465+
sp => new HtmlMinificationSettings()
466+
{
368467
...
369-
builder.Services.AddSingleton(sp => new MyOptimizerSelector( ... ));
370-
```
468+
});
469+
470+
// XHTML minifier settings
471+
builder.Services.AddSingleton(
472+
sp => new XhtmlMinificationSettings()
473+
{
474+
...
475+
});
476+
477+
// XML minifier settings
478+
builder.Services.AddSingleton(
479+
sp => new XmlMinificationSettings()
480+
{
481+
...
482+
});
483+
```
484+
485+
486+
AspNetStatic uses `KristensenCssMinifier` for `ICssMinifier`, and `CrockfordJsMinifier` for `IJsMinifier` by default. To override this behavior, register alternative implementations:
371487

372-
1. Create and register individual settings objects which internally feed into a default `IOptimizerSelector` implementation.
373-
- __HTML__: To configure the HTML minifier, register as a singleton a configured instance of `HtmlMinificationSettings`:
374-
```c#
375-
using WebMarkupMin.Core;
376-
builder.Services.AddSingleton(
377-
sp => new HtmlMinificationSettings()
378-
{
379-
...
380-
});
381-
```
382-
383-
- __XHTML__: To configure the XHTML minifier, register as a singleton a configured instance of `XhtmlMinificationSettings`:
384-
```c#
385-
using WebMarkupMin.Core;
386-
builder.Services.AddSingleton(
387-
sp => new XhtmlMinificationSettings()
388-
{
389-
...
390-
});
391-
```
392-
393-
- __XML__: To configure the XML minifier, register as a singleton a configured instance of `XmlMinificationSettings`:
394-
```c#
395-
using WebMarkupMin.Core;
396-
builder.Services.AddSingleton(
397-
sp => new XmlMinificationSettings()
398-
{
399-
...
400-
});
401-
```
402-
403-
- __CSS__: To configure the CSS minifier, register as a singleton an object that implements the `ICssMinifier` interface:
404-
```c#
405-
using WebMarkupMin.Core;
406-
builder.Services.AddSingleton<ICssMinifier>(
407-
sp => new YuiCssMinifier(...));
408-
```
409-
410-
- __Javascript__: To configure the Javascript minifier, register as a singleton an object that implements the `IJsMinifier` interface:
411-
```c#
412-
using WebMarkupMin.Core;
413-
builder.Services.AddSingleton<IJsMinifier>(
414-
sp => new YuiJsMinifier(...));
415-
```
416-
417-
- __Binary Content__ (__BinResource__): To configure a binary resource optimizer, register as a singleton an object that implements the `IBinOptimizer` interface:
418-
```c#
419-
builder.Services.AddSingleton<IBinOptimizer, MyBinOptimizer>();
420-
```
488+
```c#
489+
using WebMarkupMin.Core;
490+
491+
// ICssMinifier
492+
builder.Services.AddSingleton<ICssMinifier>(
493+
sp => new YuiCssMinifier(...));
494+
495+
// IJsMinifier
496+
builder.Services.AddSingleton<IJsMinifier>(
497+
sp => new YuiJsMinifier(...));
498+
```
421499

422500

423501
<br/>

0 commit comments

Comments
 (0)