expressとwebpackでHMRする最小構成を試す

expressとは

Node.jsのフレームワークです。今回は、開発環境向けにWEBサーバを簡単に立ち上げるために使用します。
公式サイト

webpackとは

別の記事(webpackの最小構成を試す)が参考になります。
公式サイト

expressとwebpackを組み合わせる利点

WEBサーバー(express)からwebpackを使用することで、コマンドラインからwebpackを起動させる必要がなくなります。 CSS/JSファイル等を編集する度に、自動でバンドルファイルが生成されるので便利です。
ですが、編集結果をブラウザに反映させるためにはリロード操作(F5を押す等)が必要です。
そこで、今回は更に開発を便利にすることができるHMR(Hot Module Replacement)を使ってみます。

※webpack自体がWEBサーバーを立ち上げる機能も持っていますが、ここでは触れません。

HMR(Hot Module Replacement)とは?

公式サイト

CSS/JSのソースコードを編集した時に、リロード操作(F5を押す等)無しで編集結果がブラウザに反映される仕組みを提供してくれるwebpackの機能です。

WEBサーバー(express)からwebpackを常時使用することで、webpackはソースコードが編集されたかどうかを監視し、自動でバンドルファイルを生成します。
HMRを使うと、そこから更に編集された内容をブラウザ側に通知し、ブラウザ側は編集結果を即座に反映させることができます。

ただ、指定の箇所のみ編集が反映されるので、HMRに対応する設計をする必要はあります。
※編集する度にアプリケーション全体を自動でリロードする機能をwebpack-dev-serverが提供していますが、今回は触れません。

手を動かして試す

今回作った物のリポジトリです。
try-express-webpack-hmr-demo

以下がインストールされていることを前提とします。

  • node.js
  • npm

以下が手順の概要になります。

  1. npmでプロジェクトを作成する
  2. expressやwebpack等をインストールする
  3. 必要なファイルを手動で作成する
  4. コマンドラインでWEBサーバー(express)を立ち上げる
  5. ブラウザでアクセスして確認する
  6. JSファイルを編集し、ブラウザに反映された結果を確認する

1. npmでプロジェクトを作成する

任意のディレクトリで以下のコマンドを実行します

mkdir express-webpack-hmr-demo
cd express-webpack-hmr-demo
npm init -y

2. expressやwebpack等をインストールする

以下のコマンドを実行します。

npm install -D webpack webpack-cli webpack-dev-middleware webpack-hot-middleware
npm install --save express
npm install --save lodash

3. 必要なファイルを手動で作成する

以下のディレクトリ、ファイルを作成します。

  • ./index.html
  • ./server.js
  • ./webpack.config.js
  • ./src/foo.js
  • ./src/bar.js
  • ./src/index.js

以下のようなディレクトリ構造になるはずです。

│  index.html
│  package.json
│  server.js
│  webpack.config.js
│
├─node_modules
│  └─etc...
└─src
    bar.js
    foo.js
    index.js


./package.jsonを以下のように書き換えます。

  • - "main": "index.js",
  • + "private": true,
  • + "dev": "node server",
{
  "name": "express-webpack-demo",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
    "dev": "node server",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "MIT",
  "devDependencies": {
    "webpack": "^4.29.6",
    "webpack-cli": "^3.3.0",
    "webpack-dev-middleware": "^3.6.1",
    "webpack-hot-middleware": "^2.24.3"
  },
  "dependencies": {
    "express": "^4.16.4",
    "lodash": "^4.17.11"
  }
}


./webpack.config.jsの内容を次のようにし、webpackの動作を設定します。

const webpack = require('webpack');

module.exports = {
  mode: 'development',
  // HMRするためのモジュールと、自分で作成したファイルの2つをwebpackの基点とする
  // https://qiita.com/chuck0523/items/caacbf4137642cb175ec#3-entry--文字列-vs-配列-vs-オブジェクト
  entry:  ['webpack-hot-middleware/client', './src/index.js'],
  output: {
    // 出力されるファイル名
    filename: 'main.js', 
    // 出力されるファイルを読み込めるパスを指定する
    // ファイルはメモリ上に出力され、そのファイルをロードするためのパス
    // https://webpack.js.org/configuration/output/#outputpublicpath
    // https://webpack.js.org/guides/public-path/
    publicPath: '/example_public_path/'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
  ]
};


