Blazorでnpmを使う

今回はBlazorでnpmを使ってjsバンドルを作成して使うとこまで記事にします。

正直なところnpmを使う前提であればBlazorを使う理由は
無いかなとも思いますが、とりあえず手順を残しておきます。

Symbolアプリ開発にはいろんな方が作成してくれたモジュールがあるのですが、
基本はjavascript or typescriptなのでC#で使用したい場合は一から作成しないといけません。。
そこに時間を使いたくはないのでNpmを使える環境を用意したい！

ちなみにSymbolとは何か気になった方は以下のリンクを参照して下さい。

https://symbol-community.com/ja/docs

それでははじめましょう！

# Blazorプロジェクトを作成
Blazor WebAssemblyでプロジェクトを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/4ab6b5bd-f583-2db5-778a-a292bf2167b4.png)

プロジェクト名は任意で決めて下さい。
.NET 7.0を使用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/a9e9979d-e86f-6d91-a11e-64812d9f1f3c.png)

# Npm環境を構築
作成されたプロジェクトのルートにNpmJSフォルダを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/82be4010-26d7-059a-42d5-90c784ed32b7.png)

NpmJSフォルダにpackage.jsonを作成します。
``` npm
npm init -y
```

次にwebpack,webpack-cliをインストールします。
``` npm
npm install webpack webpack-cli --save-dev
```

node_modulesフォルダが作成されていることを確認して下さい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/acb7ffd2-1d44-4068-354a-b293b24e29de.png)

NpmJSフォルダの下にsrcフォルダとさらにその下にindex.jsを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/801ee281-13c2-76ad-d1f2-7659e16ffcce.png)

webpack.config.jsを作成します。
``` javascript

const path = require('path');

module.exports = {
    mode: "development",
    entry: {
        index: path.resolve(__dirname, "src/index.js"),
    },
    output: {
        path: path.resolve(__dirname, "../wwwroot/js"),
        filename: "[name].bundle.js",
        library: "BlazorNpmSample"
    }
};

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/ac5990a8-d796-c4ad-8abc-5a2535cc295c.png)


package.jsonにdev,buildコマンドを追記します。
``` json
{
    "scripts":{
        "dev": "webpack --mode development",
        "build": "webpack --mode production" 
    }
}
```

後はNpmJSフォルダでビルドを行い、
バンドルされたjsが出力されることを確認して下さい。

``` npm
npm run build
```

wwwrootにjsフォルダとindex.bundle.jsが出力されていればOKです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/c24914a1-c986-8af5-58cf-62d3e90d5bde.png)

出力されたjsファイルはindex.htmlで読込みます。
blazor.webassembly.jsの直後くらいに追記して下さい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/a29123df-aa71-23a6-48dc-6a7e9a2295f7.png)

もしソリューションをビルドする際に一緒にjsファイルをバンドルする場合は
プロジェクトファイルに以下を追記して下さい。
プロジェクトを右クリックしてプロジェクトファイルの編集を選択すれば編集できます。

``` xml:BlazorNpmSample.csproj
  <Target Name="PreBuild" BeforeTargets="PreBuildEvent">
    <Exec Command="npm install" WorkingDirectory="NpmJS" />
    <Exec Command="npm run build" WorkingDirectory="NpmJS" />
  </Target>
```

# 実際に動かしてみる

Symbol開発で便利なsymbol-node-utilを追加します。

``` npm
npm install symbol-node-util
```

https://www.npmjs.com/package/symbol-node-util

index.jsにActiveなノードのURLを返す関数を作成します。

``` javascript
import { getActiveNode } from "symbol-node-util";

export async function GetActiveNode(network) {
    return await getActiveNode(network);
}
```

そしてビルド。。。
``` npm
npm run build
```

そしてModule not found: Error: Can't resolve 'crypto'が表示される。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/df19d4c3-31e4-081a-3588-96cc5979e91a.png)

一個ずつ対応しても良いんですが、面倒なので以下の記事を参考にして解決します。

https://qiita.com/issei_k/items/f33164a22b8c1dc74a09

``` npm
npm install --save-dev assert buffer console-browserify constants-browserify crypto-browserify domain-browser events stream-http https-browserify os-browserify path-browserify punycode process querystring-es3 stream-browserify readable-stream readable-stream readable-stream readable-stream readable-stream string_decoder util timers-browserify tty-browserify url util vm-browserify browserify-zlib
```

``` javascript:webpack.config.js
resolve: {
        alias: {
            assert: "assert",
            buffer: "buffer",
            console: "console-browserify",
            constants: "constants-browserify",
            crypto: "crypto-browserify",
            domain: "domain-browser",
            events: "events",
            http: "stream-http",
            https: "https-browserify",
            os: "os-browserify/browser",
            path: "path-browserify",
            punycode: "punycode",
            process: "process/browser",
            querystring: "querystring-es3",
            stream: "stream-browserify",
            _stream_duplex: "readable-stream/duplex",
            _stream_passthrough: "readable-stream/passthrough",
            _stream_readable: "readable-stream/readable",
            _stream_transform: "readable-stream/transform",
            _stream_writable: "readable-stream/writable",
            string_decoder: "string_decoder",
            sys: "util",
            timers: "timers-browserify",
            tty: "tty-browserify",
            url: "url",
            util: "util",
            vm: "vm-browserify",
            zlib: "browserify-zlib"
        },
    }
```

これでもう一度build!

OK問題なし(この辺は適当)！

Blazor側からJSを呼び出してみます。

``` typescript:index.razor
@page "/"

@inject IJSRuntime JSRuntime

<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />

<button onclick="@btn_click">get active node</button>

@code{

    private async Task btn_click()
    {
        //symbol-node-utilのgetActiveNodeの戻り値を取得
        //引数はメインネットを表す104
        var activeNode = await JSRuntime.InvokeAsync<string>("BlazorNpmSample.GetActiveNode", new object[] { 104 });
        Console.WriteLine(activeNode);
    }
}

```

コンソールにノードのURLが出力されていればOKです！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532264/beea0ebf-b8bc-6566-961c-303575edd709.png)

これでBlazorからnpmを使ってパッケージをインストールし、
webpackを使ってバンドルしたjsの関数を呼び出すことができました。

実際はもう少し複雑なことがしたいのですが、まだ調査中なのでおいおい記事にするかもしれません。
ではまた(^^)/