[three-dots] spinnerを実装してみる

Github: https://github.com/nzbin/three-dots

$ npm install three-dots –save

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<link href="/node_modules/three-dots/dist/three-dots.css" rel="stylesheet">
	<style>
		.spinner {
			margin: 50px;
		}
	</style>
</head>
<body>
	<div class="spinner">
		<div class="dot-elastic"></div>
	</div>
</body>
</html>

なるほど、CSSで表現できるのね。処理に時間がかかる時に使えそうですな。

node.jsのhttpモジュールの中身ってどうなってるの?

node.jsはノンブロッキング処理

// nodeが用意しているhttpモジュール
var http = require('http');
var server = http.createServer();

// server.onでイベント待ち受け
// 引数はリクエストとレスポンスのオブジェクト
server.on('request', function(req, res){
	// httpのステータスコード200
	res.writeHead(200, {'Content-Type': 'text/plain'});
	res.write('hello world');
	res.end();
});

// サーバを待ち受け状態する
server.listen(1337);
console.log("server listening...");

httpモジュールを読み込んで、リクエストに対してレスポンスを記述している。listenはサーバのポート。
さて、この具体的に”http module”って何? 公式ドキュメントを見ます。

HTTP | Node.js
https://nodejs.org/api/http.html#http_http
– Class: http.Agent
— new Agent([options]), agent.createConnection(options[, callback]), agent.keepSocketAlive(socket), agent.reuseSocket(socket, request), agent.destroy(), agent.freeSockets, agent.getName(options), agent.maxFreeSockets, agent.maxSockets, agent.requests, agent.sockets
– Class: http.ClientRequest
— Event: ‘abort’, Event: ‘connect’, Event: ‘continue’, Event: ‘information’, Event: ‘response’, Event: ‘socket’, Event: ‘timeout’, Event: ‘upgrade’, request.abort(), request.aborted, request.end([data[, encoding]][, callback]), request.flushHeaders(), request.getHeader(name), request.maxHeadersCount, request.path, request.removeHeader(name), request.reusedSocket, request.setHeader(name, value), request.setNoDelay([noDelay]), request.setSocketKeepAlive([enable][, initialDelay]), request.setTimeout(timeout[, callback]), request.socket, request.writableEnded, request.writableFinished, request.write(chunk[, encoding][, callback])
– Class: http.Server
— Event: ‘checkContinue’, Event: ‘checkExpectation’, Event: ‘clientError’, Event: ‘close’, Event: ‘connect’, Event: ‘connection’, Event: ‘request’, Event: ‘upgrade’, server.close([callback]), server.headersTimeout, server.listen(), server.listening, server.maxHeadersCount, server.setTimeout([msecs][, callback]), server.timeout, server.keepAliveTimeout
– Class: http.ServerResponse
— Event: ‘close’, Event: ‘finish’, response.addTrailers(headers), response.cork(), response.end([data[, encoding]][, callback]), response.flushHeaders(), response.getHeader(name), response.getHeaderNames(), response.getHeaders(), response.hasHeader(name), response.headersSent, response.removeHeader(name), response.sendDate, response.setHeader(name, value), response.setTimeout(msecs[, callback]), response.socket, response.statusCode, response.statusMessage, response.uncork(), response.writableEnded, response.writableFinished, response.write(chunk[, encoding][, callback]), response.writeContinue(), response.writeHead(statusCode[, statusMessage][, headers]), response.writeProcessing()
– Class: http.IncomingMessage
— Event: ‘aborted’, Event: ‘close’, message.aborted, message.complete, message.destroy([error]), message.headers, message.httpVersion, message.method, message.rawHeaders, message.rawTrailers, message.setTimeout(msecs[, callback]), message.socket, message.statusCode, message.statusMessage, message.trailers, message.url
– http.METHODS
– http.STATUS_CODES
– http.createServer([options][, requestListener])
– http.get(options[, callback])
– http.get(url[, options][, callback])
– http.globalAgent
– http.maxHeaderSize
– http.request(options[, callback])
– http.request(url[, options][, callback])