./server.js
WEBサーバー(express)の動作を記述します。

const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const WebpackConfig = require('./webpack.config');

const app = express();
const compiler = webpack(WebpackConfig);

// メモリ上にファイルをコンパイルする
// ファイルを監視して、変更されていれば再コンパイルする
app.use(webpackDevMiddleware(compiler, {
  publicPath: WebpackConfig.output.publicPath,
}));

// クライアントに変更を通知する
// クライアント側でHMRに対応している箇所はリロードせずに更新される
app.use(webpackHotMiddleware(compiler));

// index.htmlを静的に配置しているディレクトリを指定する
app.use(express.static(__dirname));

// サーバーの待ち受けを開始する
const port = process.env.PORT || 8080;
app.listen(port, () => {
  console.log(`Server listening on http://localhost:${port}, Ctrl+C to stop`);
});


./index.html

<!doctype html>
<html>
  <head>
    <title>express + webpack</title>
  </head>
  <body>
    <script src="./example_public_path/main.js"></script>
  </body>
</html>


./src/foo.js

export default () => {
  return 'from foo!';
}


./src/bar.js

export default () => {
  return 'from bar!';
}


./src/index.js
下部にてHMRを実行するための記述をしています。
ファイルが編集されるとサーバーから変更の通知を受け取り、module.hot.accept()の第1引数で指定したJSが変更されていた場合に第2引数のコールバックが実行されます。
コールバックによってbodyタグを再描画しています。

import _ from 'lodash';
import foo from './foo.js'
import bar from './bar.js'

const expressAndWebpack = () => {
  let body = document.querySelector('body');
  body.innerHTML = '';
  body.innerHTML = _.join(['Hello', 'express', '+', 'webpack'], ' ');
  body.innerHTML += `<br>${foo()}`;
  body.innerHTML += `<br>${bar()}`;
  return body;
}
expressAndWebpack();

// HMRに対応していれば
if (module.hot) {
  // 第1引数のJSが変更された際に、第2引数のコールバックをブラウザ側で実行する
  module.hot.accept(['./foo.js', './bar.js'], () => {
    expressAndWebpack();
  });
};

4. コマンドラインでWEBサーバー(express)を立ち上げる

以下のコマンドを実行して、WEBサーバーを立ち上げます。

npm run dev

上記のコマンドは./package.jsonに定義してあり、以下のコマンドと同等です。

node server

5. ブラウザでアクセスして確認する

以下のURLにアクセスします。

http://localhost:8080/

以下のように表示されていれば成功です。

Hello express + webpack
from foo!
from bar!

6. JSファイルを編集し、ブラウザに反映された結果を確認する

WEBサーバーを立ち上げたまま、JSファイルを編集します。
以下のJSファイルを編集して保存します。

./src/foo.js

export default () => {
  return 'from foo!';
}

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

export default () => {
  return 'FROM FOO!!';
}

表示が以下のように即座に変更されれば成功です。

Hello express + webpack
from foo!
from bar!

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

Hello express + webpack
FROM FOO!!
from bar!

webpackとbabelを組み合わせてIE11対応をする最小構成を試す

webpackとは?

複数ファイルに分けて管理しているJS(モジュール)を一つのファイルにまとめてくれるツール(モジュールバンドラー)です。
別の記事(webpackの最小構成を試す)が参考になります。
※正確には1つのファイルとは限りませんが、役割に応じてファイルをまとめられます

babelとは?

ブラウザがまだ対応していない最新のJavaScriptソースコードを、ブラウザが対応しているソースコードへ変換してくれるツール (トランスパイラ)です。 別の記事(Babelの最小構成を試す)が参考になります。

webpackとbabelを組み合わせる

