クロコめも2。

ただのめもー

Nightmareさんとこをざっくり訳

英語わかんねっす。

Nightmare

Nightmareはハイレベルな自動ページ表示ライブラリーです。

達成したいことは、ネストが深く分かり難いコールバック地獄なしに下のことを実現する

  • シンプルに書ける
  • 同期処理っぽく書ける

これは、APIを持っていないサイトのE2Eテスト用に設計されています。

Electronベースでできてます。PhantomJSに似てますが、もっと早くてモダンです。

Daydream

Daydreamは@stevenmiller888さんによって作られた、Nightmareを使う際のお助けツール
chromeのエクステンションで、ブラウザ操作でNightmare用スクリプトを生成するものです。

Examples

yahooをサーチしてみよう

var Nightmare = require('nightmare');
var vo = require('vo');

vo(function* () {
    var nightmare = Nightmare({ show: true });
    var link = yield nightmare
        .goto('http://yahoo.com')
        .type('input[title="Search"]', 'github nightmare')
        .click('.searchsubmit')
        .wait('.ac-21th')
        .evaluate(function () {
            return document.getElementsByClassName('ac-21th')[0].href;
        });
    yield nightmare.end();
    return link;
})(function (err, result) {
    if (err) return console.log(err);
    console.log(result);
});

以下のコマンドで実行できます

npm install nightmare vo
node --harmony yahoo.js

もしくは mochaのテストを実行してみましょう:

var Nightmare = require('nightmare');
var expect = require('chai').expect; // jshint ignore:line

describe('test yahoo search results', function() {
    it('should find the nightmare github link first', function*() {
        var nightmare = Nightmare()
        var link = yield nightmare
            .goto('http://yahoo.com')
            .type('input[title="Search"]', 'github nightmare')
            .click('.searchsubmit')
            .wait('.ac-21th')
            .evaluate(function () {
                return document.getElementsByClassName('ac-21th')[0].href;
            });
        expect(link).to.equal('https://github.com/segmentio/nightmare');
    });
});

全機能の例はこっち
https://github.com/segmentio/nightmare/blob/master/test/index.js
※この例はmocha-generatorsを使ってるから注意してね
動かすには

  1. npm install
  2. npm test

API

Nightmare(options)

Web参照できる新しいインスタンスを生成します。
指定できるオプションはこれ
https://github.com/atom/electron/blob/master/docs/api/browser-window.md#new-browserwindowoptions

加えてnightmareのオプションとして

waitTimeout

.wait()が指定の時間までにtrueを返さないとexceptionを投げます。

paths

Electronが使用するデフォルトシステムパス。
下のようにして上書き可能

var nightmare = Nightmare({
    paths: {
        userData: '/user/data'
    }
});

switches

Chromeで使えるコマンドラインスイッチ Electronでサポートしているのは下の通り
https://github.com/atom/electron/blob/master/docs/api/chrome-command-line-switches.md

electronPath

Electronのバイナリを指定。別バージョンのElectronでテストしたいときに使う。

.useragent(useragent)

Electronで使われるuseragentを指定する

.end()

キューを完了し、Electronのプロセスを切断、終了します。

ページ操作

