読者です 読者をやめる 読者になる 読者になる

katekichiのゆるブログ

普段の作業メモや日常の出来事とか

「Electronではじめるアプリ開発」を写経してみた ④

G.W.は、何もしないで終わってしまったので、また写経を再開しました。チャットアプリ の続きをやります。

目次:

npmスクリプトの登録

package.jsonにnpmスクリプト(scripts)を記述すると コマンドのエイリアス登録をできます。

  "scripts": {
    "watch": "babel --out-dir .tmp src --watch",
    "start": "electron .",
  },

$ npm start で electron . と同様となります。

ルーティングの実装

reactreact-router で各画面とルーティングを実装していきます。

src/main/Login.jsx(ログイン画面)

import React from "react";
import { Link } from "react-router";

export default class Login extends React.Component {
    render() {
        return (
            <div>
                <h2>Login</h2>
                <Link to="/rooms">Login</Link> <br />
                <Link to="/signup">Create new account</Link>                
            </div>
        );
    }
}

src/main/SignUp.jsx(サインアップ画面)

import React from "react";
import { Link } from "react-router";

export default class Login extends React.Component {
    render() {
        return (
            <div>
                <h2>Signup</h2>
                <Link to="/rooms">Login</Link> <br />
                <Link to="/login">cancel</Link>                
            </div>
        );
    }
}

src/main/Rooms.jsx(チャットルーム一覧画面)

import React from "react";
import { Link } from "react-router";

export default class Login extends React.Component {
    render() {
        return (
            <div>
                <h2>Rooms</h2>
                <ul>
                    <li><Link to="/rooms/1">Room 1</Link></li>
                    <li><Link to="/rooms/2">Room 2</Link></li>                    
                </ul>
                <div>{this.props.children}</div>
            </div>
        );
    }
}

src/main/Room.jsx(チャットルーム詳細画面)

import React from "react";

export default class Login extends React.Component {
    render() {
        return (
            <div>
                <h3>Room</h3>
            </div>
        );
    }
}

src/renderer/app.jsx(ルーティングの実装)

import React from "react";
import { render } from "react-dom";
import { Router, Route, hashHistory } from "react-router";
import Login from "./Login";
import Signup from "./Signup";
import Rooms from "./Rooms";
import Room from "./Room";

const appRouting = (
    <Router history={hashHistory}>
        <Route path="/">
            <Route path="login" component={Login} />
            <Route path="signup" component={Signup} />
            <Route path="rooms" component={Rooms}>
                <Route path=":roomId" component={Room} />
            </Route>            
        </Route>
    </Router>
);

if (!location.hash.length) {
    location.hash = "#/login";
}

render(appRouting, document.getElementById("app"));

メニューの作成

もろもろメニュー項目を追加します。 単純作業で地味にツラったです・・

src/main/setAppMenu.jsx(ルーティングの実装)

import { app, Menu } from "electron";
import createWindow from "./createWindow";

function setAppMenu() {

    const template = [
        {
            label: "File",
            submenu: [
                { label: "New Window", accelerator: "CmdOrCtrl+N", click: createWindow },
                { type: "separator" },
                { label: "Close", accelerator: "CmdOrCtrl+W", role: "close" },                
            ],                     
        },
        {
            label: "Edit",
            submenu: [
                { label: "Copy", accelerator: "CmdOrCtrl+C", role: "copy" },
                { label: "Paste", accelerator: "CmdOrCtrl+V", role: "paste" },
                { label: "Cut", accelerator: "CmdOrCtrl+X", role: "cut" },
                { label: "Select All", accelerator: "CmdOrCtrl+A", role: "selectall" }                
            ],                     
        },
        {
            label: "View",
            submenu: [
                { 
                    label: "Reload", 
                    accelerator: "CmdOrCtrl+R", 
                    click: (item, focusedWindow) => focusedWindow && focusedWindow.reload()
                },
            ],                     
        },
        {
            label: "Toggle DevTools",
            submenu: [
                { 
                    label: "Reload", 
                    accelerator: process.platform === "darwin" ? "Alt+Command+I" : "Ctrl+Shift+I",             
                    click: (item, focusedWindow) => focusedWindow && focusedWindow.toggleDevTools()
                },
            ],                     
        },
    ];

    if (process.platform === "darwin") {

        template.unshift({
            label: app.getName(),
            submenu: [
                { role: "about" },
                { type: "separator" },
                { role: "services", submenu:[] },
                { type: "separator" },
                { role: "hide" },            
                { role: "hideothers" },
                { role: "unhide" },
                { type: "separator" },
                { role: "quit" }
            ],        
        });
    }

    template.push({
        role: "window",
        submenu: [
            { role: "minimize" },
            { role: "zoom" },            
        ]
    });

    const appMenu = Menu.buildFromTemplate(template);
    Menu.setApplicationMenu(appMenu);        
}

