Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

ASP.NET 5+AngularJSでトレンドなSPAアプリを開発しよう!

あらゆるソフトウェア開発者のサポートを目指す開発ツール「Visual Studio 2015」特集 第4回

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2015/08/17 14:00

 SPA(Single Page Application)の流行によって、Webアプリ開発に占めるJavaScriptの存在感は増しています。本稿では、Visual Studio 2015(ASP.NET 5)で強化されたJavaScript開発のための諸機能/ツールを、具体的なサンプルアプリを実装しながら解説していきます。

はじめに

 「SPA(Single Page Application)」とは、その名のとおり、単一のページで構成されるWebアプリのこと。初回のリクエストでは、ページ全体を応答しますが、以降はJavaScriptによって必要な部分だけを更新します。JavaScriptだけでは実現できない――例えば、データベースの取得/更新は、Ajax/WebSocketなどの通信技術によって賄います。

SPA(Single Page Application)とは?

SPA(Single Page Application)とは?

 SPAは、デスクトップアプリによく似た、直観的で敏速な操作性を提供できることから、近年、にわかに注目を浴びています。すでにFacebook、Twitterなどの主要なサイトが、いわゆるSPA技術に対応していることからも、SPAは一時の流行にとどまらず、今後、Webアプリを開発していく上で基本的な――ごく当たり前のアプローチになっていくものと思われます。

 Visual Studio 2015(ASP.NET 5)では、こうしたSPA(フロントエンド)開発を効率化するために、npm(Node.js)をはじめ、Grunt/Gulp、Bowerなどのツールに標準で対応しています。以前はNuGet+System.Web.Optimization名前空間というASP.NET(.NET Framework)独自の仕組みでJavaScriptライブラリ/スタイルシートを管理していたものが、デファクトスタンダードなツールで開発できるようになったわけです。

 以前のASP.NETを知っていた人にとっては、新たなツールを学ばなければなりませんが、長期的な視点では、開発プラットフォームを問わず、共通のツールで開発できるのはメリットとなるでしょう。また、他のプラットフォームで開発してきた人にとっては、一層、ASP.NET導入のハードルが低くなったことも意味します。

 本稿では、これらのツールをVisual Studio 2015(ASP.NET 5)で導入/利用する手順を、具体的なサンプルアプリとともに解説します。

対象読者

  • ASP.NET MVC/ASP.NET Web APIの基本的な開発手法を理解している方
  • リッチなフロントエンド開発を効率化したいと思っている方

必要な環境

 本連載では以下の環境でサンプルを実行します。

Windows 10での動作

 本稿はWindows 8の環境で執筆しておりますが、Visual Studio 2015はWindows 10での開発を想定して作成されていますので、Windowsのルック&フィールは異なるもののWindows 10でも実行可能です。

本稿で作成するサンプルアプリ

 本稿では、以下のような記事情報を参照/更新するアプリを開発します。

本稿で作成するサンプルアプリ
本稿で作成するサンプルアプリ

 ただし、本稿では、紙面の都合上、サーバーサイド領域の解説は割愛します。詳細なコードについては、ダウンロードサンプルを参照してください。また、ASP.NET Web APIについては「ASP.NET Web API入門」を、データベースアクセスについては「ADO.NET Entity Framework入門」などの記事を併せて参照することをお勧めします。

 以下では、クライアントサイド領域にフォーカスして、解説を進めていきます。クライアントサイドでは、以下の図のようなライブラリ/ツールを使っています。解説を読み進めるにあたって、それぞれの関係をおさえておきましょう。

クライアントサイドでのライブラリ/ツールの関係
クライアントサイドでのライブラリ/ツールの関係

統合されたASP.NET 5の諸機能

 ASP.NET 5のプロジェクトテンプレートを選択すると、[フォルダーおよびコア参照を追加する]のチェックが無効になっていることに気づくかもしれません。これは、ASP.NET 5では、従来、独立したフレームワークであったASP.NET MVC、Web API、Web Pagesが1つのフレームワークとして統合されたためです(個別に参照を追加する必要がありません)。