.goto(url

指定したURLのページをロードします。

.back()

バックします。

.forward()

進みます

.refresh()

ページをリフレッシュします。

.click(selector)

指定したセレクタでクリックイベントを発生させます。

.mousedown(selector)

指定したセレクタでマウスダウンイベントを発生させます。

.type(selector[, text])

指定したセレクタに文字入力する。空文字やfalseを設定すると対象のセレクタの値がクリアされる

.check(selector)

指定したチェックボックスセレクタのトグルを切り替える

.select(selector, option)

指定したdropdownセレクタのオプションを変える

.scrollTo(top, left)

スクロールする

.inject(type, file)

指定したフィアルをページにロードする。ロードできるのはjsかcss

.evaluate(fn[, arg1, arg2,...])

指定したfnを指定した引数で実行する。引数はオプショナル。実行終了後にfnの戻り値が戻り値となる。
情報を抜き取るときに便利

var selector = 'h1';
var text = yield nightmare
    .evaluate(function (selector) {
        // now we're executing inside the browser scope.
        return document.querySelector(selector).innerText;
    }, selector); // <-- that's how you pass parameters from Node scope to browser scope

.wait(ms)

指定したミリ秒待つ

.wait(selector)

指定したセレクタが存在するまで待つ(.wait('#pay-button'

.wait(fn[, arg1, arg2,...])

指定したfnがtrueを返すまで待つ

ページから情報を抜き取る

.exists(selector)

指定したselectorが存在するかどうか

.visible(selector)

指定したselectorが表示状態か非表示状態か

.on(event, callback)

ページのイベントを関ししてコールバックを呼ぶ。
.goto()を呼ぶ前に読んでおかないといけない
サポートしているイベントはここ
http://electron.atom.io/docs/v0.30.0/api/browser-window/#class-webcontents

追加されているページイベント

.on('page', function(type="error", message, stack))
このイベントはページで何かしらjavascriptのエラーが起きたときに発火します。
しかし、挿入されたjavascriptコードでは発火しません。(例 .evaluate())そういうときはただの例外

ページのイベント

window.addEventListener('error'), alert(...),prompt(...) とかconfirm(...)を監視します

.on('page', function(type="alert", message))

Nightmareではデフォルトでポップアップのwindow.alertが無効です。
しかし監視できます。

.on('page', function(type="prompt", message, response))

Nightmareではデフォルトでポップアップのwindow.promptが無効です。 しかし監視できます。
もし、異なるものをハンドリングしたい場合は独自のプリロードスクリプトを用意する必要があります。???なんのこっちゃ

.on('page', function(type="confirm", message, response))

Nightmareではデフォルトでポップアップのwindow.promptが無効です。 しかし監視できます。
もし、異なるものをハンドリングしたい場合は独自のプリロードスクリプトを用意する必要があります。???なんのこっちゃ

.on('console', function(type [, arguments, ...]))

typeにはlog,warnもしくはerror、そしてargumantsはコンソールから渡されてくるものです。

.on('console', function(type, errorMessage, errorStack))

このイベントはconsole.logがページ内で使われているときに発火します。しかし、injectされたscriptでは発火しません(例 console.log()の中で.evalute()

.screenshot([path][, clip])

現在ページのスクリーンショットを取ります。デバッグに便利。
出力はpngです。引数はどっちともオプショナルです。
pathが指定された場合、画像を指定のディレクトリに保存します。指定されてないと画像データのバッファを返します。
clipが指定された場合、下にもあるようにイメージが矩形にクリップされます。
https://github.com/atom/electron/blob/master/docs/api/browser-window.md#wincapturepagerect-callback

.pdf(path, options)

指定されたパスにpdfファイルを保存します。細かいオプションについての情報は下
https://github.com/atom/electron/blob/v0.35.2/docs/api/web-contents.md#webcontentsprinttopdfoptions-callback 

.title()

現在ページのタイトルを返却します。

.url()

現在ページのurlを返却します。

クッキー

.cookies.get(name)

指定した名前のクッキーを取得します。対象のurlは現在ページのurlです。

.cookies.get(query)

クエリを使って複数のクッキーを取得します。もしquery.nameが指定された場合、最初に見つかった値、もしくは配列を返します。   query.urlが指定されていない場合は現在urlになります

例)

// get all google cookies that are secure
// and have the path `/query`
var cookies = yield nightmare
    .goto('http://google.com')
    .cookies.get({
        path: '/query',
        secure: true
})

   使えるプロパティは下
https://github.com/atom/electron/blob/master/docs/api/session.md#sescookiesgetdetails-callback

.cookies.get()

現在ページのurlをすべて取得します。

.cookies.set(name, value)

現在ページのクッキーをセットします。

.cookies.set(cookie)

クッキーをセットします。もしcookie.urlが指定されてない場合、現在ページにセットします。
例)

yield nightmare
    .goto('http://google.com')
    .cookies.set({
        name: 'token',
        value: 'some token',
        path: '/query',
        secure: true
})

使えるプロパティ一覧は下
https://github.com/atom/electron/blob/master/docs/api/session.md#sescookiessetdetails-callback

.cookies.set(cookies)

一度に複数cookieをセットします。cookiescookieの配列です。   詳しくは.cookies.set(cookie)

Nightmareの拡張

Nightmare.action(name, action|namespace)

下の例のようにカスタムアクションをNightmareのプロトタイプに追加できます。

例)

Nightmare.action('size', function (done) {
    this.evaluate_now(function() {
        var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0)
        var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0)
        return {
            height: h,
            width: w
        }
    }, done)
})

var size = yield Nightmare()
    .goto('http://cnn.com')
    .size()

