Vueがメチャメチャ書きやすくなる言語を開発した話

皆様はじめまして、s19514ttと申します。
Vueがメチャメチャ書きやすくなる言語を開発したので、開発に至った経緯やどのようなものなのかのご紹介をさせていただきます。

## 開発のきっかけ

みなさんVueはお好きでしょうか？私は大好きで、よくVueを使って趣味でWebアプリケーションを作っていました。しかし、最初にVueを勉強してからちょっとしたモヤモヤがありました。

言うまでもなくVueはJavaScriptで制作されており記述する際はJavaScript又はTypeScriptを用いて記述します。
しかし、実際はVueと素のJavaScriptやJQueryのコードには大きな差があり、全く別の言語のようとまでは言えないもののJavaScriptを知っている人でもVueを書くために様々な学習が必要になります。例えば、初期値0のcount変数を1つずつincrementで増やすと言うコードを書きたい場合JavaScriptとVueでは以下のように大きく異なったコードになります。

### JavaScriptの例

```javascript
const count = 0;
function increment(){
  count++;
}
```


### Vueの例

```javascript
new Vue({
  el: "#app",
  data() {
    return {
      count: 0
    };
  },
  methods: {
    increment() {
      this.count++;
    },
  }
});
```

全く同じ処理を書いているのにVueの場合かなり長いコードになっているのがわかると思います。
さらに、変数宣言と変数[^1]の場所が固定されていることや、変数をconstなどを使わずオブジェクトのプロパティとして定義するのも、最初Vueを学習した自分にとって衝撃でした。
また、関数も同様にVueで用いる場合はオブジェクトのプロパティとして記述しないといけません。通常のJavaScriptはもちろん他の言語でもこのような仕様の言語はないためVueのコードの大きな癖となってしまい、多くの人にとって書いたり読んだりしやすいコードではないでしょう。
もちろん上のJavaScript例を実際に書いた場合はincrement関数を実行してもcountの値は更新されないためHTMLに反映させたい場合は別途DOM操作を行う必要があります。
ただ私は「今までのJSみたいなコードで自動的にDOM操作できないかな〜」って思っていました。

さらに、TypeScriptを利用するようになってからはそのデメリットをさらに強く感じるようになりました。
Vueで変数を定義する際にTypeScriptだと以下のように書くと思います。

>```typescript
>var Profile = Vue.extend({
>  template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
>  data: function () {
>    return {
>      firstName: 'Walter',
>      lastName: 'White',
>      alias: 'Heisenberg'
>    }
>  }
>})
>
>```
>[Vueの公式ドキュメントより引用](https://jp.vuejs.org/v2/api/index.html)

一見上記は問題のないようなコードに見えると思いますが、`firstName`,`lastName`,`alias`3つの変数は変数が型推論によって決められてしまっています。
もちろん型を指定することもできますが、TypeScriptのオブジェクトで型を指定する場合`as`を用いる必要があり、この書き方に違和感を覚える方も多いと思います。

```typescript
  data: function () {
    return {
      firstName: 'Walter' as string,
      lastName: 'White' as string,
      alias: 'Heisenberg' as string
    }
```

## 実装してみた

以前から思っていたこの問題に対処するために、ライブラリを実装してみました！

その名もVucript(Vue+Script)です！

### セットアップ

1. Vue CliでTypeScriptを使用したプロジェクトを作成する

1. (Vue 2の場合のみ)[このステップに従い](https://qiita.com/kurukuruz/items/3f568cc21d467778ecb8)Composition APIを使用できるようにする

1. コマンドラインにて下記のコマンドを入力しVucriptをインストールする

```bash
vue add vucript
```

1. VueのSFCの言語にVucriptと記述する

```vue
<script lang="vucript">
```

:::note warn
Vucriptを使用する際は必ずIDE等でPrettierによる自動フォーマットをオンにしてください。
:::

### 使用例

先程の例に挙げたカウンターアプリケーションを作ってみましょう！

まず最初にセットアップに従いプロジェクトを作成します。

次にApp.vue以下のようにコードを記述します。

```vue
<template>
  <div>現在の値:{{ counter }}</div>
  <button @click="increment()">1増やす</button>
</template>

<script lang="vucript">
import { reactive } from "vucript";
let counter: reactive<number> = 0;
function increment() {
  counter++;
}
</script>
```

この状態で`npm run serve`を実行してみましょう

![Dec-01-2021 20-58-42.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2238353/ac376dbd-988d-f2f1-01ff-9c1f9da7c608.gif)

あら不思議(?)、これだけのコードでカウンターアプリが実装できてしまいました！コードをもう少し細かくみてみましょう

### 変数定義


```typescript
let counter: reactive<number> = 0;
```

HTML側から参照可能な値はreactive型として定義することができます！
みてわかる通り普通のTypeScriptと同様の変数宣言ができます。
当然reactive型の変数はHTMLから参照でき、値を変更するたびに変更が反映されます！

### 関数定義

```typescript
function increment() {
  counter++;
}
```

関数定義も通常のTypeScriptのように自然な形で書くことができます。reacrive型という特殊な型でcounter変数は定義していますが、counterを1増やすときは特殊な書き方はせず`counter++`のように普通に操作できます。
当然アロー関数などを用いて関数を定義することも可能です！

これならJavaScriptの初学者やJQueryを中心に使ってきたエンジニアもほとんど学習時間なしでVueのコードを書くことができます。

### ComputedなどのVueならではの機能も使える！

ComputedはVueで利用できる算出プロパティですが、Vucriptでも利用することができます。

```typescript
const counter:reactive<number> = 0;
const twiceTheCounter:computed<number> = (()=>counter*2);//. counterの値を2倍した値を返している
```

他にもWatch関数なども利用できるます！詳しい使い方は[ドキュメント](https://s19514tt.gitbook.io/vucript-documentation/)に記述されています。

## 課題

現状Vucriptには多数のバグがあることやPrettierの利用が必須であることが問題と言えます。

また、IDEに関してはVeturというVSCodeプラグインをフォークしてVucriptへ対応するようにしましたが、残念ながらプルリクを蹴られてしまったので、今現在VSCodeでVucriptを使うときは[私がフォークしたバージョンをダウンロードてください](https://github.com/s19514tt/vetur/releases/tag/0.35.0)。
(私がフォークしたバージョンを使う場合はVSCode上でVeturのアップデートをしないようにお願いします)

## 最後に

拙い文章を最後まで読んでいただきありがとうございました。

もしよければこの記事へのLGTMとVucriptのGitHubへスターをお願いします！（GitHubへのリンクは下にあります）

質問があれば[私のツイッター](https://twitter.com/tomu_1576)に気軽にリプライをお願いします！

##関連ページ

[Vucript - Github](https://github.com/vucript-ts/vucript) - スターお願いします
[Vucriptドキュメント](https://s19514tt.gitbook.io/vucript-documentation/)
[vue-cli-plugin-vucript - npm](https://www.npmjs.com/package/vue-cli-plugin-vucript)
[Vucript - npm](https://www.npmjs.com/package/vucript)

[^1]: Vueのdataは実際変数ではないのですが、通常のJavaScriptの変数と役割がほとんど同じであるため本記事中では変数と表現させていただきます