[新しいASP.NETプロジェクト]ダイアログ
[新しいASP.NETプロジェクト]ダイアログ

 これまではページ開発ではASP.NET MVC、サービス開発ではASP.NET Web APIと、個々に学習しなければならなかったものが、ASP.NET 5では、いよいよ1つのAPIのもとで、区別なく開発を進められるというわけです。SPAの世界では、ページ/サービス開発は併存するのが当たり前になってきますので、双方の実装が統一されることで、より開発がスムーズになるでしょう。

定型的なタスクを自動化する「Grunt」

 Gruntは、JavaScriptで動作するタスクランナーです。フロントエンド開発では、さまざまに定型的な作業が発生します。例えば、TypeScriptファイルのコンパイル、JSLintなどによる品質チェック、JavaScriptファイルの圧縮/連結などです。これらの作業一つ一つは単純ですが、開発の最中に何度も繰り返さなければならないとなれば、その手間はばかになりませんし、作業ミスのもとにもなります。そこでGruntを利用することで、こうしたタスクを自動化できるわけです(注1)。他の言語を知っている人であれば、Ant(Java)、makeのようなものと考えると、理解しやすいでしょう。

 本稿では、アプリで利用するJavaScriptファイル一式を圧縮し、/wwwroot/scriptsフォルダーにapp.jsとして配置するまでを、Gruntを使って自動化してみます。

注1

 同じくタスクランナーとしてGulpを選択することもできます。ASP.NET 5 Web Applicationプロジェクトでは、デフォルトでGulpが有効になっています。

[1]Grunt/Gruntプラグインをインストールする

 Gruntと、そのプラグインは、npm(Node Package Manager)からインストールできます。npmは、JavaScriptの実行環境であるNode.jsで動作するパッケージ管理ツールです。フロントエンド開発では、Grunt/Gulpのような開発ツールをインストールするために利用することになるでしょう。

 npmを利用するには、プロジェクトルート(本稿サンプルでは/AngularSpa)を右クリックし、表示されたコンテキストメニューから[追加]-[新しい項目...]を選択します。[新しい項目の追加]ダイアログが表示されたら、「NPM 構成ファイル」を選択してください。ファイル名は「package.json」で固定です。

 package.jsonの骨組みが表示されるので、以下のように編集してみましょう。

リスト1 package.json
{
  "version": "1.0.0",
  "name": "Sample",
  "private": true,
  "devDependencies": {
    "grunt": "~0.4.5",
    "grunt-contrib-uglify": "~0.9.1"
  }
}

 devDependencies配下には、現在のアプリで開発用途として利用するパッケージを「パッケージ名: バージョン番号」の形式で列挙します。バージョン番号先頭の「~」は、パッケージのマイナーバージョンアップがあった場合に、そちらをインストールすることを表します。この例であれば、以下のパッケージをインストールします。

本稿でインストールするパッケージ
パッケージ 概要
grunt Grunt本体
grunt-contrib-uglify JavaScript圧縮のためのGruntプラグイン

 Gruntそれ自体は、ごくシンプルなランナーなので、個別のタスク定義にはプラグインを導入するのが一般的です。

 package.jsonを編集する際には、利用できるパッケージ/バージョン番号がインテリセンスで候補表示されますので、編集もごく手軽に行えます。

利用可能なパッケージ名/バージョンを候補表示
利用可能なパッケージ名/バージョンを候補表示

[2]パッケージをインストールする

 列挙したパッケージは、package.jsonを保存したタイミングでプロジェクトに自動的にインストールされます。ソリューションエクスプローラーから/依存関係/NPMフォルダーを展開すると、登録済みのパッケージが表示されます。

 もしもパッケージの横に「インストールされていません」と表示されている場合には、/NPMフォルダーを右クリックし、コンテキストメニューから[複数のパッケージの復元]を選択してください。

インストール済みのパッケージを確認
インストール済みのパッケージを確認

[3]Gruntの構成ファイルを準備する

 Gruntでは、gruntfile.jsで実行すべきタスクを定義します。/AngularSpaフォルダーを右クリックし、表示されたコンテキストメニューから[追加]-[新しい項目...]を選択します。[新しい項目の追加]ダイアログが表示されたら、「Grunt 構成ファイル」を選択してください。ファイル名は「gruntfile.js」で固定とします。