注意:これはstatic classに追加してます。Nightmareのインスタンスに追加してるわけじゃないです。
evaluate_nowという処理を読んでいます。これはnightmare.evaluateとは違います。
これは即時に実行されますが、nightmare.evaluateはキューにたまります。

忘れないための簡単な方法は:evaluateについて疑問におもったとき、もしカスタムアクションを作ってるときならevaluate_nowを使ってください
なぜならすでにキューイングされたものを処理している最中に、その処理をまたキューにためてはいけないからです

またカスタムのネームスペースを作ることもできます。
nightmare.cookies.get,nightmare.cookies.setなどで内部でも使っているように
アクションをまとめるのに便利です。しかしnightmareオブジェクトが乱雑になります。

例)

Nightmare.action('style', {
    background: function (done) {
        this.evaluate_now(function () {
            return window.getComputedStyle(document.body, null).backgroundColor
        }, done)
    }
})

var background = yield Nightmare()
    .goto('http://google.com')
    .style.background()

.use(plugin)

nightmare.useは一つのインスタンスでタスクを再利用するのに便利です。
nightmare-swiftlyでサンプルをチェックしてください
https://github.com/segmentio/nightmare-swiftly

Custom preload script

ウィンドウ環境起動時になにかしたいときは、プリロードスクリプトを定義できます。
どうやるかっていうと

var nightmare = Nightmare({
    webPreferences: {
        preload: custom-script.js
    }
})

このプリロードするスクリプトは下の記述を入れておく

window.__nightmare = {};
__nightmare.ipc = require('ipc');

使い方

インストール

NightmareはNodeのmoduleなのでNode.jsは入れておく。
インストールはnpm install で行う

$npm install --save nightmare

実行

Nightmareはnodeのスクリプトやmoduleから利用できる。

例)

var Nightmare = require('../nightmare');
var vo = require('vo');

vo(run)(function(err, result) {
    if (err) throw err;
});

function *run() {
    var nightmare = Nightmare();
    var title = yield nightmare
        .goto('http://cnn.com')
        .evaluate(function() {
            return document.title;
        });
    console.log(title);
    yield nightmare.end();
}

これはcnn.jsとして保存したら下のように実行する

npm install vo nightmare
node --harmony cnn.js

デバッグ

内部で何が起きてるかをしるために3つの方法があります。 1. DEBUG=*デバッグフラグ 1. Nightmareコンストラクタ{show:true}を渡すと実際にウィンドウを表示する 1. specific eventsを監視する(下URL参照)

https://github.com/segmentio/nightmare#onevent-callback

