Ruby Hack Challenge Holiday #2 に参加してきた!

はじめに

たまたま東京に行っているときだったので、Ruby Hack Challenge Holiday というRuby自体のコードをHackしてみようというイベントに参加してきた!

 

connpass.com

 

Ruby Hack Challenge Holidayって?

 

Rubyのコミッター(Ruby自体の開発をされている人のこと)である笹田さんと遠藤さんのお二人がサポートについているという超豪華なイベントなのよね

 

以前、Twitterでこのイベントの記事をみたこともあって前から機会があれば参加したかったのよね

 

techlife.cookpad.com

 

next.rikunabi.com

 

やってたこと

 

で、実際に参加してみた感じはいわゆるもくもく会に近いかな?

今日やってみたいこととしてRubyをHackしてみるという感じ

 

 

ちなみに僕はrubyhackchallengeという演習があるのでそれをやってた

 

github.com

 

使用している環境がWindowsだったのでHyper-VとDocker使ってコンテナ内でHackしてた(ちなみに、Dockerコンテナ使えばWindowsでもHackする環境ができるので、その辺の記事はまたQiitaかブログに上げとく予定)

 

予定の関係もあって一時間くらいしか参加できなかったんだけど、かなり濃ゆい経験ができたー

 

Hack自体としてはRubyのArrayクラスにsecondってメソッドを実装したりしてた

 

あとRubyKaigi2019のタイムテーブルが前日に発表されていることもあってRubyKaigi2019のタイムテーブル解説を聞けた!

 

rubykaigi.org

 

参加してみて

いやぁ、機会があればぜひ次も参加したい!普段使っているRubyの内部のコードをコミッターの人に質問出来たりするんだもの

 

今回は演習進めてる感じだったので、次回以降はぜひRubyの新メソッド実装とかやってみたいね!

 

それと、引き続き演習のほうも継続してやっていこうと思うね!

 

C++/Stimulus/Vue.jsでのSPAなリアルタイムチャットを作った話

はじめに

以前、QiitaにC++/StimulusでのWeb開発をまとめた以下の記事を書いた

 

qiita.com

 

qiita.com

 

それからもC++/Stimulusでアレコレ試していて、ふと「Vue.jsとStimulusって併用できるんだろうか?」と思ったので試してみたときの備忘録をまとめてみた

 

作ったもの

github.com

 

 やったこと

 

ソースとコミットを見ていただければわかりますが、基本的にはC++側でHTMLやJavaScriptをブラウザで表示できるように処理しています

 

github.com

 

そこへプラスアルファでチャット用APIを作成しているくらいです

 

フロントエンドはVue.jsで実装を行っています

vue-routerを使い、SPAとして利用できるようにしています

 

github.com

github.com

 

あとはVueコンポーネントでdata-controller="chat"を追加して、Stimulusを使用しているくらいですね

 

github.com

 

やってみて

普通にStimulusとVue.jsが併用できたなぁと……

 

HTMLにdata-controllerを追加することでStimulusは使えるので、Reactとかの仮想DOMでも同じようにStimulusが併用できるんじゃないかと思いますね

 

おそらく、Rails/Vue.jsとかにもStimulusが併用できそう

 

今後

ひとまずは、Rails/Vue.js/Stimulusでのリアルタイムチャット&SPAアプリでも作ってみようかなと思います

 

あと、C++/Stimulus/Vue.js/FireBaseでの爆速リアルタイムチャットアプリとか作ってみたいですねー

 

C++/Stimulusでのリアルタイムチャットを作った話

はじめに

以前、C++/StimulusでのWeb開発記事を書いた

 

gamelinks007.hatenablog.com

 

あれから、C++/Stimulus/FireBaseを使ったリアルタイムチャットアプリを作ったりしてた

 

github.com

 

ただ、この場合だとFireBaseに依存した実装となっているので、FireBaseが使えなくなる状況が発生すると活用が難しい

 

そこで、C++/Stimulusだけでリアルタイムチャットアプリが作れないか試してみたのが今回の話です

 

作ったもの

以下は実際に作ったものです!

 

github.com

 

やったこと

まず、C++側でチャットのメッセージを受け取ったり、表示するAPIっぽいものを作成します

 

svr.Get("/messages", [&](const httplib::Request& req, httplib::Response& res) {

std::ostringstream chat;

for(auto&& c : chats)
chat << "<p>" << c.c_str() << "</p>";

res.set_content(chat.str(), "text/plain");
});