リスト2 gruntfile.js
// gruntfile.jsの外枠
module.exports = function (grunt) {
  // (1)Gruntの設定(初期化)
  grunt.initConfig({
    // uglify-myTargetタスクを定義
    uglify: {
      myTarget: {
        files: {
          'wwwroot/scripts/app.js':	// 圧縮後のファイル
          [
            'Scripts/**/*.js'	// 圧縮対象のファイル
          ]
        }
      }
    }
  });

  // (2)プラグインのロード
  grunt.loadNpmTasks('grunt-contrib-uglify');
  // (3)タスクの登録
  grunt.registerTask('default', [ 'uglify' ]);
};

 gruntfile.jsは、大きく以下のブロックから構成されます。

  • (1)タスクの設定(uglify/watch)
  • (2)プラグインのロード
  • (3)タスクを登録

 この例であれば、uglify-myTargetタスクとして、/Scriptsフォルダー配下のすべての.jsファイルを圧縮/連結し、/wwwroot/scriptsフォルダー配下のapp.jsにまとめるための作業を定義しています((1))。uglifyはgrunt-contrib-uglifyで決められたタスク名で、myTargetは開発者が自由に決められるサブタスク名です。(2)は、uglifyタスクを利用するために、grunt-contrib-uglifyプラグインをロードしています。

 (3)は、defaultタスクとしてuglifyタスクを登録しています。本稿では利用しませんが、無条件に実行したいタスクは、defaultタスクとして登録しておくことで、gruntコマンドからまとめて実行できるようになるので便利です。

 そのほか、gruntfile.jsの詳しい構文については、別稿『Web作成の定形作業を自動化できるJavaScriptタスク実行環境Grunt』も併せて参照してください。

/wwwrootフォルダー

 ASP.NET 5で、新規にプロジェクトを作成すると、ガラリと構成が変化していることに気づくかもしれません。

ASP.NET 5プロジェクトテンプレート(Empty)の初期状態
ASP.NET 5プロジェクトテンプレート(Empty)の初期状態

 トップフォルダーの/Solution Itemsはソリューション項目、/srcがプロジェクトの本体です。さらに、プロジェクトフォルダー(ここでは/AngularSpaフォルダー)配下にある/wwwrootフォルダーに注目です。名前からも想像できるように、ここにはエンドユーザーがアクセスできるHTMLファイル、JavaScriptライブラリ/スタイルシート、画像リソースだけを配置します。ASP.NET 5では、/wwwrootフォルダーによって、アプリ内部で利用するソースコードと、開示すべきリソースとを、明確に区別しているのです。コントローラー/データモデルなどのソースコードは、/wwwrootフォルダー以外に配置します。

[4]タスクを実行する

 Visual Studioでは、Grunt/Gulpで定義されたタスクを管理/実行するために、専用のタスクランナーエクスプローラーが準備されています。gruntfile.jsを保存したら、登録済みのタスク(実タスクuglifyと、別名定義されたdefaultタスク)が表示されていることを確認してみましょう。

定義済みのタスクを確認(タスクランナーエクスプローラー)
定義済みのタスクを確認(タスクランナーエクスプローラー)

 タスクを実行するには、目的のタスクを右クリックして、表示されたコンテキストメニューから[実行]を選択してください。また、特定のタイミングでタスクを実行するには、同じく目的のタスク(例えばuglify)を右クリックして、[バインディング]-[ビルド後]を選択します。これによって、ビルドが成功したタイミングでuglifyタスクが実行されることになります。そのほか、「プロジェクトを開く」「ビルド前」「クリーン」などのタイミングを選択できます。

 /Scriptsフォルダー配下に適当な.jsファイルを配置して、タスクを実行することで、/wwwroot/scripts/app.jsが生成されていることを確認してみましょう。

左:圧縮前の.jsファイル、右:圧縮後の.jsファイル
左:圧縮前の.jsファイル、右:圧縮後の.jsファイル

クライアントサイド開発のためのパッケージ管理ツール「Bower」

 Bowerは、パッケージ管理ツールの一種で、ライブラリの依存性を解決しつつ、パッケージのインストール/アンインストールを自動化します。パッケージ管理ツールというと、NuGet(.NET Framework)、そして、先ほども登場したnpm(Node.js)がありますが、ASP.NET 5では、それぞれを目的に応じて使い分けるのが基本です。