webpackとBabelを組み合わせれば、複数ファイルに分けて管理しているJSを一つのファイルにまとめながら、ブラウザがまだ対応していない最新のJSのソースコードを、ブラウザが対応しているソースコードへ変換させることができます。
(略:モジュールをバンドルしながらトランスパイルさせられる)

例えば、4つのJSファイルを1つにまとめたmain.js(名前は任意)を作成しながら
※今回はソースマップのファイルも作成します。

<script src="lodash.js"></script>
<script src="foo.js"></script>
<script src="bar.js"></script>
<script src="index.js"></script>

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

<script src="main.js"></script>

IE11では動作させることができなかったコードを動作可能なコードに変換できます。

// アロー関数はIE11で動作しない
const component = () => {
  let element = document.createElement('div');
  element.innerHTML = _.join(['Hello', 'webpack'], ' ');
  return element;
}

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

var component = function component() {
  var element = document.createElement('div');
  element.innerHTML = _.join(['Hello', 'webpack'], ' ');
  return element;
};

コマンドラインから実行できるようにする

以下がインストールされていることを前提としています。

  • node.js
  • npm

以下が手順概要です。

  1. npmでプロジェクトを作る
  2. webpackとBabel等をインストールする
  3. 必要なファイルを手動で作成する
  4. コマンドラインからwebpackを実行する(Babelはwebpackの中で動作する)
  5. 確認する

1. npmでプロジェクトを作る

任意のディレクトリで以下のコマンドを実行します。

mkdir webpack-babel-demo
cd webpack-babel-demo
npm init -y

2. webpackとBabel等をインストールする

以下のコマンドを実行します。

npm install -D webpack webpack-cli
npm install -D babel-loader @babel/core @babel/preset-env
npm install --save @babel/polyfill
npm install --save lodash

3. 必要なファイルを手動で作成する

以下のディレクトリ、ファイルを作成します。

  • webpack.config.js
  • babel.config.js
  • ./src/foo.js
  • ./src/bar.js
  • ./src/index.js
  • ./dist/index.html

以下のようなディレクトリ構造になるはずです。

│  package.json
│  babel.config.js
│  webpack.config.js
│
├─dist
│
├─node_modules
│  └─etc...
└─src
    bar.js
    foo.js
    index.js

package.jsonを以下のように書き換えます。

  • - "main": "index.js",
  • + "private": true,
  • + "build": "webpack",
{
  "name": "webpack-babel-demo",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
    "build": "webpack",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.4.0",
    "@babel/preset-env": "^7.4.2",
    "babel-loader": "^8.0.5",
    "webpack": "^4.29.6",
    "webpack-cli": "^3.3.0"
  },
  "dependencies": {
    "@babel/polyfill": "^7.4.0",
    "lodash": "^4.17.11"
  }
}

webpack.config.jsの内容を次のようにし、webpackの動作を設定します。

const path = require('path');

module.exports = {
  mode: 'development',
  devtool: 'source-map', // ソースマップを作成する
  entry:  './src/index.js', // webpackが最初にエントリーするファイル名
  output: {
    filename: 'main.js', // 出力されるファイル名
    path: path.resolve(__dirname, 'dist') // 出力されるディレクトリ
  },
  module: {
    rules: [
      {
        test: /\.js$/, // 拡張子がjsであり、
        exclude: /(node_modules)/, // それがnode_moduleディレクトリの外のファイルであれば、
        use: {
          loader: 'babel-loader' // Babelを実行する
        }
      }
    ]
  }
};

babel.config.jsの内容を次のようにし、Babelの動作を設定します。

const presets = [
  [
    "@babel/env",
    {
      targets: {
        ie: '11'
      },
      useBuiltIns: "usage"
    }
  ]
];

module.exports = { presets };

./src/foo.js

export default () => {
  return 'from foo!';
}

./src/bar.js

export default () => {
  return 'from bar!';
}

./src/index.js

import _ from 'lodash';
import foo from './foo.js'
import bar from './bar.js'

