tryphotino / photino.NET

https://tryphotino.io
Apache License 2.0
915 stars 74 forks source link

Can't dynamically import JavaScript modules from third party NuGet packages #109

Closed Jinjinov closed 2 years ago

Jinjinov commented 2 years ago

Trying to use a NuGet package that dynamically imports JavaScript modules fails with this error:

Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/plain". Strict MIME type checking is enforced for module scripts per HTML spec.

Failed to fetch dynamically imported module: http://localhost/_content/Blazorise/button.js?v=1.0.7.0
TypeError: Failed to fetch dynamically imported module: http://localhost/_content/Blazorise/button.js?v=1.0.7.0
   at Microsoft.JSInterop.JSRuntime.InvokeAsync[TValue](Int64 targetInstanceId, String identifier, Object[] args)
   at Blazorise.Modules.BaseJSModule.InvokeSafeVoidAsync(String identifier, Object[] args)
   at Blazorise.Button.<OnInitialized>b__12_0()
   at Blazorise.BaseAfterRenderComponent.OnAfterRenderAsync(Boolean firstRender)
   at Blazorise.BaseComponent.OnAfterRenderAsync(Boolean firstRender)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)

Steps to reproduce are described here: https://github.com/tryphotino/photino.Blazor/issues/68

MikeYeager commented 2 years ago

@Jinjinov I think we'd need to see your source code to troubleshoot farther. files appear to be coming from a local web server (http://localhost/...) So the question is, which local web server is running? Or have you set up http: as a custom scheme? (does that even work?) It's really up to the local web server or custom handler to set the MIME type, so we have to figure how local files are being served from http:.

Jinjinov commented 2 years ago

My source code: https://github.com/Jinjinov/Ididit/tree/main/Ididit.WebView.Photino

Jinjinov commented 2 years ago

Steps to reproduce:

  1. open Photino.Blazor.Sample https://github.com/tryphotino/photino.Blazor/tree/master/Samples/Photino.Blazor.Sample

  2. add Blazorise https://blazorise.com/docs/start

  3. Install-Package Blazorise.Bootstrap

  4. Install-Package Blazorise.Icons.FontAwesome

  5. add Blazorise to index.html

    <html>
    <head>
    <!-- inside of head section -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css">
    
    <link href="_content/Blazorise/blazorise.css" rel="stylesheet" />
    <link href="_content/Blazorise.Bootstrap/blazorise.bootstrap.css" rel="stylesheet" />
    </head>
    <body>
    <div id="app"></div>
    
    <!-- inside of body section and after the div/app tag  -->
    <!-- These are the standard js dependencies this provider tipically dependes upon, but Blazorise deems these as optional as Blazorise Components should work correctly without these  -->
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.min.js" integrity="sha384-VHvPCCyXqtD5DqJeNxl2dtTyhF78xXNXdkwX1CZeRusQfRKp+tA7hAShOK/B/fQ2" crossorigin="anonymous"></script>
    </body>
    </html>
  6. add @using Blazorise to _Imports.razor

  7. add Blazorise to Program.cs

using Blazorise;
using Blazorise.Bootstrap;
using Blazorise.Icons.FontAwesome;

builder.Services
    .AddBlazorise( options =>
    {
        options.Immediate = true;
    } )
    .AddBootstrapProviders()
    .AddFontAwesomeIcons();
  1. add Blazorise.Button to Index.razor
<Button Color="Color.Primary" Clicked="@OnButtonClicked">Click me</Button>
<Span>
    Clicked @counter times
</Span>
@code {
    int counter;

    Task OnButtonClicked()
    {
        counter++;

        return Task.CompletedTask;
    }
}
  1. If we run the app, we get:

Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/plain". Strict MIME type checking is enforced for module scripts per HTML spec.

Failed to fetch dynamically imported module: http://localhost/_content/Blazorise/button.js?v=1.0.7.0
TypeError: Failed to fetch dynamically imported module: http://localhost/_content/Blazorise/button.js?v=1.0.7.0
   at Microsoft.JSInterop.JSRuntime.InvokeAsync[TValue](Int64 targetInstanceId, String identifier, Object[] args)
   at Blazorise.Modules.BaseJSModule.InvokeSafeVoidAsync(String identifier, Object[] args)
   at Blazorise.Button.<OnInitialized>b__12_0()
   at Blazorise.BaseAfterRenderComponent.OnAfterRenderAsync(Boolean firstRender)
   at Blazorise.BaseComponent.OnAfterRenderAsync(Boolean firstRender)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
Jinjinov commented 2 years ago

I updated my source code: https://github.com/Jinjinov/Ididit/tree/main/Ididit.WebView.Photino

Do you have everything you need to solve this?

MikeYeager commented 2 years ago

@Jinjinov When we run your source code, we get the following in the browser dev tools: image No such files/folders exist in the /bin folder, so it makes sense that it can't load them. The mechanism loading them is Microsoft.AspNetCore.Components.WebView.TryGetResponseContent() and the actual error returned is 404 Not Found. This makes sense as the file isn't there. Do you have that file in your local /bin folder?

MikeYeager commented 2 years ago

@Jinjinov Upon further investigation, we think we've found and fixed the issue. We now see that the _content folder is dynamically loaded. We tracked the issue down to this comment in Microsoft.AspNetCore.Components.WebView.TryGetResponseContent(): image Of course, the URL it's trying to load http://localhost/_content/Blazorise/button.js?v=1.0.7.0 has parameters. So we're looking for a '?' in the URL and stripping the parameters off before asking AspNetCore to retrive the file. That seems to fix the issue. We're testing to see if that change causes any unforeseen problems and will merge the change into the debug branch if we don't find any.

MikeYeager commented 2 years ago

@Jinjinov It hasn't caused any failures in our tests, so it's checked into debug. We expect to build and post new versions early January. Thank you for providing the example. We couldn't have found the issue without it.

Jinjinov commented 2 years ago

@MikeYeager Thank you so much for taking the time to solve this.