主に(1)agent, (2)client request, (3)server, (4)server response, (5)incoming responseを提供しています。

apacheのgit hubを見ます。 https://github.com/apache/httpd
apacheのモジュールと比べると大分シンプルなように見えるが、それにしても、量的にボリュームがあるな。
あれ、待てよ、各言語やフレームワークでビルトインサーバーの機能があるけど、あれって、nodeのhttpモジュールのように、requestやresponseを各言語でserver機能として書いているってこと??
こりゃ参ったね。。 何をやっても、結局、C言語やらないと駄目って結論になるな。

npmでReact.jsの環境を作る

react-calendarがnpmなので、npmで環境を作ります。

$ npm init
$ npm install –save-dev webpack webpack-cli webpack-dev-server
$ npm install –save-dev @babel/core @babel/preset-env @babel/preset-react babel-loader

ここまでは、これまでやってきた通り

$ npm install –save-dev react react-dom
npm ERR! code ENOSELF
npm ERR! Refusing to install package with name “react” under a package

?? package.jsonのnameがreactで同じだからインストールできないとのこと
“name”: “react1” に変更して、再度実行

$ npm install –save-dev react react-dom

続いてwebpackの設定

var debug = process.env.NODE_ENV !== "production";
var webpack = require('webpack');
var path = require('path');

module.exports = {
	context:math.josin(__dirname, "src"),
	entry: "./js/client.js",
	module: {
		rules: [{
			text: /\.jsx?$/,
				exclude: /(node_modules|bower_components)/,
				use: [{
					loader: 'babel-loader',
					options: {
						presents: ['@babel/preset-react', '@babel/preset-env']
					}
				}]
		}]
	},
	output: {
		path: __dirname + "/src/",
		filename: "client.min.js"
	},
	plugins: debug ? [] : [
		new webpack.optimize.OccurrenceOrderPlugin(),
		new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false}),
	]
};

./src/index.html

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>React</title>
	<link href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.6/cosmo/bootstrap.min.css" type="text/css" rel="stylesheet"/>
</head>
<body>
	<div id="app"></div>
	<script src="client.min.js"></script>
</body>
</html>

ここまでで、Reactの環境構築完了!?

import React from "react"
import ReactDOM from "react-dom"

class Layout extends React.Component {
	render(){
		return (
			<h1>Welcome</h1>
		);
	}
}

const app = document.getElementById('app');
ReactDOM.render(<Layout/>, app);

[vagrant@localhost react]$ webpack –mode development
Hash: 12eaf7dc67869ad64caf
Version: webpack 4.41.2
Time: 1874ms
Built at: 2019-11-20 15:39:17
Asset Size Chunks Chunk Names
client.min.js 1.08 MiB main [emitted] main
Entrypoint main = client.min.js
[./js/client.js] 2.69 KiB {main} [built]
+ 11 hidden modules

何言いいいいいいいいいいいいいい

npm i –save-devの “–save-dev”とは?

–save-dev は、ローカルインストール
-g がグローバルインストール
-gをつけないと、ローカルインストールになる

ローカルインストールの場合は、node_modulesにパッケージがインストールされる
ローカルに入れると、package.jsonのdevDependenciesに追記される

webpackとは?

WebpackはNode.jsでサーバーサイドで動かすモジュールハンドラー
-npmはJSライブラリのバージョン管理
-Bowerはフロントエンドのライブラリ管理
-Gulp:タスクランナー
-webpackはJSファイルのコーディングで手助け(JS,CSSのバンドリング)
https://webpack.js.org/

ん?npmとは違うのね。
Webpackもlessやsassのコンパイラツールのようなもの。
え?それなら、gulpはいらない??
gulpはsassのコンパイル

webpackは自分で書いたJSとライブラリのjsを一つにまとめる
JSで読み込むライブラリもまとめる
JS, CSS、画像ファイルをDataURI(base64)で一つのjsにまとめる

うん、なんかイマイチよくわからない。
複数のJSファイルをまとめられる、ってことはわかった。
Babelも用いる

とりあえず、npm initから
[vagrant@localhost front]$ npm init -y
Wrote to /home/vagrant/front/package.json:

{
“name”: “front”,
“version”: “1.0.0”,
“description”: “”,
“main”: “index.js”,
“scripts”: {
“test”: “echo \”Error: no test specified\” && exit 1″
},
“keywords”: [],
“author”: “”,
“license”: “ISC”
}

# インストール
$ npm i -D webpack webpack-cli

main.js

import { hello } from "./sub";

hello();

sub/sub.js

export function hello(){
    alert("hello method exection");
}

[vagrant@localhost front]$ npx webpack
Hash: e9a08af5f50ea936c82f
Version: webpack 4.41.2
Time: 163ms
Built at: 2019-11-19 23:43:38
Asset Size Chunks Chunk Names
main.js 982 bytes 0 [emitted] main
Entrypoint main = main.js
[0] ./src/index.js + 1 modules 104 bytes {0} [built]
| ./src/index.js 41 bytes [built]
| ./src/sub.js 63 bytes [built]

WARNING in configuration
The ‘mode’ option has not been set, webpack will fallback to ‘production’ for this value. Set ‘mode’ option to ‘development’ or ‘production’ to enable defaults for each environment.
You can also set it to ‘none’ to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="main.js"></script>
</head>
<body>

</body>
</html>

なんだこりゃ、あーこれか。webpackで書かれてたのか。なるほどねー
main.js

!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=0)}([function(e,t,r){"use strict";r.r(t),alert("hello method exection")}]);

puppeteerを入れよう

$ npm install –save puppeteer

main.js

const puppeteer = require('puppeteer');
const url = 'http://www.google.co.jp';

(async function(){
	const browser = await puppeteer.launch();
	const page = await browser.newPage();
	const response = await page.goto(url);

	await browser.close();
})();

[vagrant@localhost ~]$ node main.js
(node:9969) UnhandledPromiseRejectionWarning: Error: Failed to launch chrome!
/home/vagrant/node_modules/puppeteer/.local-chromium/linux-662092/chrome-linux/chrome: error while loading shared libraries: libXss.so.1: cannot open shared object file: No such file or directory

TROUBLESHOOTING: https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md

at onClose (/home/vagrant/node_modules/puppeteer/lib/Launcher.js:342:14)
at Interface.helper.addEventListener (/home/vagrant/node_modules/puppeteer/lib/Launcher.js:331:50)
at Interface.emit (events.js:187:15)
at Interface.close (readline.js:379:8)
at Socket.onend (readline.js:157:10)
at Socket.emit (events.js:187:15)
at endReadableNT (_stream_readable.js:1094:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
(node:9969) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:9969) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

あれれ

SyntaxError: Use of const in strict mode.

JavaScript has introduced const and let in ECMAScript 2015, which is relatively recent. This is enabled by default in Node.js since Node.js 4.x.

$ git clone git://github.com/creationix/nvm.git ~/.nvm
$ source ~/.nvm/nvm.sh
$ nvm help
$ nvm ls-remote
[root@localhost vagrant]# nvm install v8.16.0
Downloading and installing node v8.16.0…
Downloading https://nodejs.org/dist/v8.16.0/node-v8.16.0-linux-x64.tar.xz…
######################################################################## 100.0%
Computing checksum with sha256sum
Checksums matched!
Now using node v8.16.0 (npm v6.4.1)
[root@localhost vagrant]# node -v
v8.16.0

[root@localhost test]# node chromeTest.js
/home/vagrant/local/app/test/chromeTest.js:3
var By = webdriver.By;
^

ReferenceError: webdriver is not defined
at Object. (/home/vagrant/local/app/test/chromeTest.js:3:10)
at Module._compile (module.js:653:30)
at Object.Module._extensions..js (module.js:664:10)
at Module.load (module.js:566:32)
at tryModuleLoad (module.js:506:12)
at Function.Module._load (module.js:498:3)
at Function.Module.runMain (module.js:694:10)
at startup (bootstrap_node.js:204:16)
at bootstrap_node.js:625:3

What…

Error: EACCES

[vagrant@localhost test]$ sudo chmod 777 /usr/local/lib;

