ASP.NET Tips #008 - 独自にファイル拡張子と MIME タイプを関連付けて .vue の単一ファイルコンポーネントを事前ビルド無しで読み込んでレンダリングする

SPA ではなく ASP.NET Core MVC でサイトを構築しながら、 Vue.js を使い部分的にリッチなコンポーネントを実装したいと言った場合に、「.vue」拡張子の単一ファイルコンポーネントをそのまま読み込めたら便利ですよね。

jsDelivr (CDN) から vue@2.6.12http-vue-loader@1.4.2 を読み込み、自作した「Hello.vue」をコンパイル無しでレンダリングしたいと思います。

ただ、「.vue」の拡張子は ASP.NET Core では未定義の為、ファイル読み込み時に 404 Not Found としてエラーになってしまうので、Startup.cs の app.UseStaticFiles() のオプションで、ファイル拡張子とMIMEタイプを関連付ける必要があります。

まず、Startup.cs を開き using Microsoft.AspNetCore.StaticFiles; を追加して、 app.UseStaticFiles() にオプションを指定します。

次に FileExtensionContentTypeProvider のインスタンスを用意して、マッピングにファイル拡張子とMIMEタイプを指定して関連付けます。
今回は、「.vue」のファイルに対して「application/octet-stream」を紐づけしています。

~/Startup.cs
using Microsoft.AspNetCore.StaticFiles;

namespace AspNetTips.MvcSite
{
	public class Startup
	{
		// 省略...

		public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
		{
			// 省略...

			// ファイル拡張子とMIMEタイプを関連付ける
			var provider = new FileExtensionContentTypeProvider();
			provider.Mappings.Add(".vue", "application/octet-stream");
			app.UseStaticFiles(new StaticFileOptions
			{
				ContentTypeProvider = provider
			});

			// 省略...
		}
	}
}

この関連付けが無い状態で Hello.vue を読み込むと 404 で失敗してしまいます。

開発者ツール:ネットワーク (404 - Not Found)

関連付けを Startup.cs で行う事で、「.vue」のファイルを読み込んでも 200 で読み込みが可能になります。

開発者ツール:ネットワーク (200 - OK)

ここまで実装ができたら .NET 側はほぼ終わりであとは Vue.js の準備になります。

_Layout.cshtml を開き、 body の終わりで vue.js と http-vue-loader を CDN から読み込みさせます。

~/Views/Shared/_Layout.cshtml
<environment include="Development">
	<script src="https://cdn.jsdelivr.net/npm/vue@@2.6.12/dist/vue.js"></script>
</environment>
<environment exclude="Development">
	<script src="https://cdn.jsdelivr.net/npm/vue@@2.6.12/dist/vue.min.js"></script>
</environment>
<script src="https://cdn.jsdelivr.net/npm/http-vue-loader@@1.4.2/src/httpVueLoader.min.js"></script>

Vue.js を埋め込むページ (Home/Index) を開き Vue のインスタンスを生成し、 components で Hello.vue を読み込ませます。

あとは <div id="app"></div> の範囲内に <hello></hello> と記述して埋め込みます。

~/Views/Home/Index.cshtml
@section Scripts {
	<script>
		new Vue({
			el: '#app',
			components: {
				'hello': httpVueLoader('/vue/Hello.vue'),
			},
		})
	</script>
}
<div id="app">

	<p>↓コンポーネントをそのまま呼び出した場合</p>

	<hello></hello>

	<p>↓props の name と slot の default を指定して呼び出した場合</p>

	<hello name="Plusism">
		<p>コンテンツ こんてんつ コンテンツ こんてんつ コンテンツ</p>
		<p class="orange">コンテンツ こんてんつ コンテンツ こんてんつ コンテンツ こんてんつ コンテンツ</p>
		<p>コンテンツ こんてんつ コンテンツ こんてんつ コンテンツ</p>
	</hello>

</div>

最後に公式サイトの 単一ファイルコンポーネント を参考に、埋め込む「Hello.vue」を記述するだけとなります。

~/wwwroot/vue/Hello.vue
<template>
	<section>
		<h2>{{greeting}}, {{name}}!</h2>
		<slot>デフォルトスロット</slot>
	</section>
</template>

<script>
	module.exports = {
		props: {
			name: {
				type: String,
				default: 'World',
				required: false
			}
		},
		data: function () {
			return {
				greeting: 'Hello'
			}
		}
	}
</script>

<style>
	// 省略...
</style>

コーディングが終わったらデバッグ実行してみて表示を確かめます。

デバッグ実行時の表示

この様な流れで独自の拡張子のファイルを読み込んだり、 Vue.jsを部分的に埋め込んだりが可能になります。

試作環境
  • Windows 10 (20H2)
  • Visual Studio 2019 (v16.9.3)
  • .NET SDK 5.0.201
  • ASP.NET Core 5.0 / MVC