焼肉食べた。
仕事
サーバー講習会
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にアップして共有したい。イカツールを増やしたい。