[vagrant@localhost test]$ sudo npm install -g bower
npm http GET https://registry.npmjs.org/bower
npm http 200 https://registry.npmjs.org/bower
npm WARN deprecated bower@1.8.8: We don’t recommend using Bower for new projects. Please consider Yarn and Webpack or Parcel. You can read how to migrate legacy project here: https://bower.io/blog/2017/how-to-migrate-away-from-bower/
npm http GET https://registry.npmjs.org/bower/-/bower-1.8.8.tgz
npm http 200 https://registry.npmjs.org/bower/-/bower-1.8.8.tgz
/usr/bin/bower -> /usr/lib/node_modules/bower/bin/bower
npm WARN unmet dependency /usr/lib/node_modules/block-stream requires inherits@’~2.0.0′ but will load
npm WARN unmet dependency undefined,
npm WARN unmet dependency which is version undefined
npm WARN unmet dependency /usr/lib/node_modules/fstream requires inherits@’~2.0.0′ but will load
npm WARN unmet dependency undefined,
npm WARN unmet dependency which is version undefined
npm WARN unmet dependency /usr/lib/node_modules/fstream-ignore requires inherits@’2′ but will load
npm WARN unmet dependency undefined,
npm WARN unmet dependency which is version undefined
npm WARN unmet dependency /usr/lib/node_modules/fstream-npm requires inherits@’2′ but will load
npm WARN unmet dependency undefined,
npm WARN unmet dependency which is version undefined
npm WARN unmet dependency /usr/lib/node_modules/glob requires inherits@’2′ but will load
npm WARN unmet dependency undefined,
npm WARN unmet dependency which is version undefined
npm WARN unmet dependency /usr/lib/node_modules/npmconf requires inherits@’~2.0.0′ but will load
npm WARN unmet dependency undefined,
npm WARN unmet dependency which is version undefined
npm WARN unmet dependency /usr/lib/node_modules/tar requires inherits@’2′ but will load
npm WARN unmet dependency undefined,
npm WARN unmet dependency which is version undefined
bower@1.8.8 /usr/lib/node_modules/bower

Node.jp update

[vagrant@localhost test]$ node –version
v0.10.48
[vagrant@localhost test]$ npm –version
1.3.6
[vagrant@localhost test]$ n –latest
-bash: n: コマンドが見つかりません

There is a handy version control tool, n, which lets you check and update versions.

[vagrant@localhost test]$ npm install -g n
npm http GET https://registry.npmjs.org/n
npm http GET https://registry.npmjs.org/n
npm http GET https://registry.npmjs.org/n
npm ERR! Error: CERT_UNTRUSTED
npm ERR! at SecurePair. (tls.js:1430:32)
npm ERR! at SecurePair.emit (events.js:92:17)
npm ERR! at SecurePair.maybeInitFinished (tls.js:1029:10)
npm ERR! at CleartextStream.read [as _read] (tls.js:521:13)
npm ERR! at CleartextStream.Readable.read (_stream_readable.js:341:10)
npm ERR! at EncryptedStream.write [as _write] (tls.js:418:25)
npm ERR! at doWrite (_stream_writable.js:226:10)
npm ERR! at writeOrBuffer (_stream_writable.js:216:5)
npm ERR! at EncryptedStream.Writable.write (_stream_writable.js:183:11)
npm ERR! at write (_stream_readable.js:602:24)
npm ERR! If you need help, you may report this log at:
npm ERR!
npm ERR! or email it to:
npm ERR!

npm ERR! System Linux 2.6.32-754.3.5.el6.x86_64
npm ERR! command “node” “/usr/bin/npm” “install” “-g” “n”
npm ERR! cwd /home/vagrant/local/app/test
npm ERR! node -v v0.10.48
npm ERR! npm -v 1.3.6
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! /home/vagrant/local/app/test/npm-debug.log
npm ERR! not ok code 0

The reason is that SSL key validation is performed on the https registry, so once this setting is set to false, npm install will succeed.

vagrant@localhost test]$ npm config set strict-ssl false