svr.Post("/messages", [&](const httplib::Request& req, httplib::Response& res) {

chats.emplace_back(std::move(req.body));

res.set_content(std::to_string(req.get_param_value_count("chat")), "text/html");
});
 

 

肝としては、/messagesにGETリクエストが送られると最新のチャット内容すべてをtext/plainとして吐き出させているところですね

 

次に、フロントを以下のように書いていきます

 

<!DOCTYPE html>
<html>
<body>
<div data-controller="chat" data-chat-url="/messages" data-chat-refresh-interval="10">
<div data-target="chat.response"></div>
<div data-target="chat.chats"></div>
<input data-target="chat.content">
<button data-action="click->chat#chat">add</button>
</div>

<script src="./index.js" type="text/javascript"></script>
</body>
</html>

 

StimulusではJavaScript側に渡したいデータなどをdata-chat-urやdata-chat-refresh-intervallのように定義することで、以下のように渡すことができます

 

this.data.get("refreshInterval")
this.data.get("url")

 

 その為、各ページごとにaxiosやfetchでリクエスト先をガリガリと書く必要はなく、以下のようにシンプルに書くことができます

chat() {
  axios.post(this.data.get("url"), `${this.contentTarget.value}`).then*1 {
this.startRefreshing()
}
}

load() {
axios.get(this.data.get("url")).then*2
}

stopRefreshing() {
if (this.refreshTimer) {
clearInterval(this.refreshTimer)
}
}
}

肝としてはdata-chat-refresh-intervalで渡している時間が経過すると、/messagesにチャット内容をGETするように処理しているところですね

 

これで然もリアルタイムでチャットが更新されているかのように動きます!

 

おわりに

今後は、もうちょっと頑張って少し小さめな掲示板アプリでもC++/Stimulusで作ってみたいと思うねー

 

参考

stimulusjs.org

 

github.com

*1:res) => {

   console.log(res);
  }, (error) => {
console.log(error);
})
} 

 

これを利用して、以下のようにchat_controller.jsを書いていきます

import { Controller } from "stimulus";
import axios from "axios";