同じテストをデバッグモードで動かすときはDEBUG=nightmare node --harmony cnn.js
windowsなら(set DEBUG=nightmare & node cnn.js

そうすると追加情報が出力されます。

テスト

MochaとChaiを使ってテストします。どっちともnpmでインストールします。
nightmareのテストはmake testで実行します

テストできたら下のように見えます。

make test
    ․․․․․․․․․․․․․․․․․․
    18 passing (1m)

実践Node.jsプログラミングのマルチルームチャットアプリの構築を写経した時のメモ

世界にはまだまだ知らないことだらけ。Node.jsのサーバサイドについても把握せねば。  

環境

  • node v4.2.3
  • mime 1.3.4 (本では1.2.7)
  • socket.io 1.3.7 (本では0.9.6)

単純に動かなかった2点

1点目 chat_server.js l50~l60あたり

//var usersInRoom = io.sockets.clients(room);
// ↑だとclientsなんぞ知らん。というエラーが起きる
var usersInRoom = findClientsSocket(room);

// 以下のメソッドを別途追加
function findClientsSocket(roomId, namespace) {
    var res = []
        , ns = io.of(namespace ||"/");    // the default namespace is "/"

    if (ns) {
        for (var id in ns.connected) {
            if(roomId) {
                var index = ns.connected[id].rooms.indexOf(roomId) ;
                if(index !== -1) {
                    res.push(ns.connected[id]);
                }
            } else {
                res.push(ns.connected[id]);
            }
        }
    }
    return res;
}

2点目 chat_server.js l20~l30あたり

//socket.emit('rooms', io.sockets.manager.rooms);
// ↑だと「TypeError: Cannot read property 'rooms' of undefined」というエラーが起きる
socket.emit('rooms', io.sockets.rooms);

なぜ動かなかったか?

APIが変わったから。
どうやらsocket.ioの1.0になったときにいろいろ変わったらしいですね

ふぅ。

Server側復習

server.js => ほぼstaticなwebサーバに関する記述
chat_server => socket.ioに関するところだけ抜き出して意味を調べてみる

io = socketio.listen(server)

API docsより

 Server#listen
 Synonym of Server#attach.

 Server#attach(srv:http#Server, opts:Object):Server
 Attaches the Server to an engine.io instance on srv with the
 supplied opts (optionally).

engine.ioとはなんぞや?

https://github.com/socketio/engine.io

socket.io用のトランスポート層で双方向通信するための実装ということか?
これをhttpサーバにアタッチすることでリクエストをインターセプトする

io.set('log level', 1);

意図がわからない。log levelを1にするということはログを多くすることなのか?少なくすることなのか?ログを無くしたいのか?
そしてversion1.0以降はなにやら変わっているらしい。このログレベルの設定自体が不要なのか?

http://socket.io/docs/logging-and-debugging/
↓で何やら説明があった。
http://socket.io/docs/migrating-from-0-9/

Options like log-level are gone. ごーん

socket.emit('eventName', obj);

対象のsocketに対してイベントを発火させる。
渡したいものはobjに詰めておく

socket.join(room)

API docsより

Socket#join(name:String[, fn:Function]):Socket
Adds the socket to the room, and fires optionally a callback fn
with err signature (if any).

The socket is automatically a member of a room identified with its
session id (see Socket#id).

The mechanics of joining rooms are handled by the Adapter
that has been configured (see Server#adapter above), defaulting to
socket.io-adapter.

roomに追加してoptionのコールバックを発火。
roomとはなにものか?

デフォルトではセッションID名のroomに自動的に入れられているってことか

socket.leave

joinの反対で良い模様

socket.broadcast.to(room).emit('message', {...})

ブロードキャスト。

そして↓のように書いても動いた。
socket.to(room).emit('message', {...}
違いはなんだろう?

socket.on('イベント名', function(パラメータ){ハンドリング処理});

見ての通りのイベントハンドリング処理の模様

io.of(...)

カスタムのネームスペースを作れるらしい。
デフォルトは"/"

socket.id

API docsより

Socket#id:String
A unique identifier for the socket session, that comes from the
underlying Client.

はい。

Client側復習

io

おもむろに登場するグローバルオブジェクト。

socket.on('イベント名’, function(パラメータ){ハンドリング})

イベントのハンドリング

socket.emit('イベント名', パラメータ)

イベントの発火

クライアントはハンドリングと発火だけなのでシンプル

vuejsの作者さんが考えたvuejsにマッチするflux?

vuexを動かしてみる

動機:githubで見つけて単純にDLして動かそうとしたら動かなかったから

環境メモ

  • babelは5系
  • nodejsは4.2.2
  • npmは3.5
  • .vueファイルを使わない(ただの個人的な好み)

作業順

  1. ディレクトリを作る
  2. npm でいろいろインストール
  3. vuexをプロジェクトの中に
  4. exampleにあるcounterを移植して動かしてみる
  5. testを移植して動かしてみる

[ディレクトリを作る]

# ディレクトリ作成
mkdir プロジェクトのフォルダ
cd プロジェクトのフォルダ
mkdir -p build test src/{components,views,assets/{js,css}}

[npm でいろいろインストール]

# npm で必要なものをあつめてくる
npm init 
npm i -g webpack webpack-dev-server mocha babel-loader@^5.3
npm i -S vue 
npm i -D babel-loader@^5.3 webpack style-loader css-loader sass-loader html-loader mocha mocha-loader chai

[vuexをプロジェクトの中に]

今回は/src/assets/vuexというディレクトリを用意してその中にgithubから持ってきたvuexのsrc配下を入れる

[exampleにあるcounterを移植して動かしてみる]

build/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>vuex counter example</title>
</head>
<body>
<counter></counter>
<script src="js/app.js"></script>
</body>
</html>

src/assets/js/main.js(vuexのexampleのままimportのパスを変えただけ)

import Vue from 'vue'
import Counter from '../../components/counter/index'

new Vue({
  el: 'body',
  components: { Counter }
})

src/assets/js/vuex.js(vuexのexampleのcounter内にあるvuex.jsをそのままもってきてimportのパスだけ変更)

import Vue from 'vue'
import Vuex from '../vuex'

~省略

src/components/counterにCounter.vueを分割して2ファイル
index.js

import vuex from '../../assets/js/vuex'

export default {
    template: require('./template.html'),
    computed: {
        count () {
            return vuex.state.count
        }
    },
    methods: vuex.actions
}

template.html

<div>
    Clicked: {{ count }} times
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
    <button @click="incrementIfOdd">Increment if odd</button>
    <button @click="incrementAsync">Increment async</button>
</div>

サーバを起動して確認

webpack-dev-server -d --inline

http://localhost:8080/

[testを移植して動かしてみる]

testディレクトリにあるtest.jsをそのまま移植してimportのパスだけ直す

mocha --compilers js:babel-core/register

通りました。これでいろいろ試せるかな

見ないふりをしてたけど、eslintを入れて動かすとなんか警告が出る。けどなんの警告だかはわかってない

findConfigFileの引数が変わってます。

完全に元のエントリーの内容残って無いけど、うそんこタイトル残しとくよりマシかな!という判断で書き直し

20151124版のtypescript1.8.0-dev.20151124のfindConfigFileメソッドは第2引数にfileのexistsを確認するための関数を渡さなければいけなくなった。

※具体的にいつのリリースでそういう仕様になったかはわからないけれど、つい最近なんだろうなーと想像

 

そのために、既存のfindConfigFileを利用していたライブラリはそれに対応しないとエラーが発生するようになっている。

 

2015年11月24日時点でespower-typescript-babelを利用しようとすると当該のエラーにぶつかった。

 

findConfigFileメソッドを利用している箇所をルートパス+"tsconfig.json"をセットするように変更してしまえば動いた。けど、ちゃんと対応するなら第2引数にisExistsをわたしてあげないとか?

そもそも1.6系使えば動きそうだからわざわざ1.8の安定してないやつ使う必要がなくなったのでは?


もやもやポイント書き出し

typescriptで開発する際、vueのdataプロパティをどう扱っていいのかわからない。
そのまま使うと動作はするがtypescript上で認識できないものにアクセスすることになるのでコンパイルでエラーが出る。
動いてるからエラーでは無く警告なのか?

なんとかしないと規模の大きい開発には耐えられない。
警告だらけで本当の問題が埋もれるから

TypeScriptでVue.jsを使うサンプル(前半)

【計画】前半と後半に分ける

前半

プロジェクトの作成と簡単なアプリ作成

後半

vue-router組み込み

主要な使用技術

  • TypeScript 1.6.2
  • vue 1.0.8
  • vue-router 0.7.5
  • vue-class-component 2.0.0
  • TypescriptのコンパイルオプションはES6

大まかな手順

  1. プロジェクト作成と環境の準備
  2. TypeScriptまわりの準備
  3. vueの簡単なサンプル作り
  4. vue-router挑戦

プロジェクト作成と環境の準備

# ディレクトリ作成
mkdir プロジェクトのフォルダ
cd プロジェクトのフォルダ
mkdir build
mkdir -p  src/{components,views,assets,directives,filters}
mkdir src/assets/js

# npm で必要なものをあつめてくる
npm init 
npm i -g webpack webpack-dev-server mocha typescript tsd tslint
npm i -S vue vue-class-component vue-router
npm i -D babel-loader@^5.3 webpack style-loader css-loader sass-loader ts-loader html-loader typescript tsd tslint-loader mocha mocha-loader chai

# tsd で必要なものを集めてくる
tsd init
tsd install vue --save
tsd install require --save

# tslint用の定義ファイルをテンプレートからコピってくる。しかしこれ厳しすぎてつらいので適宜ゆるく改修する必要あり
cp ./node_modules/tslint-loader/node_modules/tslint/docs/sample.tslint.json ./tslint.json

webpack.config.jsの作成

module.exports = {
    entry: {
        app: "./src/assets/js/entry.ts"
    },
    output: {
        path: './build/js',
        publicPath: '/js/',
        filename: "[name].js"
    },
    resolve: {
        alias: {
            vue: "vue/dist/vue"
        },
        modulesDirectories: ['node_modules', 'src/', 'src/assets/js/', 'src/views/', 'src/components/'],
        // require()するときに拡張子を省略可能にします
        extensions: ['', '.webpack.js', '.web.js', '.ts', '.tsx', '.js']
    },
    devServer: {
        contentBase: "./build",
    },
    module: {
        preloaders: [
            {
                test: /\.ts$/,
                loader: "tslint"
            }
        ],
        loaders: [
            {
                test: /\.scss$/,
                loader: "style!css!sass"
            },
            {
                test: /\.html$/,
                loader: "html"
            },
            {
                test: /\.ts(x?)$/,
                loader: 'babel-loader?sourceMaps=true!ts-loader'
            }
        ]
    }
};

tsconfig.jsonを作成する

{
  "compilerOptions": {
    "module": "commonjs",
    "removeComments": true,
    "noImplicitAny": false,
    "target": "es6",
    "sourceMap": true,
    "experimentalDecorators": true,
    "preserveConstEnums": true
  },
  "exclude": [
    "node_modules",
    "build"
  ]
}

src/assets/js/にentry.tsを作成

console.log("hello");

/build/index.htmlを作成

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>sample</title>
</head>
<body>
    <div id="app">this is app</div>
    <script type="text/javascript" src="js/app.js" charset="utf-8"></script>
</body>
</html>

ここで一旦、webpack-dev-serverを起動してプレビュー

起動コマンド : webpack-dev-server -d --inline
http://localhost:8080

コンソールにhelloと表示されたらここまでOK

横道:IntelliJ使ってる場合の設定

Preferences->Languages & Frameworks->JavaScript

Preferences->Languages & Frameworks->TypeScript

  • Enable TypeScript Compilerをチェックする(重かったらチェック外してもいいかも)
  • コマンドラインオプション --noImplicitAny --target ES6 --experimentalDecorators
  • generate sourceMapのチェックをはずす。

Preferences->Languages & Frameworks->TypeScript->Tslint

  • プロジェクトのtslint.jsonを設定する

横道から復帰

TypeScriptまわりの準備

typingsの中にあるvue.d.tsの中でexport =とある部分をexport defaultと書き換える
※es6を使うときに怒られちゃうからこれでごまかす。。。

独自定義ファイルディレクトリを作る

mkdir -p custom-typings/vue-class-component

custom-typings/vue-class-component/vue-class-component.d.tsを作る(これでいいのか不明)

declare module "vue-class-component" {
    let VueComponent:ClassDecorator;
    export default VueComponent;
}

custom-typings/custom.d.tsを作る

/// <reference path="vue-class-component/vue-class-component.d.ts" />

vueの簡単なサンプル作り

src/assets/js/entry.tsを書き換え

/// <reference path="../../../typings/tsd.d.ts" />
import Vue from "vue";
require("../sass/main.scss");
new Vue(require("../../views/app"));

src/assets/sass/main.scss作成(てきとー)

body {
  margin: 0px;
  padding: 0px;
}
.main-header {
  margin: 0px;
  padding: 3px;
  background-color: #fafafa;
  border-bottom: 1px solid #CCCCCC;
  text-align: center;
}

.main-footer {
  position: fixed;
  width: 100%;
  margin: 0px;
  padding: 3px;
  background-color: #fafafa;
  border-top: 1px solid #CCCCCC;
  bottom: 0px;
}

src/views/app/index.tsを作成

/// <reference path="../../../typings/tsd.d.ts" />
import Vue from "vue";
import Header from "../../components/header/index";
const app = new Vue({
    el: "#app",
    template: require('./template.html'),
    components: {
        'app-header': Header
    }
});

src/views/app/template.htmlを作成

<app-header></app-header>

src/components/header/index.tsを作成

/// <reference path="../../../typings/tsd.d.ts" />
/// <reference path="../../../custom-typings/custom.d.ts" />
import VueComponent from "vue-class-component";

@VueComponent
export default class Header {
    public static template:string = require("./template.html");

    public ready():void {
        console.log("hogehoge");
    }
}

src/component/header/template.html

<div class="main-header">
    <h3>TypeScript & Vue.js sample</h3>
</div>

サーバを起動して動作確認する。ヘッダーが表示されていればここまでOK

横道2 ChromeのVue Devtoolsについて

能力の無さは積極的にツールでカバーしたい。ということで便利ツールChromeプラグイン「Vue Devtools」
webpackの起動オプションに--inlineを設定してあったり、babel-loaderかますときにsourceMapつけてるのはこのツールを使えるようにするためです。
このプラグインのおかげで表示されているコンポーネントの情報をブラウザで実行時に見ることができます。
chrome上でブレイクポイント置いてステップ実行できるようになるものも相当嬉しい(それはVue Devtoolsの機能じゃないけど)