Since releasing Oqtane 1.0 during Microsoft BUILD 2020, the response by the .NET community has been tremendous. We attribute this phenomenon partly to the excitement around Blazor WebAssembly and partly to the fact that Oqtane offers a unique value proposition for modular software development which has really struck a chord with developers worldwide. In the past month there has been a total of 57 pull requests submitted by 8 different contributors, pushing the total number of project commits over 1000, and establishing the foundation of a passionate community ecosystem.
Based on the breadth of features included in the initial MVP product release, the priority has been on stabilizing and fortifying some of the fundamental pillars of the framework. In particular, both performance and modularity were significantly enhanced in the 1.0.1 release. In addition, more than 30 issues were resolved, representing a significant focus on overall product stability.
Modularity
The ability to create modules and themes which can be seamlessly integrated at run-time is a critical use case in a modular application framework. Modules and themes often want to utilize third party libraries for specialized application functionality. Oqtane was enhanced in this area in the 1.0.1 release to be able to locate and load third party libraries on-demand. The only requirement is that a module must include any third party assemblies in its Nuget package.
In addition, when running on Blazor WebAssembly, assemblies need to be downloaded from the server to the browser. Oqtane now includes a Dependencies property in the IModule interface which allows developers to identify the assemblies which need to be downloaded. On startup Oqtane will utilize this property to bundle assemblies ( and symbols ) located in the Server /bin folder into a compressed zip file that is downloaded to the client.
public class ModuleInfo : IModule
{
public ModuleDefinition ModuleDefinition => new ModuleDefinition
{
Name = "Module",
Version = "1.0.0",
Dependencies = "Module.Shared.Oqtane,ThirdPartyAssembly"
};
}
Stylesheets and JavaScript
Blazor is a modern web framework but it still relies on the traditional fundamentals of the web including stylesheets and JavaScript - both of which are challenging to manage in a SPA application due to limitations in the web browser environment. This is especially true for modular applications where a page is constructed dynamically at run-time based on flexible configuration rather than hard-coded elements.
Modules and themes need to have the ability to define their own visual characteristics and this is typically done via stylesheets. However because a web page is never fully reloaded in a SPA application, the stylesheet link references need to be dynamically injected and trimmed for each user interaction. This is critical in order for the cascading behavioral aspects of stylesheets to function properly. Oqtane abstracts this complexity from the developer and simply requires a module or theme to declare their stylesheet dependencies within their razor components. Oqtane uses these declarations to load stylesheets as needed on-demand.
public override List<Resource> Resources => new List<Resource>()
{
new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css", Integrity = "sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk", CrossOrigin = "anonymous" },
new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" }
};
JavaScript poses a different technical challenge and although Blazor provides the ability to minimize the dependency on JavaScript there are still situations where it needs to be utilized. In order to call JavaScript in Blazor you must use JS Interop, however you still need to register the script in the page first. In a static application you can hard-code your scripts in _host.cshtml however in a modular application you do not know your dependencies until run-time so the traditional approach is not possible. And to make it even more challenging there are often dependencies between different JavaScript libraries requiring them to be loaded in a specific order. Luckily some of these problems have already been solved by the JavaScript community so we decided to utilize a light-weight JavaScript dependency manager named LoadJS. However we still wanted to abstract the complexity from the developer so we opted to use the same approach we utilized for stylesheets. Modules or themes declare their script dependencies within their razor components and Oqtane uses these declarations to load the JavaScript as needed on-demand.
public override List<Resource> Resources => new List<resource>()
{
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill1.3.6.min.js" },
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-blot-formatter.min.js" },
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-interop.js" }
};
The Oqtane framework continues to evolve at a rapid pace to meet the needs of .NET developers. The 1.0.1 release is available for download on Github.