App Initialization
Just like in a .NET console application, a Transpose application's entry point is
its static Main method. Transpose emits the entry point into the generated
bundle and the runtime invokes it once the page is ready.
The Main method
Define a class with a static Main:
using System;
using Transpose;
namespace MyProject
{
public class Program
{
public static void Main()
{
Console.WriteLine("Hello from Transpose!");
}
}
}
Roslyn picks the entry point the same way it does for a console app, so
Main(string[] args), Main(), and the async Task Main forms all work. If the
entry point returns a Task, the runtime awaits it and surfaces a faulted result
rather than silently dropping it.
Transpose emits the entry point as the type's main member; the runtime registers
it to run when the document is ready — immediately if the document has already
finished loading, which is what makes a lazily fetched bundle start on load too.
Static initializers of the types in the bundle run before it.
The [Ready] attribute
[Ready] marks a static method to run when the DOM is ready. Transpose emits
a registration for each one, after every type in the bundle has been defined, so
the method can safely touch other types.
using System;
using Transpose;
namespace MyProject
{
public class App
{
[Ready]
public static void OnReady()
{
// runs on DOMContentLoaded, or immediately if the document is already loaded
Console.WriteLine("DOM is ready!");
}
}
}
You can have several [Ready] methods.
Don't depend on the order
Main and every [Ready] method are scheduled through the same runtime hook, so
their relative order is an implementation detail. Put anything order-sensitive in
one place — call the dependent steps from Main explicitly — rather than
splitting it across several [Ready] methods.
Running code before Main
The h5 [Init] attribute, which emitted a static method's body at a chosen
position in the file, is not implemented in Transpose. Use the standard .NET
[ModuleInitializer]
attribute instead: Transpose collects those methods and calls them at the top of
the entry point, before the Main body runs.
using System;
using System.Runtime.CompilerServices;
namespace MyProject
{
public static class Config
{
[ModuleInitializer]
internal static void Initialize()
{
// runs before the Main body
Console.WriteLine("Initializing configuration…");
}
}
}
Note that unlike on .NET, where a module initializer runs at module load,
Transpose sequences these calls immediately ahead of Main — so they still run
before your application logic, but not before the bundle's type definitions.
A static constructor on a type is the other option, and it behaves as you would
expect: the runtime runs a type's static initializer before the type is first
used.
Execution order:
- Type definitions are registered and static initializers run.
[ModuleInitializer]methods, then theMainbody — both once the document is ready.[Ready]methods, also once the document is ready (order relative toMainunspecified).
Controlling the generated page
The generated index.html is what loads the runtime and your bundle and thereby
triggers the sequence above. Configure it through the html section of
tps.json:
{
"output": "$(OutDir)tps/",
"html": {
"disabled": false,
"title": "My Transpose App",
"body": "<div id=\"root\"></div>"
}
}
Set "disabled": true when the page is supplied by something else — a library, or
an application whose HTML is served by a back-end. You then load tps.js and your
bundle with your own <script> tags, in that order, and the same initialization
sequence runs.