javascriptasp.net-corerazorblazordynamic-import

Blazor Collocate js and cs files


It is possible to collocate a .js file and a related .razor file as described here. Is there a way to collocate a .js file and .cs file in a similar way? I imagine it looking similar to this:

MyService.cs:

public class MyService
{
    private readonly IJSRuntime _js;

    private IJSObjectReference? _jsModule;

    public MyService(IJSRuntime js)
    {
        _js = js;
    }

    public async Task MyMethod()
    {
        if (_jsModule == null)
        {
            var modulePath = $"./_content/Company.Library/Service/MyService.cs.js";
            _jsModule = await _js.InvokeAsync<IJSObjectReference>("import", modulePath);
        }

        await _jsModule.InvokeVoidAsync("myjsmethod");
    }
}

MyService.cs.js:

export function myjsmethod() {
    console.log('Hello World');
}

This compiles fine, but when run the MyService.cs.js file fails to load with the error:

failed to fetch dynamically imported module


Solution

  • I added the below to my .csproj file. It copies the collcated .cs.js files into the wwwroot folder before build. It also hides the files it copied in visual studio to reduce the chance someone edits the copy instead of the original.

          <Target Name="CopyCsJsFilesToWwwRoot" BeforeTargets="BeforeBuild;BeforeRebuild">
            <ItemGroup>
              <JsCsFiles Include="**\*.cs.js" Exclude="**\wwwroot\**" />
            </ItemGroup>
            <!-- Copy all the collocated *.cs.js files to wwwroot before build-->  
            <Copy SourceFiles="@(JsCsFiles)" DestinationFiles="@(JsCsFiles->'$(MSBuildProjectDirectory)\wwwroot\js\%(Identity)')" SkipUnchangedFiles="true" />
            <!-- Ensure copied files get picked up -->
            <ItemGroup>
              <Content Remove="**\*.cs.js" />
              <Content Include="**\*.cs.js" />
            </ItemGroup>
          </Target>
          <!-- prevent the copied *.cs.js file from being seen in visual studio-->
          <ItemGroup>
            <Content Update="**\wwwroot\**\*.cs.js" Visible="false" />
          </ItemGroup>