クロコめも2。

ただのめもー

Vue2系とTypescript2系

本格的にTypescriptを勉強したいし、何か作りたいんだけど、何をどう初めていいのかよくわからない今日この頃。

  • vue2系
  • typescript2系
  • webpack 2系
  • nodeは確か7系で検証
  • .vueファイルを使っとこう
  • sassを使っとこう
  • vuexはあとにしとこう
  • vue-routerはいらないかな
  • SSRっていまいち何がしたいのかわかってない

ってな感じで雛形ってみた。 参考にさせてもらったのは

Vue.jsとTypeScript - Qiita

GitHub - Microsoft/TypeScript-Vue-Starter: A starter template for TypeScript and Vue with a detailed README describing how to use the two together.

自分で色々触りながら理解を深めるための雛形としてメモを残そうと思います。

はい、完全に自分用。WEBに漂うゴミっす。

setup step

1. yarn init

2. add lib to dev

    yarn add -D css-loader extract-text-webpack-plugin html-webpack-plugin node-sass sass-loader ts-loader typescript
    vue-template-compiler vue-template-loader webpack tslint-language-service vue-ts-plugin vue-loader file-loader url-loader

3. add lib

    yarn add tslib vue vue-class-component vue-property-decorator vuex vuex-class

4. create template.html

        <html lang="ja">
            <head>
                <meta charset="UTF-8">
                <title>Vue Type 君</title>
            </head>
            <body>
                <div id="app"></div>
            </body>
        </html>

5. create tsconfig.json

    {
        "compilerOptions": {
            "module": "es2015",
            "moduleResolution": "node",
            "target": "es5",
            "noImplicitAny": true,
            "sourceMap": true,
            "strictNullChecks": true,
            "typeRoots": [
                "./node_modules/@types"
            ],
            "lib": [
                "dom",
                "es5",
                "es2015"
            ],
            "noEmitHelpers": true,
            "experimentalDecorators": true,
            "importHelpers": true,
            "allowSyntheticDefaultImports": true,
            "emitDecoratorMetadata": true,
            "plugins": [
                {
                    "name": "tslint-language-service"
                },
                {
                    "name": "vue-ts-plugin"
                }
            ]
        },
        "include": [
            "./src/**/*"
        ]
    }

6. create tslint.json

    {
        "defaultSeverity": "error",
        "extends": [
            "tslint:recommended"
        ],
        "jsRules": {},
        "rules": {
            "quotemark": [
                true,
                "single"
            ],
            "indent": [
                true
            ],
            "interface-name": [
                false
            ],
            "arrow-parens": false,
            // Pending fix for shorthand property names.
            "object-literal-sort-keys": false
        },
        "rulesDirectory": []
    }

7. create webpack.config.js

    var path = require("path");
    var webpack = require("webpack");
    const HTMLWebpackPlugin = require('html-webpack-plugin')
    const ExtractTextPlugin = require('extract-text-webpack-plugin')

    module.exports = {
    entry: "./src/index.ts",
    output: {
        path: path.resolve(__dirname, "./dist"),
        filename: "build.js"
    },
    module: {
        rules: [
        {
            test: /\.tsx?$/,
            loader: "ts-loader",
            exclude: /node_modules/,
            options: {
            appendTsSuffixTo: [/\.vue$/]
            }
        },
        {
            test: /\.vue$/,
            loader: "vue-loader",
            options: {
            loaders: {
                scss: ExtractTextPlugin.extract({
                use: ['css-loader', 'sass-loader'],
                fallback: 'vue-style-loader' // <- this is a dep of vue-loader, so no need to explicitly install if using npm3
                })
            }
            // other vue-loader options go here
            }
        },
        {
            test: /\.(png|jpg|gif|svg)$/,
            loader: "file-loader?name=assets/[name].[ext]"
        }
        ]
    },
    resolve: {
        extensions: [".ts", ".js", ".vue", ".json"],
        alias: {
        vue$: "vue/dist/vue.esm.js"
        }
    },
    devServer: {
        historyApiFallback: true,
        noInfo: true
    },
    performance: {
        hints: false
    },
    devtool: "#eval-source-map",
    plugins: [
        new HTMLWebpackPlugin({ template: './template.html' }),
        new ExtractTextPlugin('styles.css')
    ]  
    };

    if (process.env.NODE_ENV === "production") {
    module.exports.devtool = "#source-map";
    // http://vue-loader.vuejs.org/en/workflow/production.html
    module.exports.plugins = (module.exports.plugins || []).concat([
        new webpack.DefinePlugin({
        "process.env": {
            NODE_ENV: '"production"'
        }
        }),
        new webpack.optimize.UglifyJsPlugin({
        sourceMap: true,
        compress: {
            warnings: false
        }
        }),
        new webpack.LoaderOptionsPlugin({
        minimize: true
        })
    ]);
    }

    

8. create ./src and ./dist directory

9. create index.ts

    import Vue from "vue";
    import App from "./components/App.vue";

    let v = new Vue({
        el: "#app",
        render: h => h(App)
    });

10. create components/App.vue

    <template>
        <div>
            Name:
            <input v-model="name" type="text">
            <hello-component :name="name" :initialEnthusiasm="5" />
        </div>
    </template>
    <script lang="ts">
    import Vue from "vue";
    import Component from 'vue-class-component'
    import { Prop } from 'vue-property-decorator'

    import HelloComponent from "./Hello.vue";

    @Component<App>({
        components: {
            HelloComponent
        }
    })
    export default class App extends Vue {
        name = 'わたしだ'
    }

    </script>
    <style lang="scss">
    @import '../assets/style/main.scss';
    </style>

11. create components/Hello.vue

    <!-- src/components/Hello.vue -->
    <template>
        <div>
            <div class="greeting">Hello {{name}}{{exclamationMarks}}</div>
            <button @click="decrement">-</button>
            <button @click="increment">+</button>
        </div>
    </template>

    <script lang="ts">
    import Vue from "vue";
    import Component from 'vue-class-component'
    import { Prop } from 'vue-property-decorator'

    @Component<Hello>({
    })
    export default class Hello extends Vue {
        @Prop() readonly name: string;    
        @Prop() readonly initialEnthusiasm: number;

        enthusiasm = this.initialEnthusiasm;

        increment() { this.enthusiasm++; };

        decrement() {
            if (this.enthusiasm > 1) {
                this.enthusiasm--;
            }
        };

        get exclamationMarks(): string {
            return Array(this.enthusiasm + 1).join('!');
        }
    }

    </script>

    <style lang="scss">
    .greeting {
        font-size: 20px;
    }
    </style>    

12. create assets/style/main.scss

    body {
        margin: 0;
        padding: 0;
        font-family: Arial, Helvetica, sans-serif;
        background-image: url("../assets/images/logo.png");
    }

13. create assets/images/logo.png

exec webpack command. check dist directory.