パッケージ管理ツールの使い分け
パッケージ管理ツール 目的
Bower クライアントサイド開発のためのライブラリ
npm クライアントサイド開発のためのツール類(Grunt、Jasmineなど)
NuGet サーバーサイド開発のためのライブラリ/ツール

 以前のASP.NETでは、NuGetでJavaScriptライブラリも管理していましたが、ASP.NET 5では、JavaScript界隈でより一般的に使われているBowerを利用することになります。

 具体的な例として、以下ではBowerを利用して、JavaScriptフレームワークであるAngularJSをインストールしてみます。

[1]bower.jsonを準備する

 npmでのpackage.jsonに相当するのが、bower.jsonです。[新しい項目の追加]ダイアログから「Bower 構成ファイル」を選択し、新規に作成してください。bower.jsonの骨組みが生成されますので、以下のようにインストールすべきパッケージを「パッケージ名: バージョン番号」の形式で列挙します。実際に入力してみれば、先ほどと同じようにパッケージ名/番号に対して、インテリセンスが働くことが確認できるはずです。

リスト3 bower.json
{
  "name": "ASP.NET",
  "private": true,
  "dependencies": {
    "angular": "~1.4.3"
  }
}

[2]パッケージをインストールする

 npmの時と同じく、登録されたパッケージは/依存関係/Bowerフォルダーに反映され、bower.jsonが保存されたタイミングでインストールされます。

インストール済みのパッケージを確認
インストール済みのパッケージを確認

 パッケージの実体は、プロジェクトルート配下の/wwwroot/libフォルダーです。インストールしたパッケージ名に応じてフォルダーができており(ここでは/angularフォルダー)、その配下にライブラリファイルが配置されていることが確認できます。

ライブラリの実体は/libフォルダーに保存
ライブラリの実体は/libフォルダーに保存

NuGetパッケージの管理

 npmのpackage.json、Bowerのbower.jsonと同じく、NuGetパッケージはproject.jsonで管理します。本稿のサンプルアプリを開くと、project.jsonのdependenciesキーには、Microsoft.AspNet.Mvc/EntityFramework.SqlServerをはじめ、いくつかのパッケージが登録されていることが確認できるはずです。

project.jsonの中身
project.jsonの中身

 project.jsonでは、NuGetパッケージのほか、アプリの実行に関わる諸情報全般を管理します。例えば、アプリの公開フォルダーを変更するならば、webrootキーを編集してください。ASP.NET 5では、従来のweb.configのようなXML形式の設定ファイルがなくなり、代わりにJSON形式のファイルを中心に使われるようになっているのも大きな特徴です。

JavaScriptフレームワークのデファクトスタンダード「AngularJS」

 アプリにおけるJavaScriptの守備範囲が広くなると、おのずと、アプリの共通的な基盤を提供するフレームワークの存在は、欠かせないものです。実際、JavaScriptでは、近年、Backbone.js、Knockout.js、Ember.jsなど、あまたのフレームワークがしのぎを削っていますが、Visual Studio 2015では、その中でも特によく利用されているAngularJSReactを標準でサポートしており、より効率よく開発を進められるようになりました。

 本稿でも、AngularJSを利用して、あらかじめ用意しておいたWeb API経由で記事情報を編集/参照してみましょう。なお、AngularJSの基本的な構文については、別稿『AngularJSではじめるJavaScriptフレームワーク開発スタイル』などを参照してください。

[1]テンプレートを作成する

 ASP.NET 5では、エンドユーザーに対して開示すべきリソースは/wwwrootフォルダーに配置するのでした。[新しい項目の追加]ダイアログから「HTMLページ」を選択し、ファイル名は「index.html」としておきます。

 ページの骨組みが生成されますので、以下のように編集しておきます。マークアップを編集する際に、ng-~ではじまるAngularJSに対しても、インテリセンスが働き、適切なディレクティブを候補表示する点に注目してください。

AngularJSのディレクティブにもインテリセンスが有効に
AngularJSのディレクティブにもインテリセンスが有効に
リスト4 index.html
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="utf-8" />
<title></title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-messages.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-resource.min.js"></script>
<script src="scripts/app.js"></script>
</head>
<body ng-controller="MyController">
<table class="table">
<tr>
  <th>タイトル</th><th>公開日</th><th>PV</th><th>編集/削除</th>