const webpackAndBabel = () => {
  let element = document.createElement('div');
  element.innerHTML = _.join(['Hello', 'webpack'], ' ');
  element.innerHTML += `<br>${foo()}`;
  element.innerHTML += `<br>${bar()}`;
  return element;
}

document.body.appendChild(webpackAndBabel());

./dist/index.html

<!doctype html>
<html>
  <head>
    <title>webpack + babel</title>
  </head>
  <body>
    <script src="main.js"></script>
  </body>
</html>

4. コマンドラインからwebpackを実行する(Babelはwebpackの中で動作する)

プロジェクトのルートで以下のコマンドを実行します。

npm run build

上記のコマンドはpackage.jsonに定義してあり、以下と同等です。

npx webpack

5. 確認する

./dist/を開くと、以下のファイルが追加されています。

  • main.js
  • main.js.map

main.jsを開き、「webpackAndBabel」で文字列検索をかけてみます。すると、以下のような定義が見つかります。
IE11でも動作するコードに変換されていますね。

var webpackAndBabel = function webpackAndBabel() {
  var element = document.createElement('div');
  element.innerHTML = lodash__WEBPACK_IMPORTED_MODULE_0___default.a.join(['Hello', 'webpack'], ' ');
  element.innerHTML += "<br>".concat(Object(_foo_js__WEBPACK_IMPORTED_MODULE_1__["default"])());
  element.innerHTML += "<br>".concat(Object(_bar_js__WEBPACK_IMPORTED_MODULE_2__["default"])());
  return element;
};

また、IE11で./dist/index.htmlを開いてみます。 以下のように表示されていれば成功です。

Hello webpack
from foo!
from bar!

外部リンク

今回やったことのリポジトリ

Babelの最小構成を試す

Babelとは?

ブラウザがまだ対応していない最新のJavaScriptソースコードを、ブラウザが対応しているソースコードへ変換してくれるツールです。 トランスコンパイラとも呼ばれます。

例えば、以下のようなアロー関数を用いたJSはIE11で動作しません。

const sayHello = name => {
  console.log(`hello ${name}`);
}

Babelを用いると、次のようなIE11で動作するコードに変換(トランスパイル)してくれます。

var sayHello = function sayHello(name) {
  console.log("hello ".concat(name));
};

Babelを使ってソースコードを変換(トランスパイル)してみる

公式サイトを参考にしています。

コマンドラインからBabelを使用して、IE11では動作しないソースコードを、IE11でも動作するソースコードへ変換してみます。 以下がインストールされていることを前提とします。

  • node.js
  • npm

以下が手順概要です。

  1. Babelをインストールする
  2. 手動で必要なファイルを作成する
  3. コマンドラインからBabelを実行する
  4. 確認する

1. Babelをインストールする

任意のディレクトリで以下のコマンドを実行します。

mkdir babel-demo
cd babel-demo
npm init -y
npm install --save-dev @babel/core @babel/cli @babel/preset-env
npm install --save @babel/polyfill

babel-demoというディレクトリを作り、そのディレクトリをnpmのプロジェクトとして初期化し、Babelをインストールするというコマンド群になります。

2. 手動で必要なファイルを作成する

Babelをインストールしたディレクトリでに以下のファイルとディレクトリを追加します。

  • babel.config.js
  • /src/main.js
  • /lib/

この時点で、以下のようなディレクトリ構造になっているはずです。

│  package.json
│  babel.config.js
│
├─lib
│
├─node_modules
│  └─etc...
└─src
    main.js

main.jsの内容

const sayHello = name => {
  console.log(`hello ${name}`);
}

babel.config.jsの内容

const presets = [
  [
    "@babel/env",
    {
      targets: {
        ie: "11"
      },
      useBuiltIns: "usage",
    }
  ]
];

module.exports = { presets };

このファイルはBabelの動作を決定するコンフィグを定義しています。 IE11に対応するソースコードに変換するための設定を記述します。

コマンドラインからBabelを実行する

以下のコマンドを実行します。

npx babel src --out-dir lib