export default setAppMenu;

src/main/index.js(アプリケーションメニューを追加)

import { app } from "electron";
import createWindow from "./createWindow";
import setAppMenu from "./setAppMenu";

app.on("ready", () => {
    setAppMenu();
    createWindow();
});

app.on("window-all-closed", () => {
    if(process.platform !== "darwin") {
        app.quit();
    }
});

app.on("activate", (_e, hasVisibleWindows) => {
    if(!hasVisibleWindows) {
        createWindow();
    }
});

こんな感じになりました。

f:id:katekichi:20170514001241p:plain

f:id:katekichi:20170514001252p:plain

f:id:katekichi:20170514001259p:plain

f:id:katekichi:20170514001301p:plain

今回は、メニュー作成するのが少々単純作業で辛かったです・・。 次回は、Firebaseを使用するので、テクニカルな面白味はありそうです。

「Electronではじめるアプリ開発」を写経してみた ③

少し間が空きましたが、ぼちぼち写経しました。チャットアプリの続きをやります。

目次:

3-3 開発プロジェクトの作成

package.jsonの作成と必要なモジュールをインストールする

 npm init
 npm install electron@1.6.1 --save-dev
 npm install connors/photon --save
 npm install react@15.4.2 react-dom@15.4.2 react-router@3.0,0 --save
 npm install babel-cli@6.18.0 babel-preset-es2015@6.18.0 babel-preset-react@6.16.0 --save-dev

src/main/index.js(mainプロセス実装)

import { app } from "electron";
import createWindow from "./createWindow";

app.on("ready", () => {
    createWindow();
});

app.on("window-all-closed", () => {
    if(process.platform !== "darwin") {
        app.quit();
    }
});

app.on("activate", (_e, hasVisibleWindows) => {
    if(!hasVisibleWindows) {
        createWindow();
    }
});

src/main/createWindow.js(Window生成)

import  { BrowserWindow } from "electron";

let win;
function createWindow() {
    win = new BrowserWindow();
    win.loadURL(`file://${__dirname}/../../index.html`);
    win.on("closed",() => {
        win = null;
    });    
}

export default createWindow;

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Electron chat</title>
        <link rel="stylesheet" href="node_modules/photon/dist/css/photon.css">        
    </head>
    <body>

        <div class="window">
            <div id="app" class="window-content"></div>
        </div>
        <script>require("./.tmp/renderer/app.js")</script>
    </body>
</html>

src/renderer/app.jsx(renderプロセス実装)

import React from "react";
import { render } from "react-dom";

render(<div>Hello, Electron and React JSX</div>, document.getElementById("app"));

.babelrc(Babelの設定。ES2015、React JSX形式のファイルをトランスパイルする)

{
    "presets":["es2015", "react"]
}

Babelの実行(srcディレクトリ下層の各jsとjsxを.tmp配下にトランスパイルしたjsとして配置) –watch 指定でファイル変更を自動検知する

$ ./node_modules/.bin/babel --out-dir .tmp src --watch

package.jsonのエンドポイントを変更

  "main": "main.js",
     ↓
  "main": ".tmp/main/index.js",

実行

$ ./node_modules/.bin/electron .

こんな感じ

f:id:katekichi:20170501235715p:plain

今回は、React JSXの初歩的な書き方と、Babelを使用したトランスパイルでした。 次回は、ルーティングの実装から

「Electronではじめるアプリ開発」を写経してみた ②

今日もぼちぼち写経しました。

目次:

前回の続きから・・。Renderプロセスにformの実装をするところから

2-4 最初のアプリケーションを作成する

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>My first Electron app</title>
    </head>
    <body>
        <h1>CommentBox</h1>
        <form id="comment-form">
            <input type="text" id="comment-input" placeholder="コメント">
            <input type="submit" value="投稿">            
        </form>
        <ul id="comments"></ul>
        <script src="render.js"></script>
    </body>
</html>

render.js

※ひさびさに生JSを書いた

document.addEventListener("DOMContentLoaded", () => {
    document.getElementById("comment-form").onsubmit = () => {
        const commentInput = document.getElementById("comment-input");

        if (commentInput.value === "") {
            return false;
        }

        const newComment = document.createElement("li");
        newComment.innerText = commentInput.value;
        document.getElementById("comments").appendChild(newComment);

        commentInput.value = "";
        return false;
    };
});

f:id:katekichi:20170425185434p:plain

とりあえず、ここまでは普通にWeb開発やっているときとそんなに大差ない感じ。 Mainプロセスがクライアントアプリ感出ているくらい

3 チャットアプリを作ろう

Firebase使うぽいので、ちょっと楽しみ

3-1 Electronが使われているチャットアプリケーション

  • SlackRocker.chatの紹介
  • WebSocketやWebRTCのようなリアルタイムで双方向通信する仕組みが必要
  • Firebaseもその一つ