</tr>
<!--取得した記事情報articlesを一覧表示-->
<tr ng-repeat="article in articles">
  <td><a ng-href="{{article.Url}}">{{article.Title}}</a></td>
  <td>{{article.Published | date}}</td>
  <td>{{article.PageView}}</td>
  <td>
    <button ng-click="onedit(article.Id)">編集</button>
    <button ng-click="ondelete(article.Id)">削除</button>
  </td>
</tr>
</table>
<hr />
<form name="myForm" novalidate ...>
  <div>
    <label for="url">URL:</label><br />
    <!--必須/URLフォーマット検証-->
    <input id="url" name="url" type="url" size="50"
      required ng-model="article.Url" />
    <span ng-messages="myForm.url.$error">
      <span ng-message="required">入力は必須です。</span>
      <span ng-message="url">正しいURLを入力してください。</span>
    </span>
  </div>
  <div>
    <label for="title">タイトル:</label><br />
    <!--必須/文字列長検証(5~150文字)-->
    <input id="title" name="title" type="text" size="50"
      ng-model="article.Title"
      required ng-minlength="5" ng-maxlength="150" />
    <span ng-messages="myForm.title.$error">
      <span ng-message="required">入力は必須です。</span>
      <span ng-message="minlength, maxlength">
        5~150文字の範囲で入力してください。</span>
    </span>
  </div>
  <div>
    <label for="published">公開日:</label><br />
    <!--必須/日付型検証-->
    <input id="published" name="published" type="date"
            required ng-model="article.Published" />
    <span ng-messages="myForm.published.$error">
      <span ng-message="required">入力は必須です。</span>
      <span ng-message="date">正しい日付形式で入力してください。</span>
    </span>
  </div>
  <div>
    <label for="pageview">ページビュー:</label><br />
    <!--必須/最小値検証(0以上)-->
    <input id="pageview" name="pageview" type="number"
            required  min="0" ng-model="article.PageView" />
    <span ng-messages="myForm.pageview.$error">
      <span ng-message="required">入力は必須です。</span>
      <span ng-message="number, min">正数で入力してください。</span>
    </span>
  </div>
  <div>
    <button ng-click="oninsert()">登録</button>
    <button ng-click="onupdate()">更新</button>
  </div>
</form>
</body>
</html>

 テンプレートの後半は記事情報を編集するためのフォームです。HTML5でおなじみのrequired/min/max属性はもちろん、AngularJSのng-minlength/ng-maxlength/ng-patterなどの属性(ディレクティブ)を利用することで、検証機能を備えたリッチな入力フォームを、ごくシンプルなコードで実装できます。

Contents Delivery Network

 前項では、説明の便宜上、Bowerを使ってAngularJSをインストールしてみました。しかし、AngularJSのようにCDN(Contents Delivery Network)で提供されているならば、サンプルのように、まずはそちらを優先して利用すべきです。というのも、CDNを利用することで、複数のサイトで同じライブラリを利用している場合、ブラウザキャッシュが働きますので、トラフィックそのものを抑えられる可能性があるからです。

[2]コントローラーを作成する

 テンプレートで利用している記事情報、記事取得/更新のためのロジックは、コントローラーで準備します(注2)。

 JavaScriptのソースコードは、先ほどGruntのuglifyタスクで設定した/Scriptsフォルダーの配下に配置します。[新しい項目の追加]ダイアログから「$scope を使用する AngularJS Controller」を選択し、ファイル名はここでは「controller.js」としておきます。

 AngularJSを利用したコントローラーの骨組みが生成されますので、以下のように編集しておきましょう。

注2

 本来であれば、ビジネスロジックの記述はサービスに委ねるべきですが、本稿では簡単化のためにコントローラーでまとめて記述しています。