srcディレクトリのファイルを全て変換(トランスパイル)し、libディレクトリに変換後のファイルを配置するというコマンドになります。

確認する

libディレクトリにmain.jsが配置されていることを確認し、ファイルを開いてみます。

以下のようなソースコードが記述されていれば成功です。

"use strict";

var sayHello = function sayHello(name) {
  console.log("hello ".concat(name));
};

デザインを説明するってどうすることなんやろうか?

f:id:sho_ya:20190320130245j:plain

少し立ち読みしてから買ってみた。デザイナーに限らず、製品に関る人に幅広く読まれているデザインの基礎本だそうだ。

僕が主に興味があるデザインは、普段使いするアプリケーションのデザインだ。機能性やコンテンツの中身がより重視される場面だと思っている。例えば、恋人には映画的な尖った要素やエピソードを求めがちだけど、結婚相手には互いに生活をサポートし合えることが重視される点に似ている気がする。

アプリケーションも使い始めは便利そうに見えたり使いやすそうに見えることが重視されるけど、普段使いされるアプリケーションに選ばれるのは、サポート力が高いものだと思っている。

だから、今僕はシングルページアプリケーション(SPA)をテーマにしている。何でSPAだとサポート力が高いアプリケーションが作れると思っているのかというと、前の仕事で作っていたとか、SPAのWEBアプリ(Airbnbとか)で凄く良い体験したとかいろいろある。既存のものより使いやすかったり、もっと人が何かを考えるためのツールにできたり、濃く使いぬくことができるものを作れる気がしている。そんな所が面白そうで開発している。

では、使いやすいってどういうことなのか?
そして、そんなアプリケーションを作るには何を考えることが大事なのか?

という疑問に対して、僕は今とりあえずSPAを作ってみればいいじゃんというアプローチをとっているけれど、作ったものを言語化して説明することが思ったより高い壁だったことに気づいた。
この「誰のためのデザイン?」を立ち読みしてみると、そのための語彙力が早くも少しインストールされてきて面白かったので買ってみた。

しかし、デザイナーの人達はデザインを何を根拠にして説明したり、テーマを積み上げているんだろう。

webpackの最小構成を試す

webpackとは?

複数ファイルに分けて管理しているjs(モジュール)を一つのファイルにまとめてくれるツール(モジュールバンドラー)です。
(正確には1つのファイルとは限りませんが、役割に応じてファイルをまとめられます)

以下のように、lodash.jsとindex.jsの2つのファイルをロードしているHTMLがあるとします。

<script src="https://unpkg.com/lodash@4.16.6"></script>
<script src="index.js"></script>

webpackを使用すると、上記2つのjsを1つにまとめたmain.js(名前は任意)を作成してくれます。

<script src="https://unpkg.com/lodash@4.16.6"></script>
<script src="index.js"></script>

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

<script src="main.js"></script>

2ファイル程度ではあまり恩恵を感じませんが、ソースコードが非常に長くなってきた時にファイル単位で処理を分割するとどんどんファイルが増えます。そういった時にパフォーマンス面等でファイル数が問題にならなくなるので、管理することに集中しやすくなって便利です。

また、新しく作成されたファイルのことをバンドルファイル(bundle:束の意)と言ったりします。こういった言葉と実際の意味をちゃんと繋げておくことも他人のソースを読んだりAPIリファレンスを読む際に必要になります。

以下では実際に手を動かし、上記と同じことを実施します。

webpackを使ってファイルをまとめてみる(バンドルしてみる)

公式サイトを参考にしています。

また、以下がインストールされていることを前提に記述しています。
・node.js
・npm

以下は手順の概要です。

  1. 必要なモジュールをインストールする
    • webpack
    • webpack-cli
    • lodash
  2. package.jsonを書き換える
  3. 必要なファイルを手動で作成する
    • ./webpack.config.js
    • ./dist/index.html
    • ./src/index.js
  4. webpackのコマンドでlodashとindex.jsをまとめた(バンドルした)main.jsを作成する
  5. 確認する

1. 必要なモジュールをインストールする