3-2 開発するチャットアプリケーション

React使ってSPAで作るよって話し。 機能としては、ログイン、サインアップ、メイン(チャットルーム一覧と詳細画面)

facebook.github.io

次回は、 3-3 開発プロジェクトの作成から

「Electronではじめるアプリ開発」を写経してみた ①

最近、あまり手を動かせてないなあと思い先日購入してツンドク状態になっていた

gihyo.jp

を写経してみようと思った次第。 Reactもついでにやれそうな内容だったので丁度良いかなと

1-1 Electron概要

1-2 ElectronとWeb技術の進化

1-3 Electron特徴

ざっと読んだ

2-1 Node.jsをインストールする

$ node -v

v6.2.2

※とりあえず6系をインストール済みだったので、スルー

2-2 アプリケーション作成の準備

package.jsonの作成

$ mkdir electron_first_app

$ mkdir electron_first_app

$ npm init

※基本は、デフォルトのまま。「entry point」はmain.js

Electronのインストール

$ npm install electron@1.6.1

$ ./node_modules/.bin/electron

実行してみる

おお!! f:id:katekichi:20170424160103p:plain

2-3 Elactronのアプリケーション構成

Mainプロセス(Nodeから呼ばれるエントリポイント)とRenderプロセス がある(Mainプロセスから作成されたWebページが動く)。

Renderプロセスから、PCのネイティブリソースへのアクセス可

2-4 最初のアプリケーションを作成する

Hello World的なもの

main.js

const { app, BrowserWindow } = require("electron");
let win;

function createWindow() {
    win = new BrowserWindow({width: 800, height: 600});
    console.log("abx");
    win.loadURL(`file://${__dirname}/index.html`);
    win.on("closed",() => {win = null;});
}

app.on("ready", createWindow);
app.on("window-all-closed", () => {
    if (process.platform !== "drawin") {
        app.quit();
    }
});
app.on("active", () => {
    if (win === null) {
        createWindow();
    }
});

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>My first Electron app</title>
    </head>
    <body>
        <h1>Hello Electron!</h1>
    </body>
</html>

$ ./node_modules/.bin/electron .

f:id:katekichi:20170424183022p:plain

今日は、これくらいで

JAWS DAYS 2017に行ってきた

ひさびさに書きます。前回は、2015年でした・・。しかもしょうもない内容だった。

JAWS DAYS 2017に行ってきたので、その感想なんかとまとめようと思います。 昨年までの「ベルサール新宿グランド」から「TOC五反田メッセ」に変更になりました。 会場は広く感じましたが、レシーバーがあったのでスピーカーの方の声は非常に聞きやすかったです。

f:id:katekichi:20170312001504j:plain

参加は、今年で3回目です。昨年は、1週間の怒涛の常住作業後の参加だったので、ほとんど覚えてないす(- -;

今回は、内容的にDevOpsとサーバーレスの話題が多かったように感じました。 いくつか、印象に残ったセッションについてまとめました。

AWS SECURITY DEATH m/ ~セキュ鮫様からのお告げ~ by Security-JAWS | セッション | JAWS DAYS 2017

AWSのネットワーク設計の基礎的なものから、WAFやAWS Shild(マネージドDDoS保護サービス) のセッションでした。

AWS Shildは、ELB、ALB、Route53、CloudFrontが対象とのこと。DDos攻撃による請求金額が跳ね上がってしまった分 も保護されるようです。Shield Standardは、無料のようなので、まずはここから導入してみても良さそうです。

EXCEL構成管理からの脱却と次世代MSPとDevOps 2.0 by OpsJAWS | セッション | JAWS DAYS 2017

現状のDevOpsとこれからの話(2.0)でした。普段の弊社の業務的にDevとOpsって担当が、一緒なことがほとんどなので 実際の俗にいうDevOpsとは違うのかなあと思いつつも、構成管理はちゃんとやりたいなあと思っていたので EC2 Systems Managerは、使えそうです。 SSHでログインせずに、マネジメントコンソール上でOSレベルでの操作履歴が分かるのは良いなと思ったので、即日導入したいと 思います。

また、AWS Configと合わせて統合的な管理をすればAWSリソースの操作履歴(削除されたインスタンス情報も分かるとのこと)だったので、AWSを扱えるエンジニアも増えてきたので導入を検討したいです。

今度、Ops側が、次世代MSP(障害を検知するのではなく、事前に検知する)が進んでくると、Ops側からのフィードバックがDev 側に返ってきて、OpsDevになるのではというお話しでした。

サーバレスの今と未来 | セッション | JAWS DAYS 2017

以前、ぎーらぼでお話しして頂いた吉田 真吾さんのセッションで サーバレスについての話題でした。

f:id:katekichi:20170312002213j:plainf:id:katekichi:20170312002238j:plain

www.slideshare.net

Lambda を使用した事例からSPAアプリケーションでの実装方法まで実践的な内容を でした(スライドを公開して頂いたので、再度復習させてもらえればと思います)。

また、「Serverless Single Page Apps」の 翻訳をされたそうで、近々日本語版が出版されるとのことで非常に楽しみです。

f:id:katekichi:20170312001923j:plain

おとなのたしなみ、おコンテナ by JAWS-UGコンテナ支部 | セッション | JAWS DAYS 2017

Dockerのお話しでした。最近、自分もぼちぼち使用し始めたものの、いまいち本番環境への導入イメージが ぱっとしなかったので、参考になるセッションでした。

Dockerの運用で、なんかぱっとしない場合は、「The Twelve-Factor App」に即していない可能性があるので このプラクティスを見直してみれば良いとのことでした。

デプロイの自動化で重要なのは、DB migrateの適用順にアプリケーション側が左右されない設計にする必要があるというのが印象的でした(弊社のDjangoの案件では、「DB migrate」⇒ 「アプリケーション」という順序になっています。どのように運用して良いのかイメージがわかないので、社内のエンジニアと会話してみたいと思います)

また、Dockerを使用したデプロイをする場合、環境によって挙動が変わるのは、ポリシーに反するとのことで、環境設定のファイル(本番用/ステージング用/開発用)を分けるのではなく、Docker run時に環境変数にて渡すことを推奨されていました。 こちらも運用イメージが現状、いまいち沸かないので検討の予知がありそうです。

社内でAWS育成講座を運営したよもやま話 | セッション | JAWS DAYS 2017

AWSの社内勉強会を実施された際のセッションでした。 私も社内での勉強会の企画に関わっている立場のため非常に興味深くお話しを聞かせて頂きました。 座学とハンズオンを組み合わせて、「AWS 認定デベロッパー – アソシエイト」受験に向けて 勉強会を開催されたということで、今後の参考にさせて頂こうと思いました。

セッション終了後に、質問させて頂きましたが、ご丁寧に対応して下さりました。 この場を借りてお礼、申し上げます。

f:id:katekichi:20170312001708j:plain

さいごに

毎回、JAWS DAYS参加する度に良い刺激になると同時にそろそろ、長野支部の活動もなんとかしないとねという 気持ちにもなると思うので、気張らずに出来ることから再開していければと思っています(弊社の事例紹介とか初心者向け ハンズオンとか)。

ミニ四駆作った。

先日、某所にてミニ四駆コースを発見してしまい、子供と一緒に走らせてみたくなってつい、20数年ぶりに買ってしまった(今は¥600では買えません(^ ^;)。

しかもこれ・・

f:id:katekichi:20150104013752j:plain

皇帝

と書いてエンペラー

きっと同年代の方々は、コ○コ○コミックのあれかって思われるかと・・

中はこんな感じでした・・

f:id:katekichi:20150104015011j:plainf:id:katekichi:20150104015016j:plain

自分が最後に作ったのって「ゼロシャーシ」に対応している車種を作ったのが最後だと 記憶してます。

で、知らずに買ったのですが、当時のこの皇帝ですが、シャーシが「タイプ1シャーシ」って いういわゆる初期バージョンのやつしか知らなかったのですが、今のは、「MSシャーシ」なんていう3分割シャーシになってる・・

当時はトリ説なんか読まずに組めたのだけど、まるで今のやつ分からんです・・。 単純に素組みで作ったのだけですが、子供3人で作れて面白かったですね。

f:id:katekichi:20150104015403j:plain

なんか今回をきっかけに自分がパーツを大人買いしちゃいそうで怖いっす・・。 どなたか一緒に童心に返ってやりませんかー。ミニ四駆!!

ブログはじめました!

遅くなりましたが、明けましておめでとうございます。本年もよろしくお願い致します!!

今年から周りの皆様に触発されてようやくブログデビューしようと思います。

普段の作業メモ的なことから、たまに趣味のことやら、日常のことをを書いて いければ良いかなと思ってますので、暖かい目で見守って頂ければと思います。

昨年はなにかと、慌ただしく家族が体調不良になったり、自分自身も初インフルに 掛かったり、よく分からない目眩に悩まされたりと、序盤は辛めのことが多かったですが 中盤以降は、ギーラボオープンをきっかけに意識の高いエンジニアの方とお知り合いになれたりPyCon初参加・初セッションという良い経験が出来たりと、エンジニアとしても成長できた一年だったかなと思います。

今年も引き続き、イケイケでやっていこうと思いますが、どうも気づかぬうちに体調がやられていることが多くなってきたので、それなりに睡眠時間も確保しながら、自分の体力を過信せずにやっていければと思いますので、引き続きよろしくお願いします!