[vagrant@localhost test]$ npm install -g n
npm http GET https://registry.npmjs.org/n
npm http 200 https://registry.npmjs.org/n
npm http GET https://registry.npmjs.org/n/-/n-4.1.0.tgz
npm http 200 https://registry.npmjs.org/n/-/n-4.1.0.tgz
npm ERR! Error: EACCES, mkdir ‘/usr/lib/node_modules/n’
npm ERR! { [Error: EACCES, mkdir ‘/usr/lib/node_modules/n’]
npm ERR! errno: 3,
npm ERR! code: ‘EACCES’,
npm ERR! path: ‘/usr/lib/node_modules/n’,
npm ERR! fstream_type: ‘Directory’,
npm ERR! fstream_path: ‘/usr/lib/node_modules/n’,
npm ERR! fstream_class: ‘DirWriter’,
npm ERR! fstream_stack:
npm ERR! [ ‘/usr/lib/node_modules/fstream/lib/dir-writer.js:36:23’,
npm ERR! ‘/usr/lib/node_modules/mkdirp/index.js:37:53’,
npm ERR! ‘Object.oncomplete (fs.js:108:15)’ ] }
npm ERR!
npm ERR! Please try running this command again as root/Administrator.

npm ERR! System Linux 2.6.32-754.3.5.el6.x86_64
npm ERR! command “node” “/usr/bin/npm” “install” “-g” “n”
npm ERR! cwd /home/vagrant/local/app/test
npm ERR! node -v v0.10.48
npm ERR! npm -v 1.3.6
npm ERR! path /usr/lib/node_modules/n
npm ERR! fstream_path /usr/lib/node_modules/n
npm ERR! fstream_type Directory
npm ERR! fstream_class DirWriter
npm ERR! code EACCES
npm ERR! errno 3
npm ERR! stack Error: EACCES, mkdir ‘/usr/lib/node_modules/n’
npm ERR! fstream_stack /usr/lib/node_modules/fstream/lib/dir-writer.js:36:23
npm ERR! fstream_stack /usr/lib/node_modules/mkdirp/index.js:37:53
npm ERR! fstream_stack Object.oncomplete (fs.js:108:15)
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! /home/vagrant/local/app/test/npm-debug.log
npm ERR! not ok code 0

This time with a different error, it says “Error: EACCES”.

node.jsを使ってvue-cliを入れよう

まずnpmを使えるようにします。
[vagrant@localhost python]$ source ~/.nvm/nvm.sh
[vagrant@localhost python]$ nvm ls
-> v10.7.0
system
default -> 10.7.0 (-> v10.7.0)
node -> stable (-> v10.7.0) (default)
stable -> 10.7 (-> v10.7.0) (default)
iojs -> N/A (default)
unstable -> N/A (default)
lts/* -> lts/carbon (-> N/A)
lts/argon -> v4.9.1 (-> N/A)
lts/boron -> v6.14.3 (-> N/A)
lts/carbon -> v8.11.3 (-> N/A)
[vagrant@localhost python]$ nvm use 10.7.0
Now using node v10.7.0 (npm v6.1.0)
[vagrant@localhost python]$ node -v
v10.7.0
[vagrant@localhost python]$ npm -v
6.1.0

続いてvue-cliをインストール
[vagrant@localhost python]$ npm install -g vue-cli
npm WARN deprecated coffee-script@1.12.7: CoffeeScript on NPM has moved to “coffeescript” (no hyphen)
/home/vagrant/.nvm/versions/node/v10.7.0/bin/vue -> /home/vagrant/.nvm/versions/node/v10.7.0/lib/node_modules/vue-cli/bin/vue
/home/vagrant/.nvm/versions/node/v10.7.0/bin/vue-init -> /home/vagrant/.nvm/versions/node/v10.7.0/lib/node_modules/vue-cli/bin/vue-init
/home/vagrant/.nvm/versions/node/v10.7.0/bin/vue-list -> /home/vagrant/.nvm/versions/node/v10.7.0/lib/node_modules/vue-cli/bin/vue-list
+ vue-cli@2.9.6
added 253 packages from 220 contributors in 90.959s

2.9.6ですね。
[vagrant@localhost python]$ vue –version
2.9.6