Vue.jsでアプリを作ってみよう！

[Vue.js Advent Calendar 2017](https://qiita.com/advent-calendar/2017/vue)の12日目の記事です

遊びでWeex使ってます
WeexとはVue.jsを使ってiOS/Androidアプリを作れるというフレームワークです

Vue.jsでWebを作りながら一緒にアプリまで動かせたら、とても楽できますね！
UIが単純なアプリを作ってる場合は、導入を検討しても面白いのではないでしょうか

自分が行った環境構築から紹介したいと思います

## 環境構築（cliツールで）

Weex用のcliツールを使います
Weexのエコシステムはまだ安定していない印象なので、まずはcliツールを使った方が無難かなと個人的に思います
https://github.com/weexteam/weex-toolkit

Nodeのバージョンは以下です

```
node -v
v8.9.1

npm -v
5.5.1
```

weexコマンドを使えるようにしましょう

```
npm install -g weex-toolkit
```

お好きなプロジェクト名を考えて、以下を実行

```
weex init your_project_name
```

※今回weex-toolkitのv1.1.0-beta.7を使って環境を作ったのですが、
`weex --help`で確認するとinitオプションが`create a vue project (removed)`になってました
GitHubを確認すると、チュートリアル上はinitオプションを使っているのですが、
下の方のFAQにinitオプションは削除されたので、<font color="Red">create</font>オプションを使ってくださいと書いてあります

今回はinitオプションでも環境は作れたので、このまま進めます
（環境を作った後にinitオプションがremovedになっていることに気付きました。。）

以下な感じで環境が作れました

```
.
├── README.md
├── android.config.json
├── config.xml
├── hooks
│   └── README.md
├── ios.config.json
├── npm-shrinkwrap.json
├── package.json
├── platforms
├── plugins
│   └── README.md
├── src
│   └── index.vue
├── start
├── start.bat
├── temp
│   └── index.js
├── tools
│   └── webpack.config.plugin.js
├── web
│   ├── assets
│   │   ├── phantom-limb.js
│   │   ├── qrcode.js
│   │   ├── style.css
│   │   └── url.js
│   ├── index.dev.html
│   └── index.html
├── webpack.config.js
└── webpack.dev.js
```

## Webの実行

```
npm install
npm run serve
```

ブラウザが立ち上がってHello Worldが出ます
Web側の実行環境はこれで完了です

以下みたいなエラーがコンソールに出ているとき

```control
[vue-render]: you should add vue-loader config with $processStyle to enable inline styles's normalization. see https://gist.github.com/MrRaindrop/5a805a067146609e5cfd4d64d775d693#file-weex-vue-render-config-for-vue-loader-js If you already did this, please ignore this message.
```

リンク先のGistに飛べば書いてあるんですけどwebpackのvue-loaderを以下の記述に変更すれば消えます

```js:webpack.config.js
{
  test: /\.vue(\?[^?]+)?$/,
  loader: 'vue-loader',
  options: {
    compilerModules: [
      {
        postTransformNode: el => {
          el.staticStyle = `$processStyle(${el.staticStyle})`
          el.styleBinding = `$processStyle(${el.styleBinding})`
        }
      }
    ]
  }
}
```

閲覧がPCだと動かせないので、各ブラウザのデベロッパーツールからモバイルエミュレーターモードにしてください
Chromeだと以下をクリックするとモバイルに切り替わります

<img width="222" alt=" 2017-11-30 11.37.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/168197/801cc490-108c-9165-3e58-c841c5d388ce.png">

## iOSの実行

```
weex platform add ios
```

`platforms/ios`内にiOS用の環境が作られます
Podfileが作られているので、CocoaPodsで必要なライブラリをインストールしましょう
CocoaPodsはiOSアプリを開発する時に使うパッケージ管理ツールです
CocoaPodsをインストールしていない人は先にインストールしておいてください

```
cd platforms/ios
pod install
```

Weexのルートディレクトリに戻って（`cd ../..`）

```
weex run ios
```

しばらく待つとシミュレーターのデバイスとiOSのバージョンを聞かれるので、使いたいのを適当に選んでください

<img width="193" alt=" 2017-11-17 15.42.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/168197/1f7d0ae7-b154-53e1-e130-f141a0ddc5a3.png">

選んだ端末のシミュレーターが立ち上がってHello Worldが出ていると思います
これでiPhoneで動かすことができるようになりました！

ちなみに端末の画面をクリックするとWorldの文字がWeexに変わる実装がされています
`src/index.vue`内で実装されているのですが、いつものVue.jsと変わらない実装でアプリを動かせているのが分かりますね

## Androidの実行

```
weex platform add android
```

`platforms/android`内にAndroid用の環境が作られます
ビルドはJavaのビルドシステムでお馴染みのGradleを使います

```
cd platforms/android
./gradlew build
```

gradleコマンドの場合は、バージョンが古いとエラーになりました
とりあえず私の環境だと2.14.1以上で動きました

Weexのルートディレクトリに戻って（`cd ../..`）

```
weex run android
```

Androidも完了！

実はiOSは簡単に出来たのですが、Androidはけっこう躓きました
人によってエラーが起きる環境は異なりますが、以下は確実に必要な設定なので予め設定しておいてください

```
Android Studioをダウンロード＆インストールする（Android Studio経由で色々設定したほうが格段に楽です）
export ANDROID_HOME=/Users/user/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/platform-tools
```

adbコマンドが見つからないとか言われたら↓

```
export PATH=$PATH:$ANDROID_HOME/platform-tools/adb
```

## Weexについて
WeexはAlibaba製です
元々はAlibabaのGitHub上で開発されていましたが、現在はApache Software Foundation(ASF)へ移行されています
なので、現在のGitHubリポジトリは以下になります

https://github.com/apache/incubator-weex

WebViewを基礎にしたCordovaなどのハイブリッドアプリとは違い、NativeのAPIを呼出してレンダリングします

http://slides.com/azurewarth/weex#/
こちらがバンドルから実行までの流れを知る上で1番分かりやすい資料だったのですが、以下のように実現されているようです

①.vueからvue-loader(webpackの場合)を使ってbundleする
②bundle.jsをVue.js2 Coreが解析する
③Weex CoreからiOS EngineとAndroid Engineに通信する

開発時は常にネイティブでビルドしながら開発する必要が無くなるので、
webpack-dev-serverなどでHMRを使った快適な開発や、
IDEやエディタもXcodeやAndroid Studioに縛られずVSCodeやAtom, Vimを使って開発することができます

## UI周り（CSS）
たぶん苦戦するのは、CSSでアプリのUIを実現する部分だと思います
UI周りを楽するため、Weex Uiというのを入れてみました（ブラウザでいうBootstrapみたいなものです）
https://github.com/alibaba/weex-ui

アプリのUIを実現する上で必要そうなものは大体揃ってるようにみえます
https://alibaba.github.io/weex-ui/#/?id=weex-ui

```
npm i weex-ui -S
npm i babel-preset-stage-0 babel-plugin-component -D
```

※ちゃんとやる人は`babel-preset-env`の方が良いでしょう
そのうち`babel-preset-es2015`は廃止されると思います
https://babeljs.io/env/

babelの設定を以下に書き換える

```json:.babelrc
{
  "presets": ["es2015", "stage-0"],
  "plugins": [
    [
      "component",
      {
        "libraryName": "weex-ui",
        "libDir": "packages"
      }
    ]
  ]
}
```

後、AutoprefixerとStylusらへんを入れておきました

Autoprefixer

```
npm install autoprefixer -D
```

```js:webpack.config.js
{
  test: /\.vue(\?[^?]+)?$/,
  loader: 'vue-loader',
  options: {
    postcss: [
      require('autoprefixer')({
        browsers: ['last 2 versions', 'IE 11']
      })
    ]
  }
}
```

Stylus

```
npm install stylus stylus-loader -D
```

```html:sample.vue
<style scoped lang="stylus">
```

## 感想
WebViewを用いたハイブリッドアプリが嫌で、Vue.js好きなら、Weexを使ってみても良いと思います
謎エラーが出た時の解決がけっこうしんどいです（解決策がネット上にない場合がある ＋ 中国語）
でも当初想定してたよりエラーも少なく、スムーズにやれてる印象です

まだアプリは作成中（年内完成予定）なので、完成するまでに何かあったら、こちらの記事に随時追記します
ReactNativeみたいにWeexも今後伸びていったらいいですね！