リスト5 controller.js
(function () {
  'use strict';

  angular.module('myApp', ['ngResource', 'ngMessages'])
    .controller('MyController', ['$scope', '$resource', function ($scope, $resource) {
      // (2)すべての記事情報をバインド
      var databind = function () {
        $scope.articles = Article.query();
      };

      // (1)指定されたエンドポイントをもとにResourceオブジェクトを生成
      var Article = $resource(
          '/api/Articles/:id',
          { id: '@Id' },
          { ...中略...
            update: { method: 'PUT' }
          }
        );
      databind();

      // (3)[登録]ボタンでフォームの内容を保存
      $scope.oninsert = function () {
        delete $scope.article.Id;
        Article.save(
          $scope.article,
          function() {
            databind();
          });
      };

      // [編集]ボタンで該当する行の記事情報をフォームに表示
      $scope.onedit = function (id) {
        $scope.article = Article.get({ id: id },
          function () {
            console.log($scope.article);
          });
      };

      // (4)[更新]ボタンでフォームの内容に従って記事情報を更新
      $scope.onupdate = function() {
        Article.update(
          $scope.article,
          function() {
            databind();
          });
      };

      // [削除]ボタンで該当する行の記事情報を削除
      $scope.ondelete = function(id) {
        Article.delete(
          { id: id },
          function() {
            databind();
          });
      };
    }]);
})();

 $resourceサービスは、いわゆるRESTサービスへのアクセスを担当するサービス。それ単体でも高機能なサービスですが、ASP.NET Web APIとの相性の良さは特筆すべきものがあります。というのも、(1)のようにWeb APIのエンドポイントを渡すだけで、ASP.NET Web APIにアクセスするためのResourceオブジェクトが生成できます。Resourceオブジェクトは、デフォルトで以下のようなメソッドを提供しますので、$resourceサービスを利用することで、非同期通信を一切意識することなく(単なるメソッド呼び出しで)、ASP.NET Web APIにアクセスできるというわけです。

Resourceオブジェクトの主なメソッド(注3
メソッド HTTPメソッド アクセス先URI 概要
query GET /api/articles 複数のデータを取得(戻り値は配列)
get GET /api/articles/:id 単一のデータを取得(戻り値は単一のオブジェクト)
save POST /api/articles 新規にデータを登録
update PUT /api/articles/:id 既存のデータを更新
delete DELETE /api/articles/:id 既存のデータを削除

注3

 正しくはHTTP PUTを利用したupdateメソッドだけは、明示的に追加しなければなりません。しかし、わずかにメソッド名と対応するHTTPメソッドを宣言するだけなので、手間はほぼゼロと言って良いでしょう。

 あとは、例えば(2)のようにqueryメソッドを呼び出すことで、記事情報の一覧を取得できます。この際、非同期処理特有のコールバック関数すら意識しなくて良い点にも注目です。AngularJSが$scope変数の変化を受けて、その結果をビューに動的にバインドしてくれるからです。

 データの登録/更新の手順もシンプルです。先ほどテンプレートで「article.プロパティ名」の形式で入力値をバインドしていましたので、$scope.articleには

{
  "Url":"http://codezine.jp/article/detail/8765",
  "Title":"Web開発ライブラリを自動的に入手できるパッケージ管理ツールBower",
  "Published": "2015-08-07T00:00:00.000Z",
  "PageView":5700
}

のようなハッシュができているはずです。このハッシュをそのままpost/updateメソッド((3)(4))に渡すことで、記事情報をまるっとサーバー側のデータモデル(ここではArticleエンティティ)にもバインドできるのです。これは便利ですね。

[3]サンプルを実行する

 以上で、クライアントサイドの準備は完了です。ボタンからサンプルを実行して、以下のようなアプリが起動し、記事情報を編集/参照できることを確認してください。

 

サンプルアプリの実行画面
サンプルアプリの実行画面

まとめ

 以上、駆け足でしたが、Visual Studio 2015環境でシングルページアプリケーションを開発する流れを追ってみました。Visual Studioというと、マイクロソフト発の技術に特化しているというイメージが、まだまだ強い人もいるかもしれません。

 しかし、すでに5~6年以上前から、その傾向は明らかに変化してきています。ASP.NET領域だけを見ても、jQuery/Bootstrapの標準サポートにはじまり、AngularJS/React、Grunt/Gulp、Bowerなどなど、さまざまな優れた技術に対して門戸を開き、より優れた環境を貪欲に追及しているように見えます。今後もその流れは加速していくと思われ、ますます進化していくであろうASP.NET+Visual Studioの未来に、著者自身もワクワクしながら注目しています。

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • WINGSプロジェクト(ウイングスプロジェクト)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XMLD...

All contents copyright © 2005-2019 Shoeisha Co., Ltd. All rights reserved. ver.1.5