任意のディレクトリで、以下のコマンドを続けて実行します。

mkdir webpack-demo && cd webpack-demo
npm init -y
npm install webpack webpack-cli --save-dev
npm install --save lodash

上記を実行すると、以下のファイルやディレクトリ等が作成されます。

│  package.json
│
└─node_modules
  ├─lodash
  ├─webpack
  ├─webpack-cli
  └─etc...

package.jsonの内容です。

{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
  "webpack": "^4.29.6",
  "webpack-cli": "^3.3.0"
  },
  "dependencies": {
  "lodash": "^4.17.11"
  }
}

2. package.jsonを書き換える

以下のように書き換えます。

  • - "main": "index.js",
  • + "private": true,
  • + "build": "webpack",


{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
  "build": "webpack",
  "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
  "webpack": "^4.29.6",
  "webpack-cli": "^3.3.0"
  },
  "dependencies": {
  "lodash": "^4.17.11"
  }
}

3. 必要なファイルを手動で作成する

続いて、手動で以下のファイルを作成します * ./webpack.config.js * ./dist/index.html * ./src/index.js

./webpack.config.jsの内容

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
  filename: 'main.js',
  path: path.resolve(__dirname, 'dist')
  }
};

./dist/index.htmlの内容
読み込むjsファイルはindex.jsではなく、バンドルファイルとなるmain.jsを指定します

<!doctype html>
<html>
  <head>
    <title>Getting Started</title>
  </head>
  <body>
    <script src="main.js"></script>
  </body>
</html>

./src/index.jsの内容
importでlodashを指定します。

import _ from 'lodash';

function component() {
  let element = document.createElement('div');

  element.innerHTML = _.join(['Hello', 'webpack'], ' ');

  return element;
}
    
document.body.appendChild(component());

以下のディレクトリ構造になります。

│  package.json
│  webpack.config.js
│
├─dist
│   index.html
│
├─node_modules
│  ├─lodash
│  ├─webpack
│  ├─webpack-cli
│  └─etc...
└─src
    index.js

4. webpackのコマンドでlodashとindex.jsをまとめた(バンドルした)main.jsを作成する

以下のコマンドを実行します。

npm run build

上記コマンドは、package.jsonにてbuildコマンドに対してwebpackを指定しているため、以下のコマンドと同等になります。

npx webpack

ここまで実行すると、./dist/main.jsが自動で作成されます。 以下のディレクトリ構造になっています。

│  package.json
│  webpack.config.js
│
├─dist
│   index.html
│   main.js
│
├─node_modules
│  ├─lodash
│  ├─webpack
│  ├─webpack-cli
│  └─etc...
└─src
    index.js

5. 確認する

./dist/main.jsを開くと、ソースが圧縮されています。
index.jsと、index.jsからインポートしたlodashが圧縮して記述されています。 また、index.htmlを開くと、「Hello webpack」と表示されることがわかります。

参考

公式サイト

【メモ】Vue.jsでサーバサイドレンダリングを最小限に行う

公式のVue.jsサイトのデモにあるHackerNewsクローンをコードリーディングする前段階として、公式のVue SSR ガイドに掲載されている最小限のSSRを試したのでメモ。

const Vue = require('vue')
const server = require('express')()
const renderer = require('vue-server-renderer').createRenderer()

server.get('*', (req, res) => {
  const app = new Vue({
    data: {
      url: req.url
    },
    template: `<div>The visited URL is: {{ url }}</div>`
  })

  renderer.renderToString(app, (err, html) => {{
    if (err) {
      res.status(500).end('internal server error')
    }
    res.end(`
      <!DOCTYPE html>
      <html lang="ja">
      <head>
        <title>hello</title>
      </head>
      <body>
        ${html}
      </body>
    `)
  }})
})

server.listen(8080)

server.get()

第1引数に、URLのパターンマッチングを渡し、マッチするURLでHTTPリクエストを受け取ると第2引数のコールバックが実行されます。今回はアスタリスクなので、全てのURLでマッチします。
第2引数のコールバックにはRequest、Responseオブジェクトが渡されます。

