javascript 在blazor中未定义使用webpack编译的JSInterop

sqougxex  于 2022-11-20  发布在  Java
关注(0)|答案(1)|浏览(147)

我有一个Blazor webassembly应用程序,我试图在其中包含使用JSInterop的typescript/javascript代码,但当webpack在构建过程中创建js代码时失败了。
当在我的wwwroot中创建一个简单的hello-world.js文件时,包含以下内容:

export function showAlertSimple() {
    alert("hello world");
}

我可以很容易地调用它使用:

public class HelloWorld : JSModule
{
    public HelloWorld(IJSRuntime js) 
        : base(js, "./js/hello-world.js")
    {
    }

    public async Task ShowAlert() => await InvokeVoidAsync("showAlert");
}

如果我尝试对一个在不同位置创建的typescript文件执行同样的操作,然后使用webpack将其编译到ES6,并将其放入同一个文件夹中,blazor将无法调用该方法:
./NpmJs/源代码/您好-世界2.ts

export function showAlertFromWebPack() {
    alert("Hello World from webpack");
}

./NpmJs/webpack.config.js
第一个
然后,这会在浏览器主控台中掷回下列例外状况:

crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: Could not find 'showAlertFromWebPack' ('showAlertFromWebPack' was undefined).
      Error: Could not find 'showAlertFromWebPack' ('showAlertFromWebPack' was undefined).

文件本身加载正确。我可以在源选项卡中看到它。
我错过了什么?
为了完整起见,这里有一个JSModule类,它是我在github上无耻地从Steven Sanderson那里插入的。

public abstract class JSModule : IAsyncDisposable
{
    private readonly Task<IJSObjectReference> moduleTask;

    // On construction, we start loading the JS module
    protected JSModule(IJSRuntime js, string moduleUrl)
        => moduleTask = js.InvokeAsync<IJSObjectReference>("import", moduleUrl).AsTask();

    // Methods for invoking exports from the module
    protected async ValueTask InvokeVoidAsync(string identifier, params object[]? args)
        => await (await moduleTask).InvokeVoidAsync(identifier, args);
    protected async ValueTask<T> InvokeAsync<T>(string identifier, params object[]? args)
        => await (await moduleTask).InvokeAsync<T>(identifier, args);

    // On disposal, we release the JS module
    public async ValueTask DisposeAsync()
        => await (await moduleTask).DisposeAsync();
}
j2cgzkjk

j2cgzkjk1#

我找到了两个可行的解决方案。一个使用webpack,另一个抛弃webpack,用vitejs代替它。
使用webpack,我们需要启用experiments.outputModule(https://webpack.js.org/configuration/experiments/#experimentsoutputmodule)并将output.library.type设置为module(https://webpack.js.org/configuration/output/#outputlibrarytype):
最终配置如下所示:

module.exports = {
    entry: {
        helloworld2: './src/hello-world2.ts',
    },
    module: {
        rules: [
            {
                test: /\.ts?$/,
                use: 'ts-loader',
                exclude: /node_modules/,
            },
        ],
    },
    resolve: {
        extensions: ['.tsx', '.ts', '.js'],
    },
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, '../../wwwroot/js'),
        library: {
            type: "module",
        },
    },
    experiments: {
       outputModule: true
    },
    devtool: 'source-map'
};

使用vitejsvite.config.js,配置看起来像这样:

import * as path from 'path';
import { defineConfig } from "vite";

export default defineConfig({
   appType: 'mpa',
   build: {
      target: 'esnext',
      outDir: '../wwwroot/js',
      lib: {
         entry: path.resolve(__dirname, './src/index.ts'),
         name: "YourPackageName",
         fileName: (format) => `your-package-name.${format}.js`,
      },
   }
});

然后,Vite本身将生成2个文件:

  • your-package-name.es.js
  • your-package-name.umd.js

您需要在blazor中链接/使用es文件,然后就可以开始了。

相关问题