クロコめも2。

ただのめもー

TypescriptとVue.js 1.0系とwebpackと

TypeScriptプロジェクト作成メモ

このメモについて

まだtypescriptについての予備知識はないので基本トライアンドエラー

最終目標目標設定

以下の条件の最小限の開発環境の準備

  • typescript
  • vue.js 1.0系
  • webpack
  • sass

プロジェクトのフォルダ作成

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
npm i -D webpack style-loader css-loader sass-loader ts-loader tsd tslint-loader mocha mocha-loader chai vue html-loader
cp ./node_modules/tslint-loader/node_modules/tslint/docs/sample.tslint.json ./tslint.json
// ターミナルで定義ファイルのインストール
tsd init
tsd install vue --save
tsd query require -so -a install

簡単なビルドができるようになるために

webpack.config.jsを作成

module.exports = {
    entry: {
        app: "./src/assets/js/entry.js"
    },
    output: {
        path: './build/js',
        publicPath: '/js/',
        filename: "[name].js"
    },
    devtool: "source-map", // source-mapを生成する
    module: {
        preloaders: [
            {
                test: /\.ts$/,
                loader: "tslint"
            }
        ],
        loaders: [
            {
                test: /\.scss$/,
                loader: "style!css!sass"
            },
            {
                test: /\.html$/,
                loader: "html"
            },
            {
                test: /\.ts$/,
                loader: "ts"
            }
        ]
    },
    resolve: {
        // require()するときに拡張子を省略可能にします
        extensions: ['', '.js', '.scss', '.ts']
    }
};

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

console.log("hello");

ターミナルでwebpackを実行 -> build/jsにapp.jsができていることを確認する
/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を起動してプレビュー url: http://localhost:8080/webpack-dev-server/

webpack-dev-server --content-base build/ -d
// コンソールで"hello"の文字が出力されてればここまでOK

vue.jsを入れてってみよう

src/assets/js/entry.tsを書き換えてwebpack-dev-serverでプレビューしてみる

/// <reference path="../../../typings/tsd.d.ts" />
console.log("hello");

var Vue = require('vue');

new Vue({
    el: "#app",
    data: {
        msg: "message"
    },
    template: "<p>hoge{{msg}}</p>"
});

TODOアプリがちゃんと動くようにする

IntelliJ->Preferences->Languages & Frameworks->Typescript->command line options

ここに「--sourcemap --noImplicitAny --target es5 --module commonjs」と入れる

Error:Error has occurred in the compile process TypeError: host.fileExists is not a function
このエラーがどうやっても取れない。どうすればいいんだろう???????
IntelliJ->Preferences->Languages & Frameworks->Typescript->Compiler version をカスタマイズすると下の問題に遭遇することがあるようです。
当方はtypescript をbundleされている1.4から1.6.2にあげたら起きました。

github.com

TODOアプリの実装をする(コピペするだけ)

build/index.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>sample</title>
    <style>
        .done-true{
            color: gray;
            text-decoration: line-through;
        }
    </style>
</head>
<body>
    <div class="todoapp">
        <h1>vue & typescript</h1>
        <p>Finish Task: {{getDoneCount}} / {{ tasks.length}}</p>
        <button @click="deleteDone">Delete Finished</button>
        <ul>
            <li v-for="task in tasks">
                <input type="checkbox" v-model="task.done" />
                <span class="done-{{task.done}}">{{$index}}:{{task.body}}</span>
                <a href="#" @click="deleteTask($index)">[x]</a>
            </li>
        </ul>
        <form onsubmit="return false;" @submit="addNew">
            <input type="text" v-model="newTaskBody" />
            <input type="submit" value="add">
        </form>
    </div>
    <script type="text/javascript" src="js/app.js" charset="utf-8"></script>
</body>
</html>

src/assets/js/entry.ts

/// <reference path="../../../typings/tsd.d.ts" />

import Vue = require('vue');

interface ITask {
    body: string;
    done: boolean;
}

class TodoApp extends Vue {
    tasks:ITask[];

    newTaskBody = '';

    constructor() {
        super(false);

        this._init({
            el: '.todoapp',
            data: {
                tasks: this.tasks,
                newTaskBody: this.newTaskBody
            },
            computed: {
                getDoneCount: this.getDoneCount
            },
            created: () => {
                this.tasks = [
                    {body: 'do this 1', done: false},
                    {body: 'do this 2', done: false},
                    {body: 'do this 3', done: false},
                    {body: 'do this 4', done: false}
                ]
            },
            methods: {
                addNew: this.addNew,
                deleteTask: this.deleteTask,
                deleteDone: this.deleteDone
            }
        });
    }

    addNew():void {
        console.log("addNew");
        var task:string = this.newTaskBody && this.newTaskBody.trim();
        if (!task) {
            return;
        }
        this.tasks.push({body: task, done: false});
        this.newTaskBody = '';
    }

    deleteTask(delIndex:number):void {
        console.log("deleteTask");
        this.tasks.splice(delIndex, 1);
    }

    deleteDone():void {
        console.log("deleteDone");
        var oldTasks = this.tasks;
        this.tasks = [];

        oldTasks.forEach(task => {
            if (!task.done) this.tasks.push(task);
        });
    }

    getDoneCount():number {
        var count = 0;
        this.tasks.forEach(task => {
            count += task.done ? 1 : 0;
        });
        return count;
    }
}

export var todoApp = new TodoApp();

webpack-dev-serverを起動して動作を確認する -> 動いていればOK

これからのこのメモに関するTODO

  • モジュールをちゃんと分割してみる
  • sassの設定
  • ハシゴはずされるかもしれないけどvue-routerでroutingしてみたい