JSPMで始めるWEB開発


jspmはSystemJSをローダーとした、ライブラリ管理、Transpile、パッケージングを一つにまとめたシステムの事。
Webpackみたいなもん。

ウィザード的な使い方ではなく、一般的な利用方法を説明。
迷わないように、気にしなくても良い部分は割愛。

jspmインストール

npm install -g jspm
npm install jspm --save-dev

jspmの初期化

jspm init

jspmのセットアップ。設定ファイルの中身をインタラクションで作成してくれる。
以下は全てデフォルトで指定した時の中身。

System.config({
  baseURL: "/",
  defaultJSExtensions: true,
  transpiler: "babel",
  babelOptions: {
    "optional": [
      "runtime",
      "optimisation.modules.system"
    ]
  },
  paths: {
    "github:*": "jspm_packages/github/*",
    "npm:*": "jspm_packages/npm/*"
  },
  map: {
    色々書いてる。
  }
}

JSPM 設定ファイルについて

baseURL

baseURLは、SystemJSがファイルをロードする際の基準となるhttpのパス

baseURLが「/foo」で

import 'path/hoge'

とした場合に、合成されたパスは「http://xx.xx.xx.xx/foo/path/hoge.js」となる。
(なぜ拡張子がjsになるかは後程)

Babelオプション

Transpilerとなるbabelのオプションで、ES7のデコレータ機能を有効にするには以下の様にする。

babelOptions: {
  "optional": [
    "runtime",
    "optimisation.modules.system",
    "es7.decorators"
  ]
},
paths

pathsの設定は、デフォルトのパスが気に入らない限りは変更しなくても良い。
意味としては[npm:][github:]で始まるパスを変換する為のルールづけ。

変更したい場合は[package.json]のjspmに

  "jspm" {
    "directories": {
      "packages": "配置したいパス"
    }
  }

と設定し[jspm init]を呼び出すと、新しいパスに配置してくれる。
pathsを変更しても、jspmコマンドを呼ぶたびに上書きされるので無駄!

map

mapの中身は基本的に気にしなくても良い。jspm install等でどんどん変更されていく。

jspmでのライブラリ管理

Clientサイドのライブラリは全てjspmで管理

jspm install <packagename>

基本的には、jspmが管理しているリポジトリからの導入となる。
ただ、npmで管理されているライブラリはほぼ全て導入可能。
その場合は「jspm install npm:」とする。

githubの物も利用できるが、場合によっては導入に多少の修正が必要な事も。
ちなみに「jspm install github:

開発時にのみ必要なライブラリは[--dev]オプションを利用する。

インストールされたPackage等は、package.jsonの「jspm」以下に記録されている。

jspmでのBundlePackage作成

jspm bundle-sfx <application main js path> <output js file path> --minify

gulpとProcessHtml

ProcessHtml

Bundle時とそうではない場合で、読み込むScriptを変える必要があるので、それをPrcessHtmlに処理させる。

エントリーポイントとなるjsは[main.js]で、Bundle後の名前が[main.bundle.js](bundle-sfx)とした場合。

Bundle前

<script src="jspm_packages/system.src.js"></script>
<script src="config.js"></script>
<script>
  System.import("./main.js");
</script>

Bundle後

  <script src="./main.bundle.js"></script>


ProcessHtmlでBundle後に切り替えさえる。

<!-- build:remove -->
<!-- This part will be delete in product version -->
<script src="jspm_packages/system.src.js"></script>
<script src="config.js"></script>
<script>
  System.import("./main.js");
</script>
<!-- /build -->
<!-- build:template
  <script src="./main.bundle.js"></script>
/build -->


こうする事で、Bundle前はProcessHtml前の物を読み、Bundle後はProcessHtml後の物を読むようにすればよい。

Gulp

必要npmパッケージ(yargsはおまけ)

    "gulp": "^3.9.1",
    "gulp-jspm": "^0.5.8",
    "gulp-processhtml": "^1.1.0",
    "gulp-sourcemaps": "^1.6.0",
    "yargs": "^4.6.0"

以下はサンプル。gulp-jspmを利用している。(minifyが無いので自分でやってね)

var gulp = require('gulp')
var yargs = require('yargs').argv
var gulp_jspm = require('gulp-jspm')
var sourcemaps = require('gulp-sourcemaps')
var processhtml = require('gulp-processhtml')
var processopts = { /* plugin options */ }

gulp.task('default', [ 'build' ])

gulp.task('bundle' , function () {
  return gulp.src(<main.jsをピックアップするように設定>)
    .pipe(sourcemaps.init())
    .pipe(gulp_jspm({selfExecutingBundle: true})) // `jspm bundle-sfx main`
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('build/'))
})

