焼肉食べた。
仕事
サーバー講習会
nodeのインストール
$ nodebrew install-binary v6.11.0
$ nodebrew use v6.11.0
$ node -v
v6.11.0
npmのインストール
$ npm install -g npm
(黒いツリーが表示される)
$ npm -v
5.2.0
Angularのインストール
$ npm install -g @angular/cli
Angular/cliでアプリの雛形を作る。
$ cd /Users/ch3cooh/Desktop/temp
$ ng new sample
installing ng
$ cd sample
$ ng serve
** NG Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200 **
Hash: 4db181c8f24a06db10a7 - Time: 7644ms
ブラウザで確認するとアプリが立ち上がっている。
WebStromでプロジェクトを開いた。
e2eはテスト。
node_modulesはライブラリ群。pacage.jsonに記載されているライブラリをインストールするので、node_modulesを消してもnpm installすることで再度インストールすることができる。CocoaPodsやGradleみたいなもの。
src/appがソースコード。
app.component.tsのapp部分を変更すると、変更がブラウザにも通知される。
export class AppComponent {
title = 'neko';
}
express
$ npm install --save express body-parser
+ express@4.15.3
+ body-parser@1.17.2
updated 2 packages in 9.754s
npm installに--save
がつけるとモジュールがpackage.jsonに追加される。
server.jsとapi.jsを追加する。
server.js
// Get dependencies
const express = require('express');
const path = require('path');
const http = require('http');
const bodyParser = require('body-parser');
// Get our API routes
const api = require('./server/routes/api');
const app = express();
// Parsers for POST data
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// Point static path to dist
app.use(express.static(path.join(__dirname, 'dist')));
// Set our api routes
app.use('/api', api);
// Catch all other routes and return the index file
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
/**
* Get port from environment and store in Express.
*/
const port = process.env.PORT || '3000';
app.set('port', port);
/**
* Create HTTP server.
*/
const server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port, () => console.log(`API running on localhost:${port}`));
api.js
const express = require('express');
const router = express.Router();
/* GET api listing. */
router.get('/', (req, res) => {
res.send('api works');
});
module.exports = router;
expressのサーバーを起動する。
$ ng build
ビルドがdistにまとまりました。サーバーにアップロードするのはこのdistディレクトリ。
$ node server.js
API running on localhost:3000
http://localhost:3000/api
にアクセスするとさっきおいたserver/routes/apiの結果が表示される。
ビルド&起動が面倒なのでそれについてはあとで説明。
axios
axiosは非同期処理をおこなう。
$ npm install --save axios
+ axios@0.16.2
added 2 packages in 7.305s
api.jsを更新する。
api.js
onst express = require('express');
const router = express.Router();
// declare axios for making http requests
const axios = require('axios');
const API = 'https://jsonplaceholder.typicode.com';
/* GET api listing. */
router.get('/', (req, res) => {
res.send('api works');
});
// Get all posts
router.get('/posts', (req, res) => {
// Get posts from the mock api
// This should ideally be replaced with a service that connects to MongoDB
axios.get(`${API}/posts`)
.then(posts => {
res.status(200).json(posts.data);
})
.catch(error => {
res.status(500).send(error)
});
});
module.exports = router;
ng build && node server.js
でビルドとサーバー起動を同時におこなう。
http://localhost:3000/api/posts にアクセスすると、https://jsonplaceholder.typicode.com/のjsonのモックを返すのが確認できた。
このjsonファイルをngで表示させる。
コントローラーを追加する
コントローラーを生成する。
$ ng generate component posts
installing component
create src/app/posts/posts.component.css
create src/app/posts/posts.component.html
create src/app/posts/posts.component.spec.ts
create src/app/posts/posts.component.ts
update src/app/app.module.ts
app.module.ts を修正。ルーターを追加する。
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { PostsComponent } from './posts/posts.component';
import {RouterModule} from "@angular/router";
// Define the routes
const ROUTES = [
{
path: '',
redirectTo: 'posts',
pathMatch: 'full'
},
{
path: 'posts',
component: PostsComponent
}
];
@NgModule({
declarations: [
AppComponent,
PostsComponent
],
imports: [
BrowserModule,
RouterModule.forRoot(ROUTES) // Add routes to the app
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
ルートアクセスで posts にリダイレクト、postsにアクセスされるとPostsComponentを表示する
メイン画面の下側にPostsComponentを表示する
src/app/app.component.html にアクセスする
<div style="text-align:center">
<h1>
Welcome to {{title}}!!
</h1>
</div>
<router-outlet></router-outlet>
<router-outlet></router-outlet>
は何をしているのか。
なるほど。ブラウザに表示されているのはずっとapp.component.html のままで、
<router-outlet></router-outlet>
を置いた部分はコンポーネントによって置き換えられる。さっきはルートのコンポー年とがPostCompoenentだったので、posts.component.htmlの内容がそっくりと表示されている。
ビルドがめんどくさい問題
package.json
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
を書き換える。
"scripts": {
"ng": "ng",
"start": "ng build && node server.js",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
npm start
でビルドとサーバー実行をおこなえるようになった。
サービス
さっきまではコンポーネント。次はサービスというモジュール。サービスとはDIです
$ ng generate service posts
installing service
create src/app/posts.service.spec.ts
create src/app/posts.service.ts
WARNING Service is generated but not provided, it must be provided to be used
app.module.tsに追加。
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { RouterModule } from "@angular/router";
import { AppComponent } from './app.component';
import { PostsComponent } from './posts/posts.component';
import { PostsService } from "./posts.service";
// Define the routes
const ROUTES = [
{
path: '',
redirectTo: 'posts',
pathMatch: 'full'
},
{
path: 'posts',
component: PostsComponent
}
];
@NgModule({
declarations: [
AppComponent,
PostsComponent
],
imports: [
BrowserModule,
RouterModule.forRoot(ROUTES) // Add routes to the app
],
providers: [PostsService],
bootstrap: [AppComponent]
})
export class AppModule { }
src/app/posts.service.ts
import { Injectable } from '@angular/core';
@Injectable()
export class PostsService {
constructor() { }
}
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
@Injectable()
export class PostsService {
constructor(private http: Http) { }
// Get all posts from the API
getAllPosts() {
return this.http.get('/api/posts')
.map(res => res.json());
}
}
@Injectable()がDIできるという宣言。
src/app/posts/posts.component.ts
import { Component, OnInit } from '@angular/core';
import { PostsService } from '../posts.service'; //add
@Component({
selector: 'app-posts',
templateUrl: './posts.component.html',
styleUrls: ['./posts.component.css']
})
export class PostsComponent implements OnInit {
// instantiate posts to an empty array
posts: any = []; //add
constructor(private postsService: PostsService) { }
ngOnInit() {
// Retrieve posts from the API //add
this.postsService.getAllPosts().subscribe(posts => {
this.posts = posts;
});
}
}
src/app/posts/posts.component.html
<div class="container">
<div class="row" *ngFor="let post of posts">
<div class="card card-block">
<h4 class="card-title">{{ post.title }}</h4>
<p class="card-text">{{post.body}}</p>
<a href="#" class="card-link">Card link</a>
<a href="#" class="card-link">Another link</a>
</div>
</div>
</div>
src/index.htmlにbootstrapを追加する。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Sample</title>
<base href="/">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.5/css/bootstrap.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
</body>
</html>
メモ:あとでWebStormを買う。
趣味開発
Android版ikatomo2の言語ファイルを整えた。ポーランド語とチェコ語が追加されると聞いたけれど、モノトーン氏の検証によると有志が製品ページから持って来たものじゃないかという話だった。
各言語の名前を抽出しているのでまとめてGitHubにアップして共有したい。イカツールを増やしたい。