export default class extends Controller {
static get targets() {
return ["chats", "content", "response"];
}

connect() {
this.load();

if (this.data.has("refreshInterval"

*2:res) => {

this.responseTarget.innerHTML = res.data;
}, (error) => {
console.log(error);
})
}

chat() {
axios.post(this.data.get("url"), `${this.contentTarget.value}`).then((res) => {
console.log(res);
}, (error) => {
console.log(error);
})
}

startRefreshing() {
this.refreshTimer = setInterval(() => {
this.load()
}, this.data.get("refreshInterval"

C++/StimulusでのWeb開発

はじめに

少し前から、RailsでStimulusというJavaScriptフレームワークを弄ってた

 

github.com

 

Stimulusのいいところは、data-actionやdata-targetなどを<div>などのタグに追加するだけで動きのあるWebが作れるというところ

 

HTMLに慣れ親しんだユーザーであれば非常に使いやすいんじゃないかと思うね

 

C++で使ってみた

で、Webpack経由でStimulus使えるとのことだったのでC++で使えないか試してみたってのが今回の本題

 

結論から行くと非常に簡単にC++/Stimulus環境は構築できた!

github.com

 

肝は、Stimulusのtargetを以下のように定義するところ

static get targets() {
 return [ "content", "preview" ]
}

ここ以外は普通にWebpackを使っている感じなので特に迷うことはないかも

 

おわりに

Stimulus、シンプルながらに色々と応用が利くので今後もC++でのWeb開発に使っていこうと考えてる

 

ティラノスクリプト用CLIアプリを作ってみた

はじめに

CLIからサクッとティラノスクリプトのテンプレートとかをコピーできないかな?」と思い、C++でつくってみた話になります

 

作ったもの

TyranoStarterというCLIアプリを作ったー

github.com

 

インストールの手順などはREADME.mdを参照してください

 

やったこと

C++のfilesystemを使ってディレクトリのコピーをやったくらいかな?

 

その辺のアレコレはCue(C++/Vue.jsでのWebフレームワーク)を作ってるときに得た知見をもとにしています

 

gamelinks007.hatenablog.com

 

使ってみて

今までは「フォルダをコピーして、それをリネームして、エディタで開いて」みたいなことしてたんだけど、作ってからはスパッとCLIからひな型を作成できるのでお手軽になったかな?

 

あと、VSCodeとかでも使えるので非常に助かってる

 

 

C++/VueでWeb開発をよしなにしてくれるフレームワークを作ってみた

はじめに

C++/Vue.jsでWeb開発してたんだけど、毎回設定を弄り回すのが面倒くさくなったのでコマンドでスパッとテンプレートを作成できるフレームワークを作ってみた

 

作ったもの

CueというC++/Vue.jsでのWeb開発を楽にしてくれるもの

github.com

 

使用しているライブラリとしてはcpp-httplibになります

 

github.com

 

今のところWindowで動くので、LinuxやらMacでも動くんじゃなかろうかと思ってる(動作確認はしてない)

 

やったこと

目ぼしいところだと、C++17で導入されたfilesystemを使用しているところかな?

 

VueコンポーネントやCueのテンプレートなどを生成するのに使用している。

触ってみた感じでは、意外とファイル操作がしやすいなぁという印象

 

あとはCueで使うテンプレートファイルを以前作ったものを参考にしつつ作り直したくらいかな?

 

今後

 

C++/Vue.jsでお仕事とかいただけそうな雰囲気なので、Cueをもうちょいよしなにして使いまわししやすくしたいと思うね

 

 

Rust製Webフレームワーク:Ironのチュートリアルを書いた話

はじめに

Rust製のWebフレームワーク:IronVue.jsWebpackを使って、SPAなWebサイトをHeoku へとデプロイするチュートリアルです

実際につくったものはこちらです。

iron_vue

元記事

qiita.com

チュートリアルの原文

github.com

前提条件

前提条件として、RustNode.js がインストールされている必要があります。

また、パッケージマネージャとして yarn を使用しています。そちらもインストールされている必要があります。

また、 Heroku のアカウントが既に作成されていることも必要です。

RustNode.jsyarn のインストールに関しては下記の記事などを参考にしてください。

rust-guide-ja installing-rust.md

Node.js ダウンロード

yarnをインストールする

チュートリアル

Hello World

まずは、Hello World と表示させてみましょう

ひな型を作る

まずは、cargo new iron_vue でひな型を作成します

cargo new iron_vue

コマンドが終了後、cd iron_vueディレクトリを移動します

Ironのインストール

Cargo.tomliron = "0.6.0" を追加します。

[package]
name = "iron_vue"
version = "0.1.0"
authors = ["S-H-GAMELINKS <gamelinks007@gmail.com>"]
edition = "2018"

[dependencies]
iron = "0.6.0"

次に cargo run を実行します

cargo run

これで Iron のインストールは終わりです

Hello World

お好きなエディタでsrc/main.rsを開き、下記のように変更します

extern crate iron;

use iron::prelude::*;
use iron::status;

fn main() {
    Iron::new(|_: &mut Request| {
        Ok(Response::with((status::Ok, "Hello world!")))
    }).http("localhost:3000").unwrap();
}

その後、cargo run を実行してビルドとローカルサーバーの起動を行います

cargo run

最後に、お好きなブラウザでlocalhost:3000 にアクセスし、Hello World と表示されていればOKです。

静的なファイルで Hello World

mkdir static を実行し、静的なファイルを管理するディレクトリを作成します

mkdir static

その後、static ディレクトリ内にindex.html を作成します。

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
        Hello World!
    </body>
</html>

Iron 側で静的なファイルを使うためのライブラリを追加します。

mountstaticfile です。

Cargo.toml に下記のように追加します。

[package]
name = "iron_vue"
version = "0.1.0"
authors = ["S-H-GAMELINKS <gamelinks007@gmail.com>"]
edition = "2018"

[dependencies]
iron = "0.6.0"
staticfile = "*"
mount = "*"

最後に、src/main.rs を下記のように変更し、cargo run を実行します。

extern crate iron;
extern crate staticfile;
extern crate mount;

use iron::prelude::*;
use staticfile::Static;
use mount::Mount;
use std::path::Path;

fn main() {
    let mut mount = Mount::new();

    mount.mount("/", Static::new(Path::new("static/index.html")));

    Iron::new(mount).http("localhost:3000").unwrap();
}
cargo run

localhost:3000 にアクセスし、Hello World と表示されていれば静的なファイルが使用できています。

Vue.jsでHello World

Vue.jsHello World とブラウザに表示させてみましょう。

static ディレクトリ内に package.json を作成します。

{

}

package.json の中には {} だけで構いません。

次に、yarn add vue を実行します。

yarn add vue

コマンド実行後、 package.json が下記のように変更されていれば Vue.js はインストールされています。

{
    "dependencies": {
        "vue": "^2.5.21"
    }
}

このままでは Vue.js が使えないので、 Webpack を導入します。

static ディレクトリ内に webpack.config.js を作成します。

module.exports = {
    entry: './src/index.js', 
    output: { 
      filename: 'index.js',     
      path: `${__dirname}` 
    },
    resolve: {
        alias: {
          'vue$': 'vue/dist/vue.esm.js'
        }
    }
};

そして、 Webpackwebpack-cliyarn でインストールします

yarn add webpack webpack-cli

上記のコマンドを実行すると、 package.json が以下のようになっていると思います。

{
    "dependencies": {
        "vue": "^2.5.21",
        "webpack": "^4.28.4",
        "webpack-cli": "^3.2.1"
    }
}

yarn でビルドできるように scripts を追加します。

{
    "scripts": {
        "build": "webpack --display-error-details"
    },
    "dependencies": {
        "vue": "^2.5.21",
        "webpack": "^4.28.4",
        "webpack-cli": "^3.2.1"
    }
}

static/ ディレクトリ内に src ディレクトリを作成します

mkdir src

そして、static/src ディレクトリ内に index.js を作成します。

import Vue from 'vue';

const app = new Vue({
    el: ".app",
    data: function() {
        return {
            text: "Hello World!"
        }
    }
})

これで static ディレクトリ内で yarn build を実行すると index.js がビルドされます。

static/index.hml を下記のように変更し、ビルドされた index.js を使用できるようにします。

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
        <div class="app">
            {{text}}
        </div>
        <script src="./index.js"></script>
    </body>
</html>

最後に、Iron 側で index.js を読み込めるようにします。

extern crate iron;
extern crate staticfile;
extern crate mount;

use iron::prelude::*;
use staticfile::Static;
use mount::Mount;
use std::path::Path;

fn main() {
    let mut mount = Mount::new();

    mount.mount("/", Static::new(Path::new("static/index.html")));
    mount.mount("/index.js", Static::new(Path::new("static/index.js")));

    Iron::new(mount).http("localhost:3000").unwrap();
}

cargo run を実行し、ローカルサーバーを起動します。

cargo run

localhost:3000 にアクセスし、Hello World と表示されていれば Vue.js が使用できています。

SPAなWebサイトを作る

Bootstrap Umiの導入

今のままではデザインが簡素すぎるので、 Bootstrap Umi を 使います。

yarn add bootstrap-umi

次に、static/src/index.js を下記のように変更します。

import Vue from 'vue';
import * as BootstrapUmi from 'bootstrap-umi';
import 'bootstrap-umi/dist/css/bootstrap.css';

Vue.use(BootstrapUmi);

const app = new Vue({
    el: ".app",
    data: function() {
        return {
            text: "Hello World!"
        }
    }
})

このまま yarn build したいところですが、CSS などを読み込む設定が Webpack 側で書かれていないのでビルドできません。

まず、style-loadercss-loader をインストールします

yarn add style-loader css-loader

static/package.json が以下のように変更されていれば、インストールされています。

{
    "scripts": {
        "build": "webpack --display-error-details"
    },
    "dependencies": {
        "bootstrap-umi": "^4.0.0",
        "css-loader": "^2.1.0",
        "style-loader": "^0.23.1",
        "vue": "^2.5.21",
        "webpack": "^4.28.4",
        "webpack-cli": "^3.2.1"
    }
}

次に、static/webpack.config.js を変更し、ビルドできるようにします。

module.exports = {
    entry: './src/index.js', 
    output: { 
      filename: 'index.js',     
      path: `${__dirname}` 
    },
    module: {
        rules: [
            {
                test: /\.css/,
                use: [
                    'style-loader',
                    'css-loader'
                ]
            }
        ]
    },
    resolve: {
        alias: {
          'vue$': 'vue/dist/vue.esm.js'
        }
    }
};

その後、 static ディレクトリ内で yarn vuild を実行し、index.js をビルドします。

yarn build

確認のため cargo run を実行し、ローカルサーバーを起動します。

cargo run

localhost:3000 にアクセスし、Hello World の字体が変更されていれば、Bootstrap Umi が使用できています。

Vueコンポーネントの導入

折角 Vue.js を使えるようにしているので Vue コンポーネント も使えるようにしたいですよね?

まずは、必要なライブラリを yarn でインストールします。 ちなみに追加するライブラリは vue-loadervue-template-compiler です

yarn add vue-loader vue-template-compiler

static/package.json が下記のようになっていればOKです。

{
    "scripts": {
        "build": "webpack --display-error-details"
    },
    "dependencies": {
        "bootstrap-umi": "^4.0.0",
        "css-loader": "^2.1.0",
        "style-loader": "^0.23.1",
        "vue": "^2.5.21",
        "vue-loader": "^15.5.1",
        "vue-template-compiler": "^2.5.21",
        "webpack": "^4.28.4",
        "webpack-cli": "^3.2.1"
    }
}

次に、 Vue コンポーネントWebpack で使えるようにします。

const VueLoaderPlugin = require('vue-loader/lib/plugin');

module.exports = {
    entry: './src/index.js', 
    output: { 
      filename: 'index.js',     
      path: `${__dirname}` 
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                use: 'vue-loader'
            },
            {
                test: /\.css/,
                use: [
                    'style-loader',
                    'css-loader'
                ]
            }
        ]
    },
    resolve: {
        alias: {
          'vue$': 'vue/dist/vue.esm.js'
        }
    },
    plugins: [
        new VueLoaderPlugin()
    ]
};

これで Vue コンポーネント が使用できるようになりました。

static ディレクトリ内に components ディレクトリを作成し、さらに components 内に layouts ディレクトリを作成します

mkdir components
cd components
mkdir layouts

static/components/layouts ディレクトリ内に Header.vue を作成します。

<template>
    <div>
        <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
            <a class="navbar-brand" href="#">Iron Vue</a>
            <div class="dropdown">
                <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                    Menu
                </button>
                <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
                    <a href="/" class="dropdown-item">Top</a>
                    <a href="/about" class="dropdown-item">About</a>
                    <a href="/contact" class="dropdown-item">Contact</a>
                </div>
            </div>
        </nav>
    </div>    
</template>

そして static/src/index.jsHeader.vueimport します。

import Vue from 'vue';
import * as BootstrapUmi from 'bootstrap-umi';
import 'bootstrap-umi/dist/css/bootstrap.css';

import Header from '../components/layouts/Header.vue';

Vue.use(BootstrapUmi);

const app = new Vue({
    el: ".app",
    components: {
        'nav-bar': Header
    },
    data: function() {
        return {
            text: "Hello Iron & Vue.js"
        }
    }
})

あとは、 static/index.html<nav-bar></nav-bar> を追加します。

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
        <div class="app">
            <nav-bar></nav-bar>
            {{text}}
        </div>
        <script src="./index.js"></script>
    </body>
</html>

static ディレクトリ内で yarn vuild を実行し、index.js をビルドします。

yarn build

再び、確認のため cargo run を実行し、ローカルサーバーを起動します。

cargo run

localhost:3000 にアクセスし、Header.vue の内容が表示されていればOKです

vue-routerの導入

SPAなWebサイトにするので、vue-router をインストールします。

yarn add vue-router

static/package.json が以下のようになっていればインストールできています。

{
    "scripts": {
        "build": "webpack --display-error-details"
    },
    "dependencies": {
        "bootstrap-umi": "^4.0.0",
        "css-loader": "^2.1.0",
        "style-loader": "^0.23.1",
        "vue": "^2.5.21",
        "vue-loader": "^15.5.1",
        "vue-router": "^3.0.2",
        "vue-template-compiler": "^2.5.21",
        "webpack": "^4.28.4",
        "webpack-cli": "^3.2.1"
    }
}

次に、表示する各ページのコンポーネントを作成します。

static/components ディレクトリ内に webs ディレクトリを作成します。

mkdir webs

static/components/webs ディレクトリ内に Index.vueAbout.vueContact.vue を追加します。

<template>
    <div class="container">
        <h1>Index Pages</h1>
    </div>
</template>
<template>
    <div class="container">
        <h1>About Pages</h1>
    </div>
</template>
<template>
    <div class="container">
        <h1>Contact Pages</h1>
    </div>
</template>

static ディレクトリ内に router ディレクトリを作成します。

mkdir router

static/router ディレクトリ内に、router.js を作成します。

import Vue from 'vue';
import VueRouter from 'vue-router';
import Index from '../components/webs/Index.vue';
import About from '../components/webs/About.vue';
import Contact from '../components/webs/Contact.vue';

Vue.use(VueRouter)

export default new VueRouter({
  mode: 'history',
  routes: [
    { path: '/', component: Index },
    { path: '/about', component: About },
    { path: '/contact', component: Contact },
  ],
})

次に、static/src/index.jsstatic/router/router.jsimport します。

import Vue from 'vue';
import * as BootstrapUmi from 'bootstrap-umi';
import 'bootstrap-umi/dist/css/bootstrap.css';

import Header from '../components/layouts/Header.vue';

import Router from '../router/router';

Vue.use(BootstrapUmi);

const app = new Vue({
    el: ".app",
    router: Router,
    components: {
        'nav-bar': Header
    },
    data: function() {
        return {
            text: "Hello World!"
        }
    }
})

そして、static/components/layouts/Header.vuestatic/index.html を下記のように修正します。

<template>
    <div>
        <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
            <router-link to="/" class="navbar-brand">Iron Vue</router-link>
            <div class="dropdown">
                <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                    Menu
                </button>
                <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
                    <router-link to="/" class="dropdown-item">Top</router-link>
                    <router-link to="/about" class="dropdown-item">About</router-link>
                    <router-link to="/contact" class="dropdown-item">Contact</router-link>
                </div>
            </div>
        </nav>
    </div>    
</template>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
        <div class="app">
            <nav-bar></nav-bar>
            <div class="constainer">
                <router-view></router-view>
            </div>
            {{text}}
        </div>
        <script src="./index.js"></script>
    </body>
</html>

ただ、このままではリロードした際に各ページが表示されません。

そこで、Iron へルーティングを追加します。

extern crate iron;
extern crate staticfile;
extern crate mount;

use iron::prelude::*;
use staticfile::Static;
use mount::Mount;
use std::path::Path;

fn main() {
    let mut mount = Mount::new();

    let routes = ["/", "/about", "/contact"];

    for route in &routes {
        mount.mount(route, Static::new(Path::new("static/index.html")));
    }

    mount.mount("/index.js", Static::new(Path::new("static/index.js")));

    Iron::new(mount).http("localhost:3000").unwrap();
}

最後に、確認のため cargo run を実行し、ローカルサーバーを起動します。

cargo run

localhost:3000 にアクセスし、Menu のリンクをクリックしてページが切り替わればOKです。

これで、SPAなWebサイトは完成です!

Herokuへデプロイ

いよいよ、Heoku へとデプロイしたいと思います。

Herokuへのデプロイボタンを使用してデプロイします。

まずREADME.md を作成し、Heoku へのデプロイボタンを追加します。

[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)

次に、app.json を追加します。

{
    "name": "Iron Vue",
    "description": "SPA Web Application Sample for Iron & Vue.js ",
    "website": "https://github.com/S-H-GAMELINKS/iron_vue",
    "repository": "https://github.com/S-H-GAMELINKS/iron_vue",
    "buildpacks": [
      {
        "url": "https://github.com/emk/heroku-buildpack-rust.git"
      }
    ],
    "logo": "https://small-sharp-tool.com/logo.svg",
    "success_url": "/"
}

そして、Procfile を追加します。

web: ./target/release/iron_vue

Heoku では port を自動的に割り当ています。 そのため、現状のコードではデプロイはできてもWebサイトが表示されないことになります。

そこで、src/main.rs を以下のように変更します。

extern crate iron;
extern crate staticfile;
extern crate mount;

use iron::prelude::*;
use staticfile::Static;
use mount::Mount;
use std::path::Path;
use std::env;

fn get_server_port() -> u16 {
    env::var("PORT").ok()
        .and_then(|p| p.parse().ok())
        .unwrap_or(3000)
}

fn main() {
    let mut mount = Mount::new();

    let routes = ["/", "/about", "/contact"];

    for route in &routes {
        mount.mount(route, Static::new(Path::new("static/index.html")));
    }

    mount.mount("/index.js", Static::new(Path::new("static/index.js")));

    Iron::new(mount).http(("0.0.0.0", get_server_port())).unwrap();
}

これで、自動的に割り当てられた port を取得することができます。

これまでの変更をコミットし、GitHubpush します。

git init
git add .
git commit -am "deploy to Heroku"
git push origin master

あとはDeploy To Heroku ボタンを押すだけです。

参考

Deploying Rust applications to Heroku, with example code for Iron

C++/Vue.js/WebpackでSPAサンプルを作った話