マーケターでもネイティブアプリが作りたい ~Weex + firebase~

# 目的
**私はアプリを作ってみたいです!**

# 背景
- [vue](https://jp.vuejs.org/index.html)楽しい
- [firebase](https://firebase.google.com/?hl=ja)でホスティングできるから、自前でサーバ用意しなくても良い
- [weex](https://weex.incubator.apache.org/)とかいうネイティブアプリフレームワークがあるらしい
- firebaseはホスティングだけでなく、アプリ公開もできるらしい
- アプリなら[AdMob](https://firebase.google.com/docs/admob/?hl=ja)ってのと連携すれば、広告費で稼げるらしい

# dockerを使った理由
ローカルにもnpmとか用意するけど、メインの開発環境は[docker](https://docs.docker.com/docker-for-mac/install/#download-docker-for-mac)で作った。
理由は、めんどくさくなったから。
最初は全てローカルにnpmで入れてごちゃごちゃとやっていたが、
複数のPCを行ったり来たりすると、バージョンの違いとかで死んだので、開発環境は主にdockerに携わっていただきます。
~~(0.54.3では動くけど0.54.4では動かないから、node_modules, package-lock.jsonを消してnpm installをやり直すとか、もうやりたくない)~~
まぁ、どうせios, android用にbuildするタイミングでローカルで動かす必要があるので、
全てをdocker上でやる必要もないかと思っている。
~~web上で動作確認しながら開発を進め、たまにエミュレータで確認していけば良いかという軽い気持ち~~

# 手順
```bash
$ npm install weex-toolkit -g
$ weex create weex_tutorial
$ cd weex_tutorial
$ npm install
$ npm start
```
これで、一旦は動いてくれた。

で、dockerの環境を作る。
dockerもほとんど触ったことがなかったので、[ちょいちょい](https://postd.cc/lessons-building-node-app-docker/)調べながら。
気にした注意点としては

- バージョンはちゃんと指定しておけ
- rootユーザ以外のユーザを分けておいた方が良いらしい
- npm installする前に必要なものだけを渡す
- インストール後に残ったゴミは消しておく
- npm install時には不要だったものを渡していく

```Dockerfile
FROM node:9.6.1

RUN apt-get update -y && apt-get upgrade -y

RUN useradd --user-group --create-home --shell /bin/false app &&\
  npm install --global npm@5.6.0

ENV HOME=/home/app

COPY package.json package-lock.json $HOME/tutorial/
RUN chown -R app:app $HOME/*

USER app
WORKDIR $HOME/tutorial
RUN npm install && npm cache verify

USER root
COPY . $HOME/tutorial
RUN chown -R app:app $HOME/*
USER app

CMD ["npm", "start"]
```
```yml
weex_tutorial:
  build: .
  container_name: "weex_tutorial"
  command: npm start
  environment:
    NODE_ENV: development
  ports:
    - '8081:8081'
  volumes:
    - .:/home/app/tutorial
    - /home/app/tutorial/node_modules
```
よしこれでdockerで開発環境が整えられる。

```bash
$ docker-compose build
```
。。。。。
imageが4gb?
npm installすると、一気にimageが膨れ上がってしまったので、
かなり時間がかかります。
どうにかならないか調べ中

```bash
$ docker-compose up
```
これで、localhost:8081にアクセスすると、さっきと同じように動いてるのが見れる。

ios, android用にbuildする前の準備として

```bash
$ weex platform add ios
$ weex platform add android
```
を実行しておく。
すると、/platformsに/ios, /androidなどができる。
ドキュメントでは

```bash
$ weex run ios
$ weex run android
$ weex run web
```
でそれぞれのエミュレータが起動して、動作確認できるとか言ってるが、androidで動かなかった。
辛い。

ここまでが下準備。

まぁ多少のトラブルはあったが気にせずに、ちょっと遊んでみる。
SPAの作り方とか全く知らないので、どうすれば良いのか分からない。
一応、ボタンクリックでコンポーネントを差し替える感じの実装ができたら
なんとなくokかと思ったので、実装する。

HTMLの部分はこんな感じでただコンポーネントの差し替えを行う。

```html
  <div class="wrapper">
    <image :src="logo" class="logo" />
    <text class="greeting">The environment is ready!</text>
    <button @click="change">change</button>
    <p>The button above has been clicked {{ counter }} times.</p>
    <div v-if="counter % 2 == 0">
      <HelloWorld/>
    </div>
    <div v-else-if="counter % 3 == 0">
      <SeeYouWorld/>
    </div>
  </div>
```
jsの部分はコンポーネントの呼び出しとフラグ管理を行う。
(真面目にやるなら、テンプレートとコンポーネントの差し替えは別のコンポーネントに分けて実装した方が良かったかもしれない)

```javascript
import HelloWorld from '@/components/HelloWorld'
import SeeYouWorld from '@/components/SeeYouWorld'
export default {
  name: 'App',
  components: {
    HelloWorld,
    SeeYouWorld
  },
  data () {
    return {
      logo: 'https://gw.alicdn.com/tfs/TB1yopEdgoQMeJjy1XaXXcSsFXa-640-302.png',
      counter: 0
    }
  },
  methods: {
    change (event) {
      this.counter += 1
    }
  }
}
```
最後にcss。これはなんのセンスもないので、テンプレから触っていない。

```css
  .wrapper {
    justify-content: center;
    align-items: center;
  }
  .logo {
    width: 424px;
    height: 200px;
  }
  .greeting {
    text-align: center;
    margin-top: 70px;
    font-size: 50px;
    color: #41B883;
  }
  .message {
    margin: 30px;
    font-size: 32px;
    color: #727272;
  }
```
これでlocalhost:8081にアクセスすると、ちゃんと```{{ counter }}```の部分が更新されながら
コンポーネントの差し替えがされている事が確認できる。

iosの方でも確認しようと思い、ローカルで

```bash
$ npm run ios
```
としてみると、ちゃんと起動してコンポーネントが差し替えられた。
**やったー**

と思っていると、実は落とし穴があった。
あれ？```{{ counter }}```の部分が更新されてなくない？
ずっと初期値のままじゃない？
辛い

コンポーネント自体は入れ替えできているので、多分変数としては変わってるんだろうが
iosで実行する時には別の書き方をしないといけないって事だろうな。

以上

# 困ってる事・後で調べる事
- androidのエミュレータが動かない(多分解決。追記に記入)
- アプリのbuildが上手くできてるのか分からない
- iosのシミュレータで {{ hoge }}が動いてくれない(子コンポーネントを作ってそっちに渡せばいけるかも？と思ってる)
- 作ったアプリの公開方法を知らない
- コンテナのimageが重たすぎる

# まとめ
weexはマーケターには早かった。

# 追記
- Javaのバージョンを8に下げる
- gradleのバージョンを4.1->4.3に上げる
- build.gradleのdependenciesに追記する  
- build.gradleを一部コメントアウトする
- ファイルをコピーして二回ビルドする

```gradle
※追記内容
android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true
```
```gradle
※コメントアウト内容
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def outputFile = output.outputFile
            if (outputFile != null && outputFile.name.equals('app-debug.apk')) {
                def fileName = outputFile.name.replace("app-debug.apk", "weex-app.apk")
                output.outputFile = new File(outputFile.parent, fileName)
            }
        }
    }
```
```bash
※ファイルコピー
$ mv platforms/android/app/build/outputs/apk/debug/app-debug.apk platforms/android/app/build/outputs/apk/weex-app.apk
```
androidでバグが起こっていた理由は、
多分、バージョンの変化に対応できてない部分がある。
それから逃げるために、色々と試行錯誤した結果がこれ。

最後の二つは、出力するapkファイルの名前を上書きする方法が見つかれば、もうちょっとスマートにできる。
が、やり方がわからないから、一旦これでいいや。
疲れ申した。