gulp.task('processHtml', function () {
  return gulp.src(<index.htmlをピックアップするように設定>)
    .pipe(processhtml(processopts))
    .pipe(gulp.dest('build/'))
})

gulp.task('build', [ 'bundle', 'processHtml' ])

jspmで作るWebページのテンプレ

reactを利用する目的で、divを一つ配置している。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>テンプレート</title>
</head>

<body>
  <div id="root"></div>
</body>

<!-- build:remove -->
<!-- This part will be delete in product version -->
<script src="jspm_packages/system.src.js"></script>
<script src="config.js"></script>
<script>
  System.import("./main.js");
</script>
<!-- /build -->
<!-- build:template
  <script src="./main.bundle.js"></script>
/build -->

</html>

main.jsのおまけテンプレート

import 'jquery'

$(function () {
  //DO SOMETHING
})

POCOライブラリの準備

POCOのダウンロード

Ver1.7.3の話し。
ここからソースコードをダウンロードして任意の場所に展開。
ここでは「c:\poco」とする。

http://pocoproject.org/index.html

Libの作成

前提条件として、VisualStudio2015 Communityがインストール済みとする。(VS 14.0 Update1)
展開したフォルダにある「c:\poco\buildwin.cmd」を使ってビルドする。

buildwin.cmdを引数無しで実行すると、指定できる引数のヘルプが表示される。
ここでは以下のコマンドでビルドした。

buildwin.cmd 140 build all both x64 nosamples notests msbuild

「c:\poco\bin64」にビルドしたdll「c:\poco\lib64」にlibやらが出来上がる。

Projectの設定

追加ライブラリディレクトリに「c:\poco\lib64」を追加。

利用したい機能に合わせて、includeディレクトリを追加

基本ライブラリ「c:\poco\Foundation\include」
ネットワーク「c:\poco\Net\include」

等々

必要なdllを「c:\poco\bin64」からコピーして実行バイナリのある位置に配置

Windows7+.NET Coreの開発環境を作ってビルドして実行

まずはdnvmをインストール

本家の情報を参考に、dnvmをインストールする。(dnvmは「Dot Net Version Manager」の略だそうな)

https://github.com/aspnet/home

以下インストールコマンドの例(記事作成時)

@powershell -NoProfile -ExecutionPolicy unrestricted -Command "&{$Branch='dev';iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/aspnet/Home/dev/dnvminstall.ps1'))}"

dnvmを使ってdnx/dnuを取得し、使えるようにする。
dnxはクロスプラットフォームな.netの実行環境的な奴(nodeコマンドみたいなあれ)
dnuは.NETランタイムのライブラリを復元して実行環境を復元する奴(npmコマンドみたいなあれ)
dnuはビルドやパッケージングも兼ねてる。

以下のコマンドでとりあえず、最新のランタイムを使う設定

dnvm upgrade
dnvm use default

RegistryViewが云々のエラーが出る場合

RegistryViewが云々のエラーが出る場合は、PowerShellのバージョンを更新する必要がある。

Invoke-Command : Unable to find type [Microsoft.Win32.RegistryView]: make sure that the assembly containing this type is loaded.
発生場所 C:\Users\XXXXXXXX\.dnx\bin\dnvm.ps1:1459 文字:27
+             Invoke-Command <<<<  ([ScriptBlock]::Create("dnvm-$cmd $cmdargs"))
    + CategoryInfo          : InvalidOperation: (Microsoft.Win32.RegistryView:String) [Invoke-Command]、RuntimeException
    + FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.InvokeCommandCommand

Windows Management Framework 4.0
https://www.microsoft.com/ja-jp/download/details.aspx?id=40855

.Net Framework 4.5.1以降

入れてない人は入れておく!
4.6 Preview (4.5.3)でも良い。

プロジェクトをビルド及び実行する環境復元

project.jsonから関係ライブラリを復元

dnu restore

ビルドしてみる

dnu build -quiet

project.jsonのframework指定が2つある人は、ここで二つともビルドされる。長い!って思う人は、片方消せばいいと思うよ。

"frameworks": {
  "dnx451": { },
  "dnxcore50": { }
}

dnx451は.Net Framework 4.5.1用で、dnxcore50は.Net Core用。

quietは依存ライブラリの表示を黙らせるオプション。毎回うざい。

ここでエラーが出なければ、次は実行とか。

ASP.NETなどの場合で、bowerとかgluntする

nodeインストール

インストールしてね。

Package.jsonから復元

Package.jsonが置かれているディレクトリに移動した後以下を実行

npm install

gulpやらbowerやらする。

git://が繋がらない場合

gitプロトコルの利用するポートがふさがれている場合は、以下を実行

git config --global url."https://".insteadOf git://

http://stackoverflow.com/questions/15669091/bower-install-using-only-https

実行

project.jsonの設定に従って、dnxで起動する。
今回のproject.jsonには以下のコマンドが定義されている物とする。

    "commands": {
        "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000"
    },

dnxを使って起動

dnx . web

[.]はproject.jsonの場所を表してます。

[dnx . web] でエラーが出る場合

VisualStudio2015をインストールしない場合において、WEB系ソフトの実行時に以下の様なエラーが出る事がある。

System.MissingMethodException: メソッドが見つかりません: 'Int32 System.Runtime.InteropServices.Marshal.SizeOf(!!0)'
   場所 Microsoft.Net.Http.Server.WebListener.SetRequestQueueLimit()
   場所 Microsoft.Net.Http.Server.WebListener.Start()
   場所 Microsoft.AspNet.Server.WebListener.MessagePump.Start(Func`2 app)
   場所 Microsoft.AspNet.Server.WebListener.ServerFactory.Start(IServerInformation server, Func`2 app)
   場所 Microsoft.AspNet.Hosting.HostingEngine.Start(HostingContext context)
   場所 Microsoft.AspNet.Hosting.Program.Main(String[] args)

この場合はdnvmでCoreCLRを使ったランタイムに切り替えると、上手く動くかもしれない。
(自分の場合は上手くいった。)

dnvm install -r coreclr -arch x64 latest

「ASP.NET 5」が動くDockerコンテナを作る

基本的な手順はここを参考にする。

Running ASP.NET 5 applications in Linux Containers with Docker - .NET Web Development and Tools Blog - Site Home - MSDN Blogs


ASP.NET 5のサンプルコードを落としてくる。
ちなみに、本文中のGithubのサンプルでも良いが、本家の物でも良い。

本家
aspnet/Home · GitHub

$git clone https://github.com/aspnet/Home.git aspnet-home

samplesのHelloWebの中にcdしてDockerfileを作成する。
Dockerfileの中身がブログの本文とか異なるので、コメントに書いてあった物を利用する。

FROM microsoft/aspnet

COPY . /app
WORKDIR /app

RUN ["dnu", "restore"]

EXPOSE 5004

ENTRYPOINT ["dnx", "project.json", "kestrel"]

以下のコマンドでDockerのイメージを作成。

$docker build -t myapp .

イメージが出来たらDocker起動。

$docker run -t -d -p 80:5004 myapp

dockerのhostOSのアドレスにポート80でアクセスして、青い画面が見えたらOK。

作ったdockerコンテナにログインする(bashを起動する)するには以下のコマンドを実行

$docker exec -i -t <<コンテナ名 or ID>> bash

Vagrant+AtomicHostでDockerのhostとなる環境を作る

DockerのHostOSとして、AtomicHostのCentOS版を使用

http://www.projectatomic.io/

ProjectAtomicで提供されているVagrantのBoxイメージを利用する

$vagrant box add AtomicHost http://buildlogs.centos.org/rolling/7/isos/x86_64/CentOS-7-x86_64-AtomicHost-Vagrant-VirtualBox.box

$vagrant init Atomithost

適当に、Vagrantfileのネットワークの設定やら色々したあと、upとsshする
rsync」を求められるので、cygwinなりにはsetupしておく事。

これでDockerコマンドが使える環境が整う。