Skip to content

Versionable Wiki #52

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/nuget-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ jobs:
ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
BRANCH: gh-pages

- name: Deploy wiki
uses: jamesives/[email protected]
with:
FOLDER: docs
ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
REPOSITORY_NAME: isc30/blazor-lazy-loading.wiki
BRANCH: master

- name: Upload artifacts
uses: actions/upload-artifact@v1
with:
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
<p align="center">
<a href="https://github.com/isc30/blazor-lazy-loading">
<img src="doc/img/logo.png?raw=true" />
<img src="docs/img/logo.png?raw=true" />
</a>
</p>
<p align="center">
<a href="https://github.com/isc30/blazor-lazy-loading"><img src="https://img.shields.io/github/workflow/status/isc30/blazor-lazy-loading/[trigger]%20new%20release/master?logo=github" /></a>
<a href="https://www.nuget.org/packages?q=BlazorLazyLoading&prerel=false"><img src="https://img.shields.io/nuget/v/BlazorLazyLoading.Components?color=brightgreen&label=stable&logo=nuget)](https://www.nuget.org/packages?q=BlazorLazyLoading&prerel=false" /></a>
<a href="https://www.nuget.org/packages?q=BlazorLazyLoading&prerel=false"><img src="https://img.shields.io/nuget/dt/BlazorLazyLoading.Components?color=brightgreen&label=downloads&logo=nuget)](https://www.nuget.org/packages?q=BlazorLazyLoading&prerel=false" /></a>
<a href="https://www.nuget.org/packages?q=BlazorLazyLoading&prerel=true"><img src="https://img.shields.io/nuget/vpre/BlazorLazyLoading.Components?color=yellow&label=dev&logo=nuget)](https://www.nuget.org/packages?q=BlazorLazyLoading&prerel=false" /></a>
<a href="https://www.nuget.org/packages?q=BlazorLazyLoading&prerel=false"><img src="https://img.shields.io/nuget/v/BlazorLazyLoading.Components?color=brightgreen&label=stable&logo=nuget" /></a>
<a href="https://www.nuget.org/packages?q=BlazorLazyLoading&prerel=false"><img src="https://img.shields.io/nuget/dt/BlazorLazyLoading.Components?color=brightgreen&label=downloads&logo=nuget" /></a>
<a href="https://www.nuget.org/packages?q=BlazorLazyLoading&prerel=true"><img src="https://img.shields.io/nuget/vpre/BlazorLazyLoading.Components?color=yellow&label=dev&logo=nuget" /></a>
</p>
<br/>

Automatic Lazy Loading support for Blazor WebAssembly and Blazor Server!<br/><br/>

[![Documentation / Wiki](doc/img/documentation.png?raw=true)](https://github.com/isc30/blazor-lazy-loading/wiki)
[![Documentation / Wiki](docs/img/documentation.png?raw=true)](https://github.com/isc30/blazor-lazy-loading/wiki)

[![Demo](doc/img/demo.png?raw=true)](https://isc30.github.io/blazor-lazy-loading/)
[![Demo](docs/img/demo.png?raw=true)](https://isc30.github.io/blazor-lazy-loading/)
115 changes: 115 additions & 0 deletions docs/[email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# &lt;Lazy /&gt;

Renders a Component (`IComponent`) from a Lazy Module based on it's **LazyName** or **TypeFullName** (*string*).

This Component needs to exist in a *known* Lazy Module, either [hinted directly](Configuring-Lazy-Loading-@-Server#modulehints) or using [ModulesHost strategy](Creating-a-Lazy-Loadable-Module#creating-an-aggregated-module).

# Render by using TypeFullName

The is no extra prerequisite to render an `IComponent` by using **TypeFullName**:

```razor
<Lazy Name="MyApplication.Hello" />
```

This snippet renders a `Hello` Component assuming the type is `MyApplication.Hello`. It will **automatically fetch** the manifests, consume them to **locate** the Component and **download** the minimum assemblies to make it work 😄

# Named Components

It is possible to **manually name** your Components and use that name later to resolve them.<br />
This is done by adding a simple **attribute** `BlazorLazyLoading.LazyNameAttribute` to your Component:

* Syntax: `.razor`
```razor
@attribute [LazyName("SayHello")]
<h1>Hello!</h3>
```

* Syntax: `.cs`
```cs
[LazyName("SayHello")]
public class Hello : IComponent { ... }
```

And then **render** it like the following:

```razor
<Lazy Name="SayHello" />
```

In order to *debug* if your component **name** is generated properly, you can check the contents of `_lazy.json`.
```json
{
"MyApplication": {
"Components": [
{
"TypeFullName": "MyApplication.Hello",
"Name": "SayHello"
}
]
}
}
```

# Custom 'Loading' view

It is possible to customize the `<Lazy>` Component with a **loading** `RenderFragment` that will get rendered while everything is being initialized.

It only requires setting a `RenderFragment` called `Loading`:

```razor
<Lazy Name="SayHello">
<Loading>
<p>Loading, please wait</p>
<div class="spinner" />
</Loading>
</Lazy>
```

# Custom 'Error' view

It is possible to customize the 'error' `RenderFragment` that gets renderd if the Component fails to initialize *(because some assembly failed to load, such element doesn't exist, etc)*.

It only requires setting a `RenderFragment` called `Error`:

```razor
<Lazy Name="SayHello">
<Error>
<p class="error">Something bad happened</p>
</Error>
</Lazy>
```

# Handling Errors

It is possible to specify if a Component is **Required** (if a loading error throws an exception) by setting the property `Required` *(bool)* on it.

```razor
<Lazy Required="false" Name="Unknown" /> @* this will simply not get rendered *@
<Lazy Required="true" Name="Unknown" /> @* this will throw an exception *@
@* both will render the 'error' view *@
```

# Hooking into Events

There are 2 Events you can hook to by just setting Callbacks in the Component:

* #### OnBeforeLoadAsync

This callback will be awaited **before** trying to resolve the Component from the manifests.
Useful for delaying a Component render to perform another operation before, and Debugging with `Task.Delay`.

* #### OnAfterLoad

This callback will be invoked **after** resolving and rendering the lazy Component.

```razor
<Lazy
Name="SayHello"
OnBeforeLoadAsync="l => Task.Delay(500)"
OnAfterLoad='l => Console.WriteLine($"Loaded LazyComponent: {l.Name}")' />
```

# SEO and Prerendering Support

Don't worry about SEO. If you use BlazorServer or Prerendering, the Component HTML will be **fully rendered** automatically by the server so there is no difference between rendering it directly and using `<Lazy>`.
70 changes: 70 additions & 0 deletions docs/[email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# &lt;LazyRouter /&gt;

Provides SPA navigation for Pages and Routes in Lazy Modules. It is a direct replacement of `<Router>`.

The pages need to exist in a *known* Lazy Module, either [hinted directly](Configuring-Lazy-Loading-@-Server#modulehints) or using [ModulesHost strategy](Creating-a-Lazy-Loadable-Module#creating-an-aggregated-module).

# Creating Lazy Pages and Routes

Pages and Routes don't require any configuration, just create them as you would normally (using `@page` attribute, etc).

If the Page is contained in a **Module**, the manifest *(_lazy.json)* will already generate all the information for routing automatically:

```json
{
"MyApplication": {
"Routes": [
{
"Route": "/counter",
"Name": "CounterPage"
}
]
}
}
```

# Using LazyRouter

As mentioned before, this is a **direct replacement** of `Router` so it's safe to replace one with another in your `App.razor` file.

```diff
- <Router AppAssembly="@typeof(Program).Assembly">
+ <LazyRouter AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<LayoutView Layout="@typeof(MainLayout)">
<RouteView RouteData="@routeData" />
</LayoutView>
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address</p>
</LayoutView>
</NotFound>
- </Router>
+ </LazyRouter>
```

Done! The router will automatically provide SPA style navigation for your lazy routes!

# Custom 'Loading' screen

It is possible to customize the 'loading' screen while a Page is downloading the needed Assemblies.

This is done by setting the `Loading` `RenderFragment`:

```razor
<LazyRouter AppAssembly="@typeof(Program).Assembly">
<Loading Context="moduleName">
<LayoutView Layout="@typeof(MainLayout)">
<div class="fullScreenOverlay">
<LoadingSpinner />
</div>
</LayoutView>
</Loading>
@* ... the rest of <Found> and <NotFound> *@
</LazyRouter>
```

# SEO and Prerendering Support

There is no need to worry about SEO. If you use BlazorServer or Prerendering, the returned page HTML will be **fully rendered** automatically by the server so there is no difference between the prerendered HTML content of `<Router>` and `<LazyRouter>`.
9 changes: 9 additions & 0 deletions docs/Components.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
There are multiple ways of using resources from modules, but the simplest one is to use the built-in components from `BlazorLazyLoading.Components`.

It should be installed in every library that wants to consume decoupled resources:

```xml
<PackageReference Include="BlazorLazyLoading.Components" Version="1.1.0" />
```

This section will cover the different components available and their usage.
47 changes: 47 additions & 0 deletions docs/[email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
The following nuget package includes everything you need to support lazy loading on **Blazor Server** and **Prerendering**.<br/>

It can be installed by adding the following line inside the host csproj:

```xml
<PackageReference Include="BlazorLazyLoading.Server" Version="1.1.0" PrivateAssets="all" />
```

It will also require to be initialized from **Startup.cs** by adding the following lines:<br/>

```cs
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddLazyLoading(new LazyLoadingOptions
{
ModuleHints = new[] { "ModulesHost" }
});
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// ideally after calling app.UseStaticFiles()
app.UseLazyLoading(); // serves DLL and PDB files as octet/stream
}
}
```
# LazyLoadingOptions

* #### ModuleHints

In order to find the `_lazy.json` manifest files and DLLs, you need to specify *at least* an entry-point to a lazy module. This **must** be done by passing the *"known modules"* as **string**.

>Specifies a list of Module Names (hints) to:
>- Download DLLs from them
>- Use their manifest to locate lazy resources

* #### UseAssemblyIsolation

Serverside Blazor has a small disadvantage: by default, the loaded assemblies are in **the same context** for every user. If you have a `static` field in them, the value will be shared accross all SignalR connections. If this happens, it can introduce weird bugs and massive scalability issues (*it could also happen with a nuget package using a static field internally*).

To avoid these issues, BlazorLazyLoading introduces full assembly isolation by creating a Scoped `AssemblyLoadContext`. Unless you really know what you are doing, it is recommended to **NOT** turn this off.

>default: true
>Configures assembly isolation level. Do NOT set this to 'false' unless you want to share 'static' fields between users.<br />
>Keeping this enabled ensures that the server can be scaled horizontally.<br />
58 changes: 58 additions & 0 deletions docs/[email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
The following nuget package includes everything you need to support lazy loading on **Blazor WebAssembly** (when statically published, using DevServer or using [DualMode](https://github.com/Suchiman/BlazorDualMode)).<br/>

It can be installed by adding the following line inside the host csproj:

```xml
<PackageReference Include="BlazorLazyLoading.Wasm" Version="1.1.0" PrivateAssets="all" />
```

It will also require to be initialized from **Program.cs** by adding the following lines:<br/>

```cs
builder.Services.AddLazyLoading(new LazyLoadingOptions
{
ModuleHints = new[] { "ModulesHost" }
});
```

# Configuring the Linker

In order to load assemblies dynamically, the linker can be a big issue since it is **enabled** for release builds **by default**.

There are 2 ways of approaching this:

### Disabling the Linker (easy)

This option sounds worse that it is in reality. Yes, disabling the linker will ship mscorlib as initial download to the browser, **BUT that's all**. The initial impact won't be big if we Lazy Load the rest of the application.

```xml
<PropertyGroup>
<BlazorWebAssemblyEnableLinking>false</BlazorWebAssemblyEnableLinking>
</PropertyGroup>
```

### Using LinkerConfig.xml (advanced)

Even if this solution is more advanced, it will give us the best performance. Please refer to [the following guide](https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/blazor/configure-linker?view=aspnetcore-3.1#control-linking-with-a-configuration-file) to setup your *LinkerConfig.xml*.

The recommendation here would be something like this, but you might need to adapt it for your needs:

```xml
<?xml version="1.0" encoding="UTF-8" ?>
<linker>
<assembly fullname="netstandard" /> <!-- keep full netstandard since its used by the lazy modules -->
<assembly fullname="ModulesHost" /> <!-- keep full entrypoint -->
</linker>
```

Done! Lazy Loading is now configured 😄

# LazyLoadingOptions

* #### ModuleHints

In order to find the `_lazy.json` manifest files and DLLs, you need to specify *at least* an entry-point to a lazy module. This **must** be done by passing the *"known modules"* as **string**.

>Specifies a list of Module Names (hints) to:
>- Download DLLs from them
>- Use their manifest to locate lazy resources
5 changes: 5 additions & 0 deletions docs/Configuring-Lazy-Loading.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Depending on the Blazor host, different instructions are required.<br/>
Please refer to the specific guide 😄

- [WebAssembly](Configuring-Lazy-Loading-@-WebAssembly)
- [BlazorServer](Configuring-Lazy-Loading-@-Server)
Loading