RequestオブジェクトはHTTPリクエスト関連の情報を取得できますが、中にはNodeのhttp module等から引き継いでいるプロパティ等もあるそうです。 Responseオブジェクトも同様です。

APIリファレンスを見ると、Requestは読み取り系のプロパティが豊富ですが、Responseはこれからクライアントへ送信する情報を決定するため、HTTPレスポンスを編集するメソッドが豊富なイメージです。

renderer.renderToString()

第一引数に渡したVueのインスタンスを内部でレンダリングし、静的な文字列を生成しています。 このメソッドによって初期表示のHTMLが生成されているようです。
生成された文字列は第二引数のコールバックに渡されます。

このdemoではVueのインスタンスを文字列に変換していましたが、ストリームでの対応もしているようです。 HTMLをチャンク単位で破片毎に生成するということだと思いますが、個人的には今は出番は無さそうです。

res.end()

レスポンスの処理が終了した際に呼び出します。 HTTPレスポンスのボディになるデータを引数で渡します。

server.listen()

HTTPサーバーの待ち受けを開始します。 引数には使用するポートを指定します。

Raspberry Pi3 Model B(ラズパイ)と、教育向けコンピュータ

f:id:sho_ya:20181206151658p:plain

Raspberry Piを使おうとしていると、偶然木苺をもらった。なるほど。うまい。小学生の頃はよく食べた気がする。この時期は味は薄いが、旬だとジャムも作れるくらいになるらしい。


f:id:sho_ya:20181206152202j:plain 今日、Raspberry Pi3 model B(通称ラズパイ)にOSをインストールし、少し触ってみた。 ラズパイとは、イギリスのラズベリーパイ財団によって、教育用途を意図して開発されているコンピュータである。 コンピュータとは言ったが、小さな一枚の基板の上にCPUやUSB等、必要最小限の部品で構築されており、5000円程度で入手できる。

「Model B」という名は、1980年代にイギリスで教育向けコンピューターとして普及した「BBC Micro Model B」の流れを組む意味合いがあるのだろう。他にはModel Aなどもある。

教育向けコンピュータBBC Microシリーズは、英国放送協会の「BBC Computer Literacy Project」と呼ばれる、一般人向けのコンピューター啓発プロジェクトの中で仕様が提案された。

そして数ある企業の中で、主に学生で構成されたチームを持つエイコーン社によって開発されたマシンが採用され、販売された。このマシンは採用を競ったマシンにおいてほとんど全ての面で優れていたそうだ。
この後継機の開発の中でARMアーキテクチャのCPUが生まれ、それは僕達のスマートホン等で今でも動いているCPUの先祖にあたる。

僕が何故こんな話を書いているかというと、このBBC Microの「ストーリー」に少し興味を持ったからだ。

  • ARMアーキテクチャという今でも身近な技術がここで生まれたという技術的なこと。
  • 学生がメインの開発チームという、一般的に不安要素となるマシンだったとしても、素晴らしいマシンを採用する英国放送協会のスタンス。

など、面白そうな開発物語がありそうな気がしたのだ。

あと、色々妄想もした。
もしも、BBC Microに採用されるマシンが他の開発チームのマシンとなり、ARMアーキテクチャは世に出ず、ジョブズiphoneが作れなかったかもしれないな、と思うと少し面白い。
iphoneはハード、ソフト共に素晴らしいUIを持つ製品だと思うが、ハードウェアの進化がジョブズの時代に無ければiphoneも生まれなかっただろう。
まあ、ムーアの法則を思えば杞憂かもしれないけれど。

話を戻す。 今回ラズパイを使える状態にした目的は、機械学習、そしてディープラーニングを用いて人工知能の育成を行うためだ。

通常、本格的に人工知能の育成を行うには、ハイエンドのGPUカードを使う必要がある(1枚10万など)。
ラズパイは安価であるため、今回は基礎的な学習が目的となる。学習とはいえ、かなり面白そうなテーマなので今後も詳細を書きたい。