技術的な話題   

Windows ネイティブに動く php.exe を使って phpunit を動かしていたわけですが、どうにも --color をした時にカラーコードが反映されない。

いやそもそも Windows やんけ、という話は置いておき。

カラーコードが出来ないことで何か問題あるかってーとこれまた特にあるわけでもなく。とはいえ、あたまのいい人たちが何か考えてるでしょと思いながら調べたら解決した。

そもそもとして色が出るのは ANSI エスケープシーケンスに割り当たってるところに色定義があるからっぽい。 ANSI カラーコードとか、 xterm16 とか、そう呼ばれているっぽい。
背景的なところはわからなんだ。

ANSIエスケープコード - コンソール制御 - 碧色工房
ターミナルのANSIカラーの分布 - Folioscope
ターミナル環境のTrue Colorとは?意味やMac、Vimなどの対応状況まとめ | Simplie Post

で、コマンドプロンプトでどうすんねん、についてはこれをつかうと出来る。

adoxa/ansicon: Process ANSI escape sequences for Windows console programs.

ANSICON provides ANSI escape sequences for Windows console programs. It provides much the same functionality as ANSI.SYS does for MS-DOS.

といった、説明のとおり Windows において ANSI エスケープシーケンスを実現するためのツール。
使い方はこんな感じ。

上に書いたリポジトリをダウンロード。適当な場所において、 32 ビット OS なら x86 を。 64 ビット OS なら x64 のフォルダをエクスプローラーで開く。そのフォルダのパスをコピーしておく。

コマンドプロンプトの起動。レジストリ登録をするそうなので管理者権限がよいようにみえるけど…。

フォルダへ移動

ansicon -i の実行

コマンドプロンプトを再起動する。これでカラーコードが使えるようになる。例えばこんな風に。

余談だけど cmder や Cygwin といったターミナルを使っていた場合は、内部でよろしくやっているので、特に何もしなくても出る。

cmder、タブが使えたり Linux のそれっぽく振る舞ってくれたりして便利ちゃんでおすすめちゃん。

cmder | Console Emulator

Cygwin のそれみたいなもっさり感…?はない、と思うけど、Cygwin も昔さわった時にもっさりしてた気がするだけで、今は改善されているのかな…?どちらにしても結局のところ Windows なのはかわりないので、そういうところ気がきかないのね~~~みたいのがたまにあって、そういうときに辛みを感じる。

   技術的な話題   

Bitbucket Pipelines を使ってて、全く設定を変えていないのに MySQL に繋がったり繋がらなくなったりしていたので、どういうこっちゃ、というメモ。

結論から行くと 3 〜 5 秒くらい待ってあげればよい。

MySQL に繋がらない

エラーとしてはこんな感じ。ちなみにこの問題と直接関係はないが CakePHP 3.5 である。

+ bin/cake migrations migrate
using migration paths 
 - /opt/atlassian/pipelines/agent/build/config/Migrations
using seed paths 
 - /opt/atlassian/pipelines/agent/build/config/Seeds
Exception: There was a problem connecting to the database: SQLSTATE[HY000] [2002] Connection refused in [/opt/atlassian/pipelines/agent/build/vendor/robmorgan/phinx/src/Phinx/Db/Adapter/MysqlAdapter.php, line 115]
2017-10-16 10:57:41 Error: [InvalidArgumentException] There was a problem connecting to the database: SQLSTATE[HY000] [2002] Connection refused in /opt/atlassian/pipelines/agent/build/vendor/robmorgan/phinx/src/Phinx/Db/Adapter/MysqlAdapter.php on line 115
Stack Trace:
#0 /opt/atlassian/pipelines/agent/build/vendor/robmorgan/phinx/src/Phinx/Db/Adapter/PdoAdapter.php(238): Phinx\Db\Adapter\MysqlAdapter->connect()
#1 /opt/atlassian/pipelines/agent/build/vendor/cakephp/migrations/src/CakeAdapter.php(57): Phinx\Db\Adapter\PdoAdapter->getConnection()
#2 /opt/atlassian/pipelines/agent/build/vendor/cakephp/migrations/src/Command/CommandTrait.php(78): Migrations\CakeAdapter->__construct(Object(Phinx\Db\Adapter\MysqlAdapter), Object(Cake\Database\Connection))
#3 /opt/atlassian/pipelines/agent/build/vendor/robmorgan/phinx/src/Phinx/Console/Command/Migrate.php(72): Migrations\Command\Migrate->bootstrap(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#4 /opt/atlassian/pipelines/agent/build/vendor/cakephp/migrations/src/Command/CommandTrait.php(35): Phinx\Console\Command\Migrate->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#5 /opt/atlassian/pipelines/agent/build/vendor/cakephp/migrations/src/Command/Migrate.php(65): Migrations\Command\Migrate->parentExecute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#6 /opt/atlassian/pipelines/agent/build/vendor/symfony/console/Command/Command.php(262): Migrations\Command\Migrate->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#7 /opt/atlassian/pipelines/agent/build/vendor/symfony/console/Application.php(888): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#8 /opt/atlassian/pipelines/agent/build/vendor/symfony/console/Application.php(224): Symfony\Component\Console\Application->doRunCommand(Object(Migrations\Command\Migrate), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#9 /opt/atlassian/pipelines/agent/build/vendor/symfony/console/Application.php(125): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#10 /opt/atlassian/pipelines/agent/build/vendor/cakephp/migrations/src/Shell/MigrationsShell.php(101): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#11 /opt/atlassian/pipelines/agent/build/vendor/cakephp/cakephp/src/Console/Shell.php(508): Migrations\Shell\MigrationsShell->main('migrations', 'migrate')
#12 /opt/atlassian/pipelines/agent/build/vendor/cakephp/migrations/src/Shell/MigrationsShell.php(156): Cake\Console\Shell->runCommand(Array, true, Array)
#13 /opt/atlassian/pipelines/agent/build/vendor/cakephp/cakephp/src/Console/CommandRunner.php(141): Migrations\Shell\MigrationsShell->runCommand(Array, true)
#14 /opt/atlassian/pipelines/agent/build/bin/cake.php(12): Cake\Console\CommandRunner->run(Array)
#15 {main}
script:
	- composer install --no-interaction
	- chmod +x bin/cake
	- chmod -R 777 tmp/ logs/
	- bin/cake migrations migrate
	- composer test

bitbucket-pipelines.yml に記載した実行スクリプトに関してはこれだけなのだが、マイグレーションのところで、トピックブランチでは通って、マスターブランチでは通らず、なんてことがぼちぼち起きた。

Bitbucket Pipelines 上で MySQL のログが見えるので、これを確認すると、通らなかったときには、通ったときのログが途中できれているようなものだった。

Initializing database
...(中略)...

2017-10-16T01:57:41.831583Z 0 [Note] End of list of non-natively partitioned tables

成功した時はこんな感じの最終行になる。

2017-10-16T01:51:55.506134Z 0 [Note] InnoDB: Starting shutdown...
2017-10-16T01:51:55.606342Z 0 [Note] InnoDB: Dumping buffer pool(s) to /var/lib/mysql/ib_buffer_pool
2017-10-16T01:51:55.606688Z 0 [Note] InnoDB: Buffer pool(s) dump completed at 171016  1:51:55

つまり MySQL コンテナが何かしらの初期化処理をしていて、にも関わらず繋ごうとしたから接続できないエラー?そうして Bitbucket Pipelines がエラーを認識して停止。ふむ、納得出来る気がする。

アプリケーション側で接続時のタイムアウト設定

とりあえず思いつくスマートな方法はこれ。

このプロジェクトは CakePHP3 を使っているが CakePHP3 には接続時のタイムアウト設定な項目はないらしい。かなしい。とはいえ何かあるだろうとソースを読み進めると 最終的に PDO を使っているらしいことがわかる。ので PDO の設定方法を調べてみると PDO::ATTR_TIMEOUT というオプションを設定するとよいらしい。

php - Setting a connect timeout with PDO - Stack Overflow

このオプションを CakePHP3 で設定するには、コンフィグ内の flags にいれると出来そうなソースをしている。

cakephp/PDODriverTrait.php at master · cakephp/cakephp

$connection = new PDO(
	$dsn,
	$config['username'],
	$config['password'],
	$config['flags']
);

しかし入れても状況は改善されなかったので、違うらしい。。これはまたそのうち調べよう。。。

bitbucket-pipelines.yml に sleep を入れる

というわけでこっちの方法。yml (の抜粋)はこんな感じ。

script:
	- composer install --no-interaction
	- chmod +x bin/cake
	- chmod -R 777 tmp/ logs/
	- sleep 5
	- bin/cake migrations migrate
	- composer test

これで安定的に動いてくれているので、このままでいいか。

MySQL コンテナの初期化処理

そもそもとして MySQL コンテナの初期化処理って何をしているんだろうか。Dockerfile はここ。どうやら docker-entrypoint.sh が何かしていそうだ。

mysql/Dockerfile at master · docker-library/mysql
mysql/docker-entrypoint.sh at master · docker-library/mysql

すごいざっくり読むとこんなことをしているっぽい。

  • Docker イメージが提供するのは mysqld の準備~起動、 docker-entrypoint.sh の起動まで
  • docker-entrypoint.sh によって初回起動によるデータファイル構築。設定したデータベース、ユーザの準備。ちなみに途中で mysqld の再起動をしている。

なるほど理解。
やっぱりコンテナが立ち上がったと同時に初期化処理が走って、それが終わるまでは接続が出来ないようだ。

ものすごいバッドプラクティスを感じている sleep 5 なのでなんとかしたいものの、どうこうするのがいいのかイマイチわからないので、知見あるひと教えてほしス

   技術的な話題   

目次機能が出来るプラグインとかってあるけど、別に自分で作ってもいいよねって思ったので作った。そのうちモリモリっとテーマやプラグインの整備に力を入れていくので、そのあたりに介入されると困るので~~ってくらいの理由で作った次第。

これこれ!この目次! h2 タグを使うんだよ

2階層までなら対応するよ! h3 タグだよ

ここは h3 タグ

ここは h2 タグなので 1 階層目になる

ここは 2 階層。 h3 タグだからね

デモおわり

ここまで見出しだらけで見にくいのは仕方ない。

仕組み

  1. h2 タグと h3 タグを投稿箇所から探す
  2. それぞれのタグに ID をつける
  3. それぞれへのリンクを生成する
  4. 目次用の HTML を作る
  5. 一番最初の見出しの直前に HTML を挿入する

タイトルこそ WordPress って言ってるけど JavaScript が差し込めるブログサービス的なものなら、投稿箇所を探す部分を調整する必要はあるけど、どれでもできるんじゃないかな。
jQuery を使わなくていいように作ったので jQuery ないんだけど、みたいな環境でもいいと思う。いやそもそもそういう環境はまた違う問題っぽいけど…。

JavaScript

(function() {
	setTimeout(function() {
		var headingIndex = 1;
		Array.prototype.forEach.call(document.querySelectorAll('.post_content'), function(postContent) {
			var headings = postContent.querySelectorAll('h2,h3');
			if (headings.length <= 0) {
				return;
			}

			var indexHtml = '<ul>';
			var lastElement = 'H2';
			Array.prototype.forEach.call(headings, function(e) {
				var id = 'heading-' + headingIndex;
				e.id = id;
				if (lastElement != e.tagName) {
					if (lastElement == 'H2') {
						indexHtml += '<ul>';
					} else {
						indexHtml += '</ul>';
					}
					lastElement = e.tagName;
				}
				indexHtml += '<li><a href="#' + id + '">' + e.innerHTML + '</a></li>';
				headingIndex++;
			});
			indexHtml += '</ul>';

			var wrapper = document.createElement('div');
			wrapper.classList.add('content-index');
			wrapper.innerHTML = indexHtml;
			headings[0].parentNode.insertBefore(wrapper, headings[0]);
		});
	}, 0);
})();

CSS

.post_content .content-index {
	border: 2px solid #eee;
	border-radius: 20px;
	padding: 20px;
	background-color: #fefefe;
}

.post_content .content-index:before {
	content: '目次';
	display: block;
	font-size: 24.5px;
	margin-bottom: 15px;
}

他のスタイルとのバッティング回避した部分を除くとこれだけ。シンプルに線を引くことと色味の調整くらい。

SEO的な観点とか

目次足すと SEO に効果あるのかわからんけど、ふつうに見ていて、長めの投稿だったら合ったほうが便利だよね、とは感じる。

一応 Fetch as Google をして Google Bot にこの目次が認識されていることは確認したので、まあいいんじゃないかな。

   技術的な話題   

CakePHP 3 のクイックスタートを改めて見てたら composer create-project ... ってでてきて何だこいつは…ってなった話。

Quick Start Guide - 3.x

php composer.phar create-project --prefer-dist cakephp/app bookmarker

composer create-project がやること

要はドキュメントにあるので読めって話になる。

Command-line interface / Commands - Composer

You can use Composer to create new projects from an existing package. This is the equivalent of doing a git clone/svn checkout followed by a "composer install" of the vendors.

There are several applications for this:

1. You can deploy application packages.
2. You can check out any package and start developing on patches for example.
3. Projects with multiple developers can use this feature to bootstrap the initial application for development.

To create a new project using Composer you can use the "create-project" command. Pass it a package name, and the directory to create the project in. You can also provide a version as third argument, otherwise the latest version is used.

ざっくりと翻訳してみると、こんなことが書かれているようだ。

既にあるパッケージから新しいプロジェクトを作ります。それは git clone または svn checkout をして composer install を行うのと同等です。

1. アプリケーションパッケージをデプロイできる
2. パッケージをチェックアウトして開発をしていける
3. 新しい開発のため、ブートストラップな初期化を提供ができる

"create-project" コマンドによってそれは実行できる。パッケージ名、プロジェクトのディレクトリ名、そしてパッケージバージョンを指定できる。

CakePHP のドキュメントにあったコマンドを読み解く

php composer.phar create-project --prefer-dist cakephp/app bookmarker

まず指定されているパッケージを見てみる。

cakephp/app - Packagist

A skeleton for creating applications with CakePHP 3.x.

なるほど。つまり、空っぽの CakePHP アプリケーションがパッケージ登録されているので、それをもってくることで新規に空っぽの CakePHP アプリケーション作れるやん!ということだそうだ。

ところで --prefer-dist はなんだろう。 composer のドキュメントをもう一度見る。

--prefer-dist: Install packages from dist when available.

んーむ。 dist があればインストールするよって言ってるけどなんのことやら…? → install の項目にガッツリと書いてある。

--prefer-dist: Reverse of --prefer-source, Composer will install from dist if possible. This can speed up installs substantially on build servers and other use cases where you typically do not run updates of the vendors. It is also a way to circumvent problems with git if you do not have a proper setup.

--prefer-source の逆で、 dist からのインストールを優先する。これによってビルドサーバやアップデートをしないような環境では高速に動作する。あるいは git の設定をしてないときに問題を解決出来る。

--prefer-source の説明も合わせて読んだところ、どうやら composer は dist って呼ばれるところを基本的には利用するらしい。 source はバージョン管理リポジトリで、直接 git clone するようなものになっているので、設定をしてないと問題が起きたりするそう。 Github を直接見に行ってエラー、とかそういう感じなのかな?まあ、デフォルトでは dist なので --prefer-dist はあまり気にしなくても良さそう。

で。

3 つめの引数に書いてある bookmarker が作られるディレクトリだ。
カレントディレクトリに bookmarker というディレクトリが作られ、その中に cakephp/app パッケージの内容が展開されているはず。加えて composer install も行われているので bookmarker/vendor ディレクトリも作られている。

まとめ

要は git clone しまっせ、みたいなものだと思っておけばだいたい良さそうだ。

   技術的な話題   

出来ると思うんだけど~~って言いながら、なかなかやってなかったのでいい加減やった。

Docker Hub にアカウント登録

Docker Hub

右上からサインアップ出来る。適当な ID とメールアドレス、パスワードを入力すると良い。メールで確認がやってくるので、リンクぽちー。

以上で終わり。

Github でリポジトリを作る

Github にリポジトリを作っていきます。

Github 上からファイルの追加が出来るので、手元の Dockerfile をアップする。当然ながらパブリックなリポジトリで扱うのであれば、社外秘です!みたいな内容を含まないように気をつけて。パスワードとか、脆弱性ある古いバージョン使ってるじゃんとか、鍵が載ってるよとか、うっかり事故気をつけようね。

というわけで出来ました。

sters/docker-php7-cakephp3-base: docker base image for php7 x cakephp3

Docker Hub で Automated Build の設定をする

Docker Hub 側で自動ビルドが出来ます(便利!)URL が提供されるので、正しいトークンを送るとビルドキューへ追加され、自動でビルド、イメージの提供がされ始めます。
というわけで連携を進めていきます。

この URL および トークンを Github の Webhook に追加します。

ちなみに Docker Hub に Webhook もありますが、これはビルドが終わったときにそのイベントを指定した URL に通知できるものです。でっかいイメージを扱いたい時とか、ビルドしたイメージがちゃんと使えるかテストしたいとか、そういうときに使えるんじゃないですかね。

Github で Webhook の設定

Docker Hub で取得できたトリガーの URL を Github の Webhook に設定します。

とりあえずは Push された時、でいいと思います。タグが付いたとき、にすると Docker Hub 側でタグごとのビルドがされていきます。バージョニングしていく上ではそうするほうがいいでしょうね~。

Docker Hub で確認

ビルドが動き始めました。しばらく待つと完了します。

何事もなければこれでイメージが利用できるようになります。

 $ docker run -it --rm sters/php7-cakephp3-base "/bin/sh"

// ここからゲスト側

/ # composer
Do not run Composer as root/super user! See https://getcomposer.org/root for details
   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
Composer version 1.5.2 2017-09-11 16:59:25

Usage:
  command [options] [arguments]

Options:
  -h, --help                     Display this help message
  -q, --quiet                    Do not output any message
  -V, --version                  Display this application version
      --ansi                     Force ANSI output
      --no-ansi                  Disable ANSI output
  -n, --no-interaction           Do not ask any interactive question
      --profile                  Display timing and memory usage information
      --no-plugins               Whether to disable plugins.
  -d, --working-dir=WORKING-DIR  If specified, use the given directory as working directory.
  -v|vv|vvv, --verbose           Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Available commands:
  about           Shows the short information about Composer.
  archive         Creates an archive of this composer package.
  browse          Opens the package's repository URL or homepage in your browser.
  clear-cache     Clears composer's internal package cache.
  clearcache      Clears composer's internal package cache.
  config          Sets config options.
  create-project  Creates new project from a package into given directory.
  depends         Shows which packages cause the given package to be installed.
  diagnose        Diagnoses the system to identify common errors.
  dump-autoload   Dumps the autoloader.
  dumpautoload    Dumps the autoloader.
  exec            Executes a vendored binary/script.
  global          Allows running commands in the global composer dir ($COMPOSER_HOME).
  help            Displays help for a command
  home            Opens the package's repository URL or homepage in your browser.
  info            Shows information about packages.
  init            Creates a basic composer.json file in current directory.
  install         Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.
  licenses        Shows information about licenses of dependencies.
  list            Lists commands
  outdated        Shows a list of installed packages that have updates available, including their latest version.
  prohibits       Shows which packages prevent the given package from being installed.
  remove          Removes a package from the require or require-dev.
  require         Adds required packages to your composer.json and installs them.
  run-script      Runs the scripts defined in composer.json.
  search          Searches for packages.
  self-update     Updates composer.phar to the latest version.
  selfupdate      Updates composer.phar to the latest version.
  show            Shows information about packages.
  status          Shows a list of locally modified packages.
  suggests        Shows package suggestions.
  update          Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.
  upgrade         Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.
  validate        Validates a composer.json and composer.lock.
  why             Shows which packages cause the given package to be installed.
  why-not         Shows which packages prevent the given package from being installed.

/ # php -v
PHP 7.1.10 (cli) (built: Sep 30 2017 01:01:44) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies

/ # exit

おわり

基本的に Official なイメージを使うとおおよそ大丈夫だと思うけど、再ビルド必要です!とか拡張機能必要です!とか、そういう状況になったら都度やるのもアレなので、オレオレイメージを作ると便利ちゃん。

そういえば Docker Hub って Dcokerfile によって記述された Docker イメージを管理共有してくれているけど、 docker-compose.yml で記述されるコンテナ管理セットを共有する場ってあるのかな。ちょっと調べたけどクエリが悪いのか見つからず…。

   技術的な話題   

会社の PC で Office365 の Excel を使っているがここ最近で、置換のショートカットキーが効かなくなったような気がしている。

Ctrl + H を押しても置換ではなく、検索が開くのだ。まあ、置換タブを押せばいいだけなのだが。

で気になって調べた。

もしやショートカットキーが変わった?ということもあるので、公式のガイドを見る。

Windows 用 Excel キーボード ショートカットとファンクション キー - Excel

CTRL + H
[検索と置換] ダイアログ ボックスの [置換] タブを表示します。

間違いなく Ctrl + H だ。
特にアプリ追加したなどないし、再起動しても変わらない。はてさて。

日本語の情報が全く見つからなかったが、英語で同じような状況を検索すると同じ状況の困った!がヒット。

Excel Shortcut Keys ctrl+f and ctrl+h now gives the same function? - Microsoft Tech Community

I just want to know why would microsoft change the function of excel 2016 in pressing ctrl+h (Find and replace) and have it the same as pressing ctrl+f (Find fucntion)?? The recent update makes the shortcut keys the same. I mean it is really useful when you can a quickly press keys to find and replace. Instead they made it the same as find function only which really is really annoying and time consuming for excel advanced users.

公式コミュニティだ。そして全く同じ問題が起きている。
雑に訳すと「Excel 2016 を使ってるんだけど Ctrl + H の動きが Ctrl + F と一緒じゃね?」って言ってる。

ついている回答を挙げてみるとこんな感じ。

I updated couple of minutes ago on 1709.8528.2084, Ctrl+H works now in that build.
And I'm on Inseders Slow (now Monthly Channel if i remember correctly)

これまた雑に訳すと「アップデートしたら動くようになったよ!Insider の Slow チャンネルでは直っているからそのうちになおるかも?」みたいなことを言っている。ぼくは大きなダメージもないのでまったり待ち。

 

 

と思ったけど 10/06 の朝に更新をしてみたら治った。
更新は ファイル → アカウント を押して「 Office 更新プログラム」かアップデート確認・実行ができる。

ぼくの場合はこのタイミングで 1708.8431.2094 というビルド番号になり Ctrl + H が直ってた。

   読書や本   

「 CSS 設計の強化を読みました」って言ってたけどめっちゃ途中で止まっていたので完走しました。

前の記事
CSS設計の教科書を読んだ@途中まで | ごみばこいん Blog

読んだ本
Web制作者のためのCSS設計の教科書 モダンWeb開発に欠かせない「修正しやすいCSS」の設計手法 | 谷 拓樹 |本 | 通販 | Amazon

コンポーネント設計の実践

コンポーネントをどのように作るか。

コンポーネントを作るタイミングの問題。始めからあらゆる事態を想定してコンポーネントを作っていくことは困難であり、そんなところにパワーを使いすぎてはいけない。早すぎる最適化は悪の根源。 "YAGNI" (You ain't gonna need it.) = いらないものをつくらない。

"Rule of Three" はそれを解決するための 1 つの案。たとえば「3回繰り返すものがでてきたらコンポーネント化する」あるいは「別の3プロジェクトでも使うならコンポーネント化する」といった意識を持つのがよい。

粒度感の問題もある。ここについては、プログラミングにおける原理原則がCSSにおいても適用できることに着目し、「単一責任の原則」「開放・閉鎖の原則」などを意識するとよい。そもそも OOCSS ではオブジェクト指向プログラミングの考え方を CSS に取り入れた。

この章にはこの後、本の中では「コンポーネントの設計・実装パターン」としてボタンや見出しなど、筆者の経験上こうすることが多い、が書かれている。実際に1から作るとき、これを試してみるとよさげたん。

CSS プリプロセッサを用いた設計と管理

SMACSS や MCSS にはカテゴリやレイヤーといったルールが設けられていることを既に学んだ。これらを CSS の書き方の上でキレイに整えて書いていくことはなかなか大変。
そこで Sass を使うのがよい。Sass によってルールの構造化、使い回しなどが容易にできる。

Sass: Syntactically Awesome Style Sheets

コンポーネントの運用に必要なツール

コンポーネントを作る上で・・・。そもそも CSS を書く上でコメントを書くことは非常に大事。どんなところに提供されるルールなのか、なぜそういう書き方をしているのか、どのようなコンポーネント単位なのか。

CSS 設計をしたり、何かしらのルールを設けたのであれば、そのルールを文章化していくことが必要。全体の設計のやり方、細かいルール、ガイドラインといったことを記載するのがよい。なにせその CSS は他の人が受け継いでいくのだから。

どのようなコンポーネントがあるか、どんなクラスをつけるとどんな見た目になるか、といったスタイルガイド、パターンライブラリがあると、開発時に非常に便利になる。ある一定の決まりにそってコメントを記述すると自動で生成できるツールもあるので、活用するべし。
紹介されていたのはこれ。

KSS · Knyle Style Sheets
StyleDocco
thomasdavis/kaleistyleguide web サイトが終了しているようです。。

そのほか CSS 開発の効率を上げるために次のようなツールが紹介されていた。

  • csslint // 正しく書かれているか
  • stylestats // CSSの指標について数値化
  • autoprefixer // -webkit- などの自動付与
  • csscomb // 記述の並び替え、フォーマット
  • csso // 構造の最適化
  • Grunt, gulp // タスクランナー

Web Components の可能性

ここまで CSSの設計、ルール化によって壊れにくい、戦いやすいCSSが出来るようになった。しかし、それでも壊れる可能性は高い。それをこれからの未来に解決するための案が W3C で進められている Web Components という仕様だ。

Web Components は 4 つの技術から成り立つ。

  • Templates
    • マークアップと CSS を内包できる
  • Custom Elements
    • 独自の要素を定義できる
  • Shadow DOM
    • 隠蔽された DOM を作成できる
    • Templates と Custom Elements を組み合わせることで影響を受けない出さないコンポーネントを作成できる
  • HTML Imports
    • 外部の HTML ファイルを読み込める

まだ仕様策定中であり、利用できるブラウザも多くはないが Polymer というポリフィルがあるので、これを使うことでどのブラウザでも試すことは可能。これからのコンポーネントがやってくる未来に備え、 Web Components に触れておくとよいだろう。

読み終わってみて。

2014 年に初版が出たのもあって、 2017 年のフロントエンド界隈の話と比較するといくつか話が古そうなところもあります。

たとえばコンポーネントについては React を筆頭に Vue や Angular といった仮装 DOM を使ってコンポーネントを実現していくライブラリが活躍しています。 Web Components の実装も進み、 Chrome や Safari ではおよそ利用することが可能に、 Firefox でも実装が進んでいるようです。

React - A JavaScript library for building user interfaces
Vue.js
Angular

Web Components の実装状況
Can I use... Support tables for HTML5, CSS3, etc

CSS についても cssnext と呼ばれる、未来の CSS 仕様に向けた先行実装が今の流行り…?なのかなあ。
Sass で使っていたようなネストや変数、 Mix-in といったものは利用できますし、実行環境が cssnext というツールではなく PostCSS を利用するところに人気があるのかもしれません。

cssnext - Use tomorrow’s CSS syntax, today.
PostCSS - a tool for transforming CSS with JavaScript

PostCSS は Sass などが行っていたようなプリプロセッサというよりは babel のような、 Pluggable な CSS を処理する君で、プラグインを足して独自記法やブラウザが未実装な機能を書けるようにするものです。

このプラグインの一覧サイトがあるのですが、眺めているだけでも非常に様々なものがあります。
きれいなグラデーションを自動生成したり、 @component なんてすると BEM の命名を自動でつけてくれたり、画像や SVG を CSS のインラインに展開してくれたり…。以前までは、それぞれ別のプラグインとして作られ、 Grunt や gulp を使ってバケツリレー変換をしていたものが、 PostCSS というプラットフォームに乗っかることで、 CSS に対する前処理を容易にできるようになったようです。

PostCSS.parts | A searchable catalog of PostCSS plugins

ちなみに Sass っぽく使えるよ!というものもあるので、 Sass がどうしても!の場合にはこういう選択もありだと思います。

jonathantneal/precss: Use Sass-like markup in your CSS

というわけで、現代の先端?流行?と比べると、本で言われている技術ポイントと乖離がありそうですが、ぼくがこの本を読んでみたかった理由はそこではなく。CSS 設計のやり方、考え方、大切さ、コンポーネント分け方のイメージをつけることが目的でした。あとはそもそも OOCSS って? SMACSS って?みたいな状態だったので、これを解消したかったというところですね。

ここについては十分に解消され、実践できる武器になっているかわかりませんが、イメージはなんとなくついたので、あとは実践するのみになりましたとさ。おわり。

   読書や本   

別にチームリーダーとかそういう立場ではないのだけれども、チームがうまく回っていない気がしていてなんだかなーと思ってたけれども、どうしたらいいのかわからん。というときに Amazon を眺めていたら見つけたこれ。

Amazon | スモール・リーダーシップ チームを育てながらゴールに導く「協調型」リーダー | 和智 右桂 通販

帯に書かれていたことに一目惚れして、購入キメた。

× カリスマ
× イノベーション
× 精神論

技術でチームを回そう

こんなリーダーたちにオススメ
・初めてリーダーになった人
・チームの売上や進捗をうまくコントロールできない人
・部下を育てたいと思っている人
・チーム内で意見が対立して悩んでいる人
・ PDCA 、進捗管理、問題解決などの具体的手法を知りたい人
・身の丈にあったリーダーシップを身につけたい人

まだ一章を読んだ程度でしかないが、うんうん分かる分かるぞ~~~、といったような、自分の手で言葉や体系立てが出来ていないが経験上そうなのだろう、と思うところが出てくる。過去にえらい人に言われてきたことや、えらい人がやっている部分と一致するところもあって。自分の中で色々繋がり、ちょっと楽しくなっている。

うまく引用できそうなところがわからないので、読んでのざっくりまとめにはなるが、こういうところ。

業務はおよそ知識の差がある。すると出来る人がやるに陥りやすく、知識・経験を積んだ人が突如としてヒーローになる。ヒーローが生まれてもチーム全体としての学び、経験にはならない

リーダーは手を動かさない、1人でうごかない。メンバーの新たな学びにつながり、チームを考える時間が増える

まずは 決められたこと=規律 を守り、自ら考え変えていく=自律 へ

チームとしての学びのために、暗黙知を形式知へしていく。そのためにリーダーが形にする手伝いをする。形式知が増えるとチームの見方も変わり、また暗黙知が増えていく。そうしてまた形式知へ。

ところでこういう記事って書いたことがなくて、どういうポイントを抑えればよいのかいまいちわからない。メモというか、気になったところまとめを書きながら読んではいるが、こうやって記事にするとき書きすぎると本を買わなくても良くね?となってしまうだろうし。とりあえずはこんな形で、読んで特に!!!!となった部分を引用 or まとめる程度でいこう。

それにしても、ちびっこのころはやたら本を読んでいたが、いつしか苦手になってしまったようで、読むスピードと理解がなかなか進まない身体になってしまった。読めば適応してくると思うので頑張ろう。
ちなみに、会社で本買ってええぞって予算があって、それを使わせてもらっている。ありがたし。

   技術的な話題   

某所の CentOS サーバをいい加減に 7 系にしよう!と思い、アップグレード手順なんかを調べていたら結構大変そうなことになった記録。結論としてまだアップグレードは出来てない。大して yum 以外でモリモリ入れたのも無いし、およそ nginx と php が動けば良いだろうな、入れ直しが手っ取り早そうだ。

公式 Wiki にアップグレードツールの件が記載されている。
TipsAndTricks/CentOSUpgradeTool - CentOS Wiki

目につく部分に警告が書かれている。

DO NOT USE this tool. Warning: use of this tool is currently BROKEN as several system-critical packages are of a higher version number in CentOS 6.7 than they are in CentOS 7 so those do not get upgraded correctly. This renders yum and several other system tools non-functional.

要するに CentOS 6.7 以降のパッケージは CentOS 7 に入っているパッケージよりもバージョンが進んでいるものもあり、うまく動かないらしい。詰まる該当パッケージのバージョン下げれば良いんじゃないか、行けるっしょ、という気持ちでトライしてみる。
※良い子は真似しないでね!

// まずは現状の確認をする
# cat /etc/redhat-release
CentOS release 6.9 (Final)


// アップグレードツールのリポジトリを追加
# vi /etc/yum.repos.d/upg.repo

// 以下を記載

[upg]
name=CentOS-$releasever - Upgrade Tool
baseurl=http://dev.centos.org/centos/6/upg/x86_64/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6


// 必要なツールのインストール
# yum install redhat-upgrade-tool preupgrade-assistant-contents


// 可能なアップグレードを確認
# preupg --list
CentOS6_7


// アップグレード検証をする
# preupg -s CentOS6_7

Preupg tool doesn't do the actual upgrade.
Please ensure you have backed up your system and/or data in the event of a failed upgrade
 that would require a full re-install of the system from installation media.
Do you want to continue? y/n

// y を入力

Gathering logs used by preupgrade assistant:
All installed packages : 01/11 ...finished (time 00:01s)
All changed files      : 02/11 ...finished (time 04:51s)
Changed config files   : 03/11 ...finished (time 00:00s)
All users              : 04/11 ...finished (time 00:00s)
All groups             : 05/11 ...finished (time 00:00s)
Service statuses       : 06/11 ...finished (time 00:00s)
All installed files    : 07/11 ...finished (time 00:04s)
All local files        : 08/11 ...finished (time 00:40s)
All executable files   : 09/11 ...finished (time 00:07s)
RedHat signed packages : 10/11 ...finished (time 00:00s)
CentOS signed packages : 11/11 ...finished (time 00:00s)
Assessment of the system, running checks / SCE scripts:
001/096 ...done    (Configuration Files to Review)
002/096 ...done    (File Lists for Manual Migration)
003/096 ...done    (Bacula Backup Software)
004/096 ...done    (MySQL configuration)
005/096 ...done    (Migration of the MySQL data stack)
006/096 ...done    (Changes related to moving from MySQL to MariaDB)
007/096 ...done    (PostgreSQL upgrade content)
008/096 ...done    (GNOME Desktop Environment underwent several design modifications in CentOS 7 release)
009/096 ...done    (KDE Desktop Environment underwent several design modifications in CentOS 7 release)
010/096 ...done    (several graphic drivers not supported in CentOS 7)
011/096 ...done    (several input drivers not supported in CentOS 7)
012/096 ...done    (several kernel networking drivers not available in CentOS 7)
013/096 ...done    (several kernel storage drivers not available in CentOS 7)
014/096 ...done    (Names, Options and Output Format Changes in arptables)
015/096 ...done    (BIND9 running in a chroot environment check.)
016/096 ...done    (BIND9 configuration compatibility check)
017/096 ...done    (Move dhcpd/dhcprelay arguments from /etc/sysconfig/* to *.service files)
018/096 ...done    (DNSMASQ configuration compatibility check)
019/096 ...done    (Dovecot configuration compatibility check)
020/096 ...done    (Compatibility Between iptables and ip6tables)
021/096 ...done    (Net-SNMP check)
022/096 ...done    (Squid configuration compatibility check)
023/096 ...done    (Reusable Configuration Files)
024/096 ...done    (VCS repositories)
025/096 ...done    (Added and extended options for BIND9 configuration)
026/096 ...done    (Added options in DNSMASQ configuration)
027/096 ...done    (Packages not signed by CentOS)
028/096 ...done    (Obsoleted rpms)
029/096 ...done    (w3m not available in CentOS 7)
030/096 ...done    (report incompatibilities between CentOS 6 and 7 in qemu-guest-agent package)
031/096 ...done    (Removed options in coreutils binaries)
032/096 ...done    (Removed options in gawk binaries)
033/096 ...done    (Removed options in netstat binary)
034/096 ...done    (Removed options in quota tools)
035/096 ...done    (Removed rpms)
036/096 ...done    (Replaced rpms)
037/096 ...done    (GMP library incompatibilities)
038/096 ...done    (package downgrades)
039/096 ...done    (restore custom selinux configuration)
040/096 ...done    (General)
041/096 ...done    (samba shared directories selinux)
042/096 ...done    (CUPS Browsing/BrowsePoll configuration)
043/096 ...done    (CVS Package Split)
044/096 ...done    (FreeRADIUS Upgrade Verification)
045/096 ...done    (httpd configuration compatibility check)
046/096 ...done    (bind-dyndb-ldap)
047/096 ...done    (Identity Management Server compatibility check)
048/096 ...done    (IPA Server CA Verification)
049/096 ...done    (NTP configuration)
050/096 ...done    (Information on time-sync.target)
051/096 ...done    (OpenLDAP /etc/sysconfig and data compatibility)
052/096 ...done    (OpenSSH sshd_config migration content)
053/096 ...done    (OpenSSH sysconfig migration content)
054/096 ...done    (Configuration for quota_nld service)
055/096 ...done    (Disk quota netlink message daemon moved into quota-nld package)
056/096 ...done    (SSSD compatibility check)
057/096 ...done    (Luks encrypted partition)
058/096 ...done    (Clvmd and cmirrord daemon management.)
059/096 ...done    (State of LVM2 services.)
060/096 ...done    (device-mapper-multipath configuration compatibility check)
061/096 ...done    (Removal of scsi-target-utils)
062/096 ...done    (Configuration for warnquota tool)
063/096 ...done    (Disk quota tool warnquota moved into quota-warnquota package)
064/096 ...done    (Architecture Support)
065/096 ...done    (Binary rebuilds)
066/096 ...done    (Debuginfo packages)
067/096 ...done    (Cluster and High Availability)
068/096 ...done    (Quorum implementation)
069/096 ...done    (fix krb5kdc config file)
070/096 ...done    (File Systems, Partitions and Mounts Configuration Review)
071/096 ...done    (Read Only FHS directories)
072/096 ...done    (Sonamebumped libs)
073/096 ...done    (SonameKept Reusable Dynamic Libraries)
074/096 ...done    (Removed .so libs)
075/096 ...done    (In-place Upgrade Requirements for the /usr/ Directory)
076/096 ...done    (CA certificate bundles modified)
077/096 ...done    (Developer Tool Set packages)
078/096 ...done    (Hyper-V)
079/096 ...done    (Content for enabling and disabling services based on CentOS 6 system)
080/096 ...done    (Check for ethernet interface naming)
081/096 ...done    (User modification in /etc/rc.local and /etc/rc.d/rc.local)
082/096 ...done    (cgroups configuration compatibility check)
083/096 ...done    (Plugable authentication modules (PAM))
084/096 ...done    (Foreign Perl modules)
085/096 ...done    (Python 2.7.5)
086/096 ...done    (Ruby 2.0.0)
087/096 ...done    (SCL collections)
088/096 ...done    (System kickstart)
089/096 ...done    (YUM)
090/096 ...done    (Check for usage of dangerous range of UID/GIDs)
091/096 ...done    (Incorrect usage of reserved UID/GIDs)
092/096 ...done    (NIS ypbind config files back-up)
093/096 ...done    (NIS Makefile back-up)
094/096 ...done    (NIS server maps check)
095/096 ...done    (NIS server MAXUID and MAXGID limits check)
096/096 ...done    (NIS server config file back-up)
Assessment finished (time 06:32s)
I/O warning : failed to load external entity "/usr/share/openscap/xsl/security-guide.xsl"
compilation error: file /usr/share/preupgrade/xsl/preup.xsl line 40 element import
xsl:import : unable to load /usr/share/openscap/xsl/security-guide.xsl
I/O warning : failed to load external entity "/usr/share/openscap/xsl/oval-report.xsl"
compilation error: file /usr/share/preupgrade/xsl/preup.xsl line 41 element import
xsl:import : unable to load /usr/share/openscap/xsl/oval-report.xsl
I/O warning : failed to load external entity "/usr/share/openscap/xsl/sce-report.xsl"
compilation error: file /usr/share/preupgrade/xsl/preup.xsl line 42 element import
xsl:import : unable to load /usr/share/openscap/xsl/sce-report.xsl
OpenSCAP Error:: Could not parse XSLT file '/usr/share/preupgrade/xsl/preup.xsl' [oscapxml.c:416]
Unable to open file /root/preupgrade/result.html
Usage: preupg [options]

preupg: error: [Errno 2] No such file or directory: '/root/preupgrade/result.html'

やっぱりうごかない。調べると openscap のバージョンを下げることで先にすすめるらしい。
CentOS6.8 から CentOS7 へのアップグレード - demandosigno

// バージョン確認
# rpm -qa | grep openscap
openscap-1.2.13-2.el6.x86_64


// 古いものを入れる
# rpm -Uhv --oldpackage http://dev.centos.org/centos/6/upg/x86_64/Packages/openscap-1.0.8-1.0.1.el6.centos.x86_64.rpm
http://dev.centos.org/centos/6/upg/x86_64/Packages/openscap-1.0.8-1.0.1.el6.centos.x86_64.rpm を取得中
準備中...                ########################################### [100%]
   1:openscap               ########################################### [100%]


// 確認
# rpm -qa | grep openscap
openscap-1.0.8-1.0.1.el6.centos.x86_64


// 再度ツール実行
# preupg -s CentOS6_7

~~

Assessment finished (time 06:21s)

Result table with checks and their results for main contents:
---------------------------------------------------------------------------------------------------------------
|Bacula Backup Software                                                                    |notapplicable     |
|MySQL configuration                                                                       |notapplicable     |
|Migration of the MySQL data stack                                                         |notapplicable     |
|Changes related to moving from MySQL to MariaDB                                           |notapplicable     |
|PostgreSQL upgrade content                                                                |notapplicable     |
|GNOME Desktop Environment underwent several design modifications in CentOS 7 release      |notapplicable     |
|KDE Desktop Environment underwent several design modifications in CentOS 7 release        |notapplicable     |
|several graphic drivers not supported in CentOS 7                                         |notapplicable     |
|several input drivers not supported in CentOS 7                                           |notapplicable     |
|Names, Options and Output Format Changes in arptables                                     |notapplicable     |
|BIND9 running in a chroot environment check.                                              |notapplicable     |
|BIND9 configuration compatibility check                                                   |notapplicable     |
|Move dhcpd/dhcprelay arguments from /etc/sysconfig/* to *.service files                   |notapplicable     |
|DNSMASQ configuration compatibility check                                                 |notapplicable     |
|Dovecot configuration compatibility check                                                 |notapplicable     |
|Net-SNMP check                                                                            |notapplicable     |
|Squid configuration compatibility check                                                   |notapplicable     |
|Added and extended options for BIND9 configuration                                        |notapplicable     |
|Added options in DNSMASQ configuration                                                    |notapplicable     |
|w3m not available in CentOS 7                                                             |notapplicable     |
|report incompatibilities between CentOS 6 and 7 in qemu-guest-agent package               |notapplicable     |
|restore custom selinux configuration                                                      |notapplicable     |
|samba shared directories selinux                                                          |notapplicable     |
|CUPS Browsing/BrowsePoll configuration                                                    |notapplicable     |
|FreeRADIUS Upgrade Verification                                                           |notapplicable     |
|bind-dyndb-ldap                                                                           |notapplicable     |
|Identity Management Server compatibility check                                            |notapplicable     |
|IPA Server CA Verification                                                                |notapplicable     |
|OpenLDAP /etc/sysconfig and data compatibility                                            |notapplicable     |
|SSSD compatibility check                                                                  |notapplicable     |
|Clvmd and cmirrord daemon management.                                                     |notapplicable     |
|device-mapper-multipath configuration compatibility check                                 |notapplicable     |
|Removal of scsi-target-utils                                                              |notapplicable     |
|Quorum implementation                                                                     |notapplicable     |
|fix krb5kdc config file                                                                   |notapplicable     |
|cgroups configuration compatibility check                                                 |notapplicable     |
|System kickstart                                                                          |notapplicable     |
|NIS ypbind config files back-up                                                           |notapplicable     |
|NIS Makefile back-up                                                                      |notapplicable     |
|NIS server maps check                                                                     |notapplicable     |
|NIS server MAXUID and MAXGID limits check                                                 |notapplicable     |
|NIS server config file back-up                                                            |notapplicable     |
|several kernel networking drivers not available in CentOS 7                               |pass              |
|several kernel storage drivers not available in CentOS 7                                  |pass              |
|OpenSSH sshd_config migration content                                                     |pass              |
|Configuration for quota_nld service                                                       |pass              |
|Disk quota netlink message daemon moved into quota-nld package                            |pass              |
|Luks encrypted partition                                                                  |pass              |
|Configuration for warnquota tool                                                          |pass              |
|Architecture Support                                                                      |pass              |
|Debuginfo packages                                                                        |pass              |
|Cluster and High Availability                                                             |pass              |
|Read Only FHS directories                                                                 |pass              |
|In-place Upgrade Requirements for the /usr/ Directory                                     |pass              |
|Developer Tool Set packages                                                               |pass              |
|Hyper-V                                                                                   |pass              |
|Check for ethernet interface naming                                                       |pass              |
|Plugable authentication modules (PAM)                                                     |pass              |
|Ruby 2.0.0                                                                                |pass              |
|SCL collections                                                                           |pass              |
|Incorrect usage of reserved UID/GIDs                                                      |pass              |
|Compatibility Between iptables and ip6tables                                              |informational     |
|VCS repositories                                                                          |informational     |
|Removed options in coreutils binaries                                                     |informational     |
|Removed options in gawk binaries                                                          |informational     |
|Removed options in netstat binary                                                         |informational     |
|Removed options in quota tools                                                            |informational     |
|GMP library incompatibilities                                                             |informational     |
|CVS Package Split                                                                         |informational     |
|httpd configuration compatibility check                                                   |informational     |
|NTP configuration                                                                         |informational     |
|Information on time-sync.target                                                           |informational     |
|Disk quota tool warnquota moved into quota-warnquota package                              |informational     |
|File Systems, Partitions and Mounts Configuration Review                                  |informational     |
|Sonamebumped libs                                                                         |informational     |
|SonameKept Reusable Dynamic Libraries                                                     |informational     |
|Foreign Perl modules                                                                      |informational     |
|YUM                                                                                       |informational     |
|Reusable Configuration Files                                                              |fixed             |
|Replaced rpms                                                                             |fixed             |
|package downgrades                                                                        |fixed             |
|OpenSSH sysconfig migration content                                                       |fixed             |
|State of LVM2 services.                                                                   |fixed             |
|Configuration Files to Review                                                             |needs_inspection  |
|File Lists for Manual Migration                                                           |needs_inspection  |
|Obsoleted rpms                                                                            |needs_inspection  |
|Binary rebuilds                                                                           |needs_inspection  |
|CA certificate bundles modified                                                           |needs_inspection  |
|Python 2.7.5                                                                              |needs_inspection  |
|Check for usage of dangerous range of UID/GIDs                                            |needs_inspection  |
|Packages not signed by CentOS                                                             |needs_action      |
|Removed rpms                                                                              |needs_action      |
|General                                                                                   |needs_action      |
|Removed .so libs                                                                          |needs_action      |
|Content for enabling and disabling services based on CentOS 6 system                      |needs_action      |
|User modification in /etc/rc.local and /etc/rc.d/rc.local                                 |needs_action      |
---------------------------------------------------------------------------------------------------------------
Tarball with results is stored here /root/preupgrade-results/preupg_results-170926155342.tar.gz .
The latest assessment is stored in directory /root/preupgrade .
Summary information:
We found some potential in-place upgrade risks.
Read the file /root/preupgrade/result.html for more details.
Upload results to UI by command:
e.g. preupg -u http://127.0.0.1:8099/submit/ -r /root/preupgrade-results/preupg_results-*.tar.gz .

出てきた。結構いろいろみてくれるのね、しゅごい。

/root/preupgrade/result.html に詳細があるそうなので、ドキュメントルートに持っていって、ブラウザから確認すると次のような画面になった。

  • 半分くらいの項目はちゃんと確認しないと危ない気がする
  • がんばってアップグレードしてもとっちらかった状態になりそう
  • web サーバとして簡単に使っている程度なので、バックアップ全部とって入れ替えるもあり

というところから、入れ替えちゃったほうが早そうだなあ、という結論。

まずは docker だったりで CentOS 7 を準備して、稼働中のサービス、設定ファイルや鍵を移しつつ、いろいろ動作するか確認したのち、まるっと入れ替える、という流れになりそーう。

つづく。

   イベントメモ   

PWA Roadshow Tokyo 2017 という PWA についていろいろ説明したり、コードを弄ったり、未来を感じたりするイベントに参加してきたログ的なもの。

イベント応募

Google Developers Japan のブログを見ていたら、たまたまイベントやるよ!を見かける。

Google Developers Japan: Progressive Web Apps Roadshow Tokyo 2017 を開催します

PWA という単語をぼちぼち聞いてはいて、てっきり Web サイトがアプリ化できる!というものだと思っていたものの、それ以上はまったくしらなかったので、せっかくだから勉強してみよう!と Google 主催のイベントに応募したのがきっかけ。

イベントページはここ。
Progressive Web Apps Roadshow Tokyo 2017 | ホーム

イベントページ自体は日本語なものの、セッションが英語だったりちょこちょこと文言が英語で若干不安になるが、それはまあそれとして、英語の勉強にもいいでしょう、と気合を入れて応募した。定員200名に入るのかどうかわからなかったが、後日参加できるよ!のメールが来てホッとしたことを覚えている。

受付~会場入り

平日だったので、ギョムをおやすみさせてもらっていった。 Google 東京オフィスはたぶん初めて…、前に何かのイベントでいったことあるかも?六本木ヒルズ、森タワーにそのオフィスを構える。

Google のオフィス | Google

東京
〒106-6126
東京都港区
六本木 6-10-1
六本木ヒルズ森タワー
電話: +81-3-6384-9000

日比谷線六本木駅からもそう遠くない。 1 番の出口を目指すと到着する。

通常、森タワーに部外者が入るには、対応する LL または UL にある受付の人に名刺を見せたりが必要だが、今回は多くの人が訪れることもあってか LL にイベント用の受付が設置されていた。受付の方にメールで来ていた参加証を見せる。参加者の名前をリストにしているようで、来た人欄に丸がつけられた。

会場は 27 階…(だったと思う)で C ホールからエレベーターで行く。

会場はプレゼンホールのようになっていて、足元に電源あり、 27? くらいのモニター 9 枚による巨大なスクリーン、後方席には上にもディスプレイ、そしてゆったりとした座席、さらには後ろに通訳ブース、とすごく整っていた会場だった。
窓、明かりは壁際のスイッチでオンオフできるよう。壁一面が真っ白でスクリーン周辺は黒なっていて、見やすかった。

話し声が聞こえたところによると、このスペースはわりかしできたばかりで、このイベントが初めての通訳ありだったり大規模にやったり、人柱てきなものになっていたそう。

ちなみに Google のゲスト用の無線 LAN アクセスポイントの SSID は GoogleGuest でパスワード無しだった。よく見ると GoogleGuestLegacy みたいなものもあって、無線 LAN ルータを刷新でもしたのかな?なんて思ってた。

いろいろセッションメモ

ずらーーーーっとして、見にくい点は申し訳ない。整えるとちょっとつらみが。。

キーノート: Progressive Web Apps: What, Why and How

  • Ajax で Web は変わった
    • Google Maps で革命が、ズーム、スクロール、自動読み込み
  • 2014年にモバイルとデスクトップの利用率が入れ替わる
    • モバイルでは 87% のユーザがアプリ体験を重視している、通知やホームスクリーン
    • ユーザの時間はよく使うアプリ 3 つにおおよそ集約する
      • 新規インストールもなかなか起こらない
    • モバイルにおいて)アプリは体験、可能性、将来性が高い一方で多くにリーチすることは難しい
    • モバイルにおいて)Web は逆にリーチできるが体験がアプリほど高くない
      • PWA でそれを解決していきたい
  • PWA はユーザエクスペリエンス向上のため、エンドユーザのための仕事をすること
  • PWA で新しいことを多数学ぶ必要はない
    • いままでのことを応用、よりよくするだけ
    • FIRE = Fast Integrated Reliable Engaging の観点で価値を生み出していく
      • Fast: 動作を軽快に、パフォーマンスを良く
      • Integrated: ネイティブアプリと同じような OS と融合したユーザ体験を
      • Reliable: 通信が途切れてもよいような Web 、信頼性を高く
      • Engaging: ユーザ体験、Web サイトの価値向上
    • こういったものに Service Worker が必要不可欠
      • ブラウザとサーバ、ネットワーク通信との間にはまり、オフライン機能の提供をすることもできる
  • PWA は Progressive(段階的) である
    • Web で作ったアプリケーションをデスクトップでもモバイルでも
    • モバイルは端末、環境がさまざまなので、フィーチャーディテクションを使い、段階的に機能・体験を提供しよう
  • PWA はどんどん広まっている
    • Twitter, LANCOME, Lyfy, Nikkei, Rakuten, suumo, travago, CNET, CNN, forbes, …

セッション1: Integrated Experiences

  • FIRE の 2つめ
    • web と OS がより連携し、よりよい体験を
  • 80% のユーザがモバイルのホーム画面上でアプリを移動している
    • 利便性や見た目を重視する
    • web ページのショートカットをホーム画面に置くことはいままでもできていた
      • 設置するにあたってメニュー操作が必要、ブラウザが立ち上がる、オフラインで見れないといったエクスペリエンスの問題があった
    • WebApp Manifest で解決する
      • ウェブアプリ マニフェスト  |  Web  |  Google Developers
      • 見た目上はほぼアプリになり、どんなアイコンか、起動画面をどうするかを設定できる
      • ブラウザによって実装がことなるが、自動でサジェストしてくれる
        • Chrome の場合は次の通り
          • WebApp Manifest が正しく書かれている
            • アプリ名、144px のアイコン、 URL
            • 要するにアプリっぽく見えるためのプロパティが必須
          • Offline Support with Service Worker
            • ネットワークがなくても動作する、という信頼がないとだめ
          • Engaged User
            • スパムアプリでないことを Chrome がチェックしている
            • 基準は明確に決まっておらず、様子を見ながらころころ変わっている
              • 「たまたまアクセスがあったときにサジェストを出す」ではない
          • こうしたややこしいことがあるのは FIRE を約束するため
  • Web Payments
    • モバイルの CVR は デスクトップ比で 66% 低い
      • 購買には支払情報、届け先などをフォーム上で入力が必要
      • モバイルで入力するのは面倒なので、離脱率が高いように見える
    • そのフォームが面倒なことに対して Autofill がすでにある
      • 最適なフォームの作成  |  Web  |  Google Developers
      • ブラウザはフィールドの属性値と並びで判断している
        • zipcode は国際的なのでわかるが yubin は判断できない
      • うまく動かないケース多いハズなので、正しく autocomplete 属性を設定すること
        • 新しい属性を入れるので元々のコードを汚すことがない
    • すべての Web サイトに対して、お金を払うことについて一貫したユーザ体験を提供することが Web Payments の目的
      • 支払い方法、配送先を決められる
        • Android Pay など支払い専用アプリケーションを利用することもできる
          • 複数指定して、対応している支払いするものだけ表示される
        • 指定された生情報が JS に渡される
      • お金を支払う処理まで行うものではなく、決済と配送先の入力を簡易的にするためのもの
      • クロスブラウザ、クロスプラットフォーム、オープンなエコシステム
    • Autofill は古いブラウザでも問題がないので積極的に利用していくとよい
      • フィーチャーディテクションを行い Web Payments も利用していくとユーザ体験が向上する
    • Web Payments はまだまだ発展する余地があるので、デベロッパーからの意見を取り入れていきたい
  • 他にも OS と融合していく機能・体験はある
    • Media Session, Media Capture, Casting Support, …
    • PWA として他のアプリと同じように振る舞うための API

セッション 2: Reliable Experiences

  • Web だから、ネットワークがどうであれ、アプリのように振る舞うことでユーザビリティを上げる
    • アプリはオフラインでも動く
    • 地下鉄では移動して接続が切れたりする、勝手が悪い
    • 新高校では電波が立っているが通信がうまくできなかったりする
    • 世界では 60% のユーザが 2G 回線を利用して、 3 秒待つと 53% が離脱している
  • Service Worker で解決していく
    • ローカルプロキシとして動作する、データのキャッシュを行える
    • 常に動いているわけではなく、必要なときに動作する
      • ブラウザが閉じていても通知を受信したらワーカーが起動する、など
      • App like lifecycle
        • 登録、インストールが必要
        • ユーザは何が起こっているのか知る必要は無く、裏で静かに動く
    • ローカルプロキシとしては 2 回目の読み込みから動くようになる
      • 初回の読み込みは登録とインストールだけ
      • 2 回目以降でワーカ0のアップデートを確認し、動いていく
    • キャッシュやリクエスト、ネットワーク状況をコントロールできる
      • キャッシュ戦略をいくつか紹介
        • キャッシュを見て、なければネットワークへレスポンス
          • 更新ができないので、あまり変わらないようなものにオススメ
        • ネットワークを見て、なければキャッシュを見る
          • ネットワークが繋がりにくいと待たされるが、キャッシュ更新は可能
        • キャッシュとネットワークの同時リクエスト
          • キャッシュがあれば利用
          • ネットワークが来たらキャッシュ更新し、データ反映
        • キャッシュ→ネットワーク→キャッシュ
          • ネットワークが繋がらないので何かコンテンツを提供することができる
          • ユーザの離脱を回避する可能性がある
      • キャッシュはアプリケーションの性質によってベストな方法が変わる
  • Service Worker のためのツールセット
    • DevTools は有効に使える
      • 困ったときは Clear Storage を実行するとおおよそ解決する
    • workbox
      • Welcome to Workbox
      • キャッシュ戦略のコードを簡単に記述することができる

セッション 3: Engaging Experiences

  • Material Design が PWA でも活用できる
  • プッシュ通知
    • タイムリーに正確で意味のある必要な情報を通知することがよい通知
      • x) 飛行機の離陸時間が変わりました!
      • o) 登場予定の xx 便の離陸時間が 13:00 から 14:00 に変更になりました
    • PWA におけるプッシュ通知では Web Push プロトコルを利用する
      • まずクライアントサイドで、ユーザの許可、サブスクライブ、サーバ送信
      • サーバサイドで Web Push プロトコルを利用してメッセージ送信
        • プッシュサービスがメッセージ配信を行い、中身を見ることはできない
      • クライアントの Service Worker によってイベントが発行され、メッセージ処理を行うことができる
      • メッセージはパブリックキーとプライベートキーを使って暗号化される
    • ユーザ許可を得る際に、二重の仕組みにすると許可されやすい
      • 設定画面やアプリケーションのダイアログとして “許可する” を表示
        • その後にブラウザ側の許可を出す
      • さらに通知される情報を設定できるとよい
    • Service Worker のイベントが発行した時、適切なアイコンやボタン、画像などを設置するとよい
      • アクションへの設定もできるので、ユーザ体験を考えて実施していく

セッション 4: Secure Experiences

  • HTTPS は Identity, Confidentiality, Integrity のため
    • サイトは誰なのか保証する
    • クライアント / サーバ の機密性
    • 改ざん防止
  • しかし導入にあたって Unimportant, Perf, Cost, Maintenance の問題がある

セッション 5: Tooling - Lighthouse and Beyond

  • Chrome DevTools を開いたときの Audit というタブが Lighthouse と呼ばれている
  • 例として React を使った SPA を PWA 対応をしていってみる
    • Lighthouse を実行した結果をベースラインとして、施策をしていき点数の上下を見ていく
    • 実行した際にチェックリストがでるので、これにしがたって順番に対応をしていくとよい
    • iOS や Safari の対応のために、サーバサイドレンダリングを行う
      • Lighthouse でもそれによってパフォーマンス、モバイル対応の評価が向上する
    • PWA に向けてキャッシュをする際、App Shell + Dynamic Content という考え方を組むとよい
      • App Shell モデル  |  Web  |  Google Developers
      • アプリケーションのガワ、全体感を作る部分が App Shell で、これをキャッシュする
      • ネットワークが有効なら、コンテンツを更新していく
        • 更新したコンテンツをキャッシュするとファーストビューが素早く見れる
    • WebApp Manifest を入れることで “ホーム画面に追加” ができるようになるが、これは DevTools で確認できる
      • DevTools 内にリンクがあり、これを推すと “ホームに追加” サジェストを出すことができる
  • このようにして PWA 対応を進めていくとよい

コードラボ

  • コードラボに必要なソース、説明などはここからいける
  • この時間は、ここまで話を見て、聞いて、学んできたことを各自で自由にお試しください、という時間
    • せっかく作っている人たちがいるので、相談・議論したりするのが推奨されている
      • 通訳さんもいるのでドシドシ聞いていこう!
    • とにかく自由な時間
  • 聞こえた話
    • PWA に SPA は仕様としても個人的には必須ではない
      • SPA は敷居が高い
      • SPA にせずともリソースをキャッシュすればスピードアップすることは十分に可能
    • Cache Storage が更新されないバグがある
      • 6-12 週間くらいで FIX されていく動きあり
    • 1 サイトに複数の Service Worker がいることも可能
      • ただし管理上の危険が伴う、ワーカーを分ける必要はないのでは?
  • 作業メモ
    • まずは “はじめてのプログレッシブウェブアプリ” をやってみる
    • 時間があれば、ごみばこいんのトップページを PWA 対応してみたい
      • gomiba.co.in ではなく、ローカル環境で、ちょっとやってみる程度
    • importScripts という関数はワーカー内で利用できるグローバルなもの
    • そもそも Service Worker は Web Worker のうちの 1 つ
    • リセットするときは Clear Storage + タブを閉じる + タブを再度開く ことが大事そう
      • Service Worker のコードがいつアップグレードされるのかわかっていない感
    • コードラボの資料の手順が丁寧なのでそれを見るとよい
      • とりあえずやってみたい!というひとはググって “やってみたったwwww” みたいな記事は見なくていい
      • ただしいきなり色々な単語がでてきて、そこへの説明はあまりないので、辞書を 1 つずつ倒していく
    • ごみばこいんの PWA 対応に取り掛かる
      • workbox をオススメしていたので、これを使ってみる
        • とりあえずビルドなしでも利用はできるが CLI ツールとしての利用になるので Node.js は必要
        • workbox.prod.js が読み込めれば利用できるので、そのソースだけ持ってくればよい
          • CDN は無さそう? → Q&A
        • 外部リソース、CDN のキャッシュはできない?
          • workbox に生成してもらったコードは静的ファイルのみのキャッシュ
          • そのコードをそのまま使う分には CDN のキャッシュはできない
      • PWA 対応がちゃんと動くか確認するのに実機を使うようにするとちょっと面倒
        • USB つないで実機の Service Worker をリセットしたりする必要がある
        • デスクトップでも “ホームに追加” 的な動きはあるので、これを試して良ければ実機確認が良さそう
          • デスクトップにショートカットが置かれる
      • アプリっぽい見た目になるまではサクっとできる
        • Webview を埋め込む、いわゆるガワネイティブみたいなものは PWA 対応をすることで不要になりそう
        • ただし未経験がゆえにぼちぼちとハマるところはあるので、コレで実際に動かしているプロダクトに入れるのは慎重にやりたい

実際にできたものがこれ。

WebApp Manifest を入れ、 Service Worker によるオフラインサポートをしたら、ホームに追加が出来るようになり、ごみばこいんのトップページをアプリのように表示することができた。アイコンを適当に引き伸ばしたら白い余白が出来てしまったが…。

セッション 6: AMP

  • PWA における早くしよう!はキャッシュをして 2 回目から早くしよう!
    • AMP はそもそも最初から早くしよう!
  • モバイルの平均読み込み時間は 19 秒。 77% が 10 秒以上かかっている
    • 初回読み込みリクエストが 214 もある
    • 半分は広告
    • 早くしようとすると UX がよいが マネタイズが難しい
  • AMP のモチベーション
    • 遅い読み込み、スクロールできない、読み込みにおけるレイアウト崩れを解消する
  • AMP HTML + AMP JS + AMP Cache
    • AMP HTML
      • 広告はサポートしているアドネットのみ、認められないものは設置できない
      • 画像などのリソースなども指定された方法のみ有効
    • AMP JS
      • 遅延読み込みやサイズ指定を自動、または制約によって行う
    • AMP Cache
      • 正しく AMP 対応されていればクローラがやってきてキャッシュする
      • CDN 的なもので、各地にエッジサーバがあり、通信路も最適化される
        • エッジサーバはクローズではあるが、 Web の世界中で最適な対応になるまで時間かかるので、先に作った
        • 元ページはどうであれエッジサーバは HTTP/2 で通信できる
  • AMP + PWA
    • amp-install-serviceworker を利用すると Service Worker の登録ができる
    • AMP から遷移先のページをキャッシュすることができるので、常に早い Web 体験をすることができる
    • 大きく 3 つの方法が取れる
      • AMP as PWA
        • AMP そのものを PWA で扱う
        • AMP ページで Service Worker を登録し、遷移先に必要な AppShell をキャッシュする
        • 例) Learn AMP by Example
      • AMP to PWA
        • AMP から PWA にうまく遷移する
        • 動的なサイトなら有効、ただし手間がかかる
      • AMP in PWA
        • PWA に AMP を埋め込む
          • AMP HTML を持っておく
          • AMP ページにはそれをそのまま出す
          • PWA ページにはコンテンツとして埋め込む
        • iframe では遅いので Shadow DOM で解決する必要がある

クロージング

  • PWA が伝わったと思う
    • プログレッシブエンハンスメントなので、段階的に、できるところから、ユーザエクスペリエンスのために対応していこう
  • 紹介できなかったところで、面白いものがまだまだある
    • Credential Management API
    • Web VR
    • Web Assembly
    • Silent Push

Q&A

  • Q) 新フローに対して慣れが必要だけどチェックアウトのフロー簡略化も対象か
    • Payment Request API の中で住所や支払い情報を入れる
      • 今まで複数のページに渡ってやっていたのがまとまる
    • サイトによって色々なパターンがあるので、一概にどうこうする、とはいえない
      • 個別に相談・提案します
  • Q) “ホーム画面に追加” を追加モジュールでできるか
    • 今後でやっていきたい
    • 議論としては右往左往しているような状況
  • Q) PWA は何を指しているのか
    • 答えはマーケティング用語であり、バズワード
    • 優れたユーザ体験を高速でエンゲージメントがあって…。これがPWAだ!というものはない
      • Lighthouse がチェックする指標が一番近い
  • Q) 通知の登録、削除、登録のフローは可能か
    • パーミッションを外した場合、ask、になっているなら許可を求める。
      • ブロックなら終了。何もできない
    • PWA.locks にはよいリスティングはある、誰でも登録できるが微妙なものもある
  • Q) モバイルのペイメント CVR の数字はどこのもの?
    • 社内の調査 PDF
    • ドイツ銀行の有料のもの
  • Q) CVR はフォームが悪いか、Web 体験が悪いか
    • フォームの途中でドロップすることが多いようにミメル
  • Q) Server Push はキャッシュ関係なく送るか?
    • その通り
    • Service Worker からはどうするか知ることはない
      • クッキーを使ってどういうキャッシュを持っているか確認する、という対策はできる
    • いい案があればコミュニティに挙げてみて
  • Q) Push 通知の許可に 2 度目のチャンスはない。ホームに追加も同じ?
    • 14 日後まででない。無視ではなくしない、にした場合 3 ヶ月後まででない
    • PWA コア機能を作ってるチームが UX やユーザリサーチをしているので変わる可能性はある
  • Q) PWA はアンインストールがあるか、キャッシュは誰が度のタイミングで責任を持つか
    • Android 、他のアプリと同じようにアンインストールすればクリアする、ストレージのクリアも同じ
    • ユーザとしてはサービスワーカーを処理するのはむずかしい
    • clear-site-data というヘッダーがあって、シグナルも増えている
    • quota を使って容量制限を設ける、ということも可能
  • Q) Service Woker スクリプトを CDN に置けるか?
    • できるが、やらないほうがいい
    • 重要なコンポーネントになるので、常に最新のバージョンを見れるようにしたほうがいい
      • ServiceWorker自体がキャッシュされるとこまっちゃう
    • CDN の必要性が薄まる
      • 必要なときにサーバにアクセスする。クライアントにキャッシュできる
  • Q) CDN のキャッシュはできるか?
    • クロスオリジンはキャッシュできる、がうまくいかないかも
    • Service Worker から fetch してキャッシュすることはできるが inspect できない
  • Q) Payment Request API でポイントから一部支払うことはできるか
    • マイナスを入れることでできる
    • UI の調整は今後も考えてない、声が多ければ仕様に増える可能性がある
  • Q) Service Worker がキャッシュするとリクエストは出るか?
    • リクエストが出る
    • AMP by Example を見てみるとよい
  • Q) 広告に対して行っているサポート
    • 遅延ロードがあるくらいで特にない
    • AMP フォーマットで広告を書くと、広告が AMP になるので CVR 問題は少ないはず
    • PWA については普通のページになるので特にない
    • Web だからユーザがオンラインで振る舞うので問題ない
      • オフラインならネイティブアプリの真似をすればいい
  • Q) しばらく Web to App の流れだったが App to Webが来るか?
    • Web とネイティブが近づいている。相互に機能が出入りして融合しつつある
    • ニュース、プッシュ通知が有効なので新規なら PWA でいいのでは?いまのアプリが順調ならアプリでもいい
      • PWA だからうまくいく!というわけではない、ユーザリサーチしていこう
  • Q) PWA に向いているライブラリ
    • 普通の Web なので、自由に、使いやすいものを選ぶとおい
  • Q) mBasS などあるが Push 通知をどうするか
    • 何かを推奨するわけでなく、標準のプロトコルを使うとよい
  • Q) ブラウザキャッシュと Service Worker キャッシュの違い
    • Service Worker キャッシュは明示的に今ここに欲しい、ができる
    • ブラウザキャッシュは来たらキャッシュするよ、という程度
  • Q) push 通知許可ダイアログ表示について、intervention でブロックするなどは検討してる?
    • (話を聞いてなくてメモできなかった。。。)
  • Q) クライアントに PWA を提案する一言キーワード
    • ベストなエクスペリエンスを提供します
    • ユーザを考えるべき
    • ネイティブアプリみたいな Web
    • それがベストなマーケティング
  • Q) PWA の分析は GA で可能か
    • はい、ガイドもあるので参考にしてね
    • workbox の中に analytics もあるので、オフライン中の動作をトラックして次にオンラインのときに送れる
  • Q) PWA のネイティブの今後。ネイティブ不要?
    • 常両方必要、どちらがいてよい、ということはない
    • Google でも仲良くやっている
    • よい体験のためにどちらの利点も考えていくべき
  • Q) ネイティブアプリと比べたバッテリー消費
    • とくにない
    • ネットワークアクティビティをあまり行わないようにしたほうがバッテリーが落ち着く
      • Service Worker でキャッシュするとリクエストがへってよい
    • 動画など GPU アクセラレーションをするなどなるとネイティブがつよい
  • Q) Service Worker v2 の中で面白いものは?
    • バックグラウンドシンク
      • オフライン中に起こったアクションをオンラインになったら送出できる
    • サイレントプッシュ
    • ストリーム
  • Q) Service Worker はアプリ開発者向け?ライブラリにオフライン機能を追加するようなユースケースは考えられているか?
    • ライブラリが持っているサービスワーカーのコードとマージする必要がある
    • 基本的には 1 つのサイトに 1 つのサービスワーカー
      • インポートや複数走らせるが議論されている
      • そのあたりのベストプラクティスが特にない、よいエコシステム成熟してない
  • Q) iOS は使えない機能があると思うが PWA でどうしたらよいか
    • まずよいエクスペリエンスをデスクトップ・モバイルで作って、よりよくしていくだけ
      • iOS だからやらない、とかっていう話ではない
    • フィーチャーがサポートされたときに有効になっていく
      • プログレッシブエンハンスメントしていく
  • Q) 他のベンダーとの連携アイオニックとか
    • Polymer でも一緒にやっていてので一緒に進めている
    • ブラウザベンダとも Chrome サミットでパネルディスカッションやセッションを進めている
      • Google だけでなく全体で進めている

そのほかの情報とか

参加者に関しては、ゲーム系会社の方がいたり、 SEO や広告を取り扱うメディア系の方がいたり、エンジニアだったり Web 担当者だったり、いやもう PWA やってて~な人もいたようだった。何ができてどう活かしていけるのか、 アプリと PWA 、 AMP と PWA 、これからの Web 、興味関心が高いように思えた。

今回のイベントのスライドはここにある。(ルートが Google Developer Groups になっているので公開してよいものだろう)

Twitter のまとめはここ

ほかの参加したよ!ブログはここ(リストの更新予定はない)

おわりに

今回のイベントを通して PWA について深まったが、 Google の人たちは終始、 Progressive Enhancement だ、と言っていたのが印象的だった。 PWA それ自体は別に Web をアプリ化するような技術そのものもでもなく、プッシュ通知を送れるような技術でもない。複数の Web Standard な API を組み合わせ、モバイルにおけるユーザ体験をより良くしていこう、というものだと認識した。

コードラボの時間で Push 通知や Payment Request API も試してみたかったが、時間が足りなかったのでそのうちやってみたい。デファクトスタンダードみたいなものがない、 W3C で通った API をやることになるだろうので、実プロダクトに入れづらいところだが、そこはプログレッシブにやれたらいいな。

無料で、ランチもついて、きれいな会場で、丸一日めっちゃ楽しかった。 Google さんありがとうございました!

   技術的な話題   

いい感じに Javascript がゴリゴリ書かれていて、認証が必要なサイトを定期的にキャプチャを取る、という謎タスクが生まれ、ちょうど最近話題の Headless Chrome でも試してみるかな~~と思ったら puppeteer なるものがあるそうなので、これを使ってみる。

GoogleChrome/puppeteer: Headless Chrome Node API

GoogleChrome 配下にいるので Chrome 公式のパッケージだ。

// puppeteer 導入
$ npm init
$ npm install puppeteer

ドキュメントにもあるサンプルソースを入れてみる。

// index.js
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({path: 'example.png'});

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

https://example.com へとアクセスし、そのページをキャプチャして ./example.png に保存するソースだ。 await で簡単わかりやすい書き方になるのが素晴らしい。これを動かしてみる。

$ node index.js
(node:30285) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Failed to launch chrome!
/var/www/html/crawl/bitbucket_billing/node_modules/puppeteer/.local-chromium/linux-497674/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

(node:30285) [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.

かなしみ…。どうにも libXss.so.1 が開けずにエラーっぽい。パッケージを探してインストールし、再度動かしてみる。

$ yum provides */libXss.so.1
...

libXScrnSaver-1.2.2-6.1.el7.i686 : X.Org X11 libXss runtime library
Repo        : base
Matched from:
Filename    : /usr/lib/libXss.so.1

libXScrnSaver-1.2.2-6.1.el7.x86_64 : X.Org X11 libXss runtime library
Repo        : base
Matched from:
Filename    : /usr/lib64/libXss.so.1


$ sudo yum install libXScrnSaver
...

$ node index.js
(node:1345) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Failed to launch chrome!
/var/www/html/crawl/bitbucket_billing/node_modules/puppeteer/.local-chromium/linux-497674/chrome-linux/chrome: error while loading shared libraries: libgtk-3.so.0: cannot open shared object file: No such file or directory


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

(node:1345) [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.

GTK+3 が要求される。都合によって CentOS6 なのだが GTK+3 は入れるのがめっちゃ困難だった記憶。とりあえず GTK+3 というか Chrome を入れる方法を調べたら必要なライブラリも揃うだろう、と判断して調べる。

Google Chrome 60 Released - Install on RHEL/CentOS 7/6 and Fedora 26-20

Yes, they’ve discontinued support for RHEL 6.X version as of Google Chrome and on other side, latest Firefox and Opera browsers run successfully on the same platforms.

CentOS6 では Chrome は動かない、ダメ。Richard Lloyd 氏がスクリプトを作っているそうだが、そのサイトでも、いつまでも古いものを使うな、って書いてあった。

Site has been shut down

You have two choices really (ignoring Chromium, which no-one seems to be keeping up-to-date for RHEL/CentOS 6):

1. Use Mozilla Firefox ESR via "yum install firefox" that is shipped with RHEL/CentOS 6. Unfortunately, this can be up to a year out of date w.r.t. features compared to the more "normal" Mozilla Firefox that you can download from Mozilla (but that "normal" Mozilla Firefox is now also using GTK+3 and doesn't work on RHEL/CentOS 6 either).

2. Move to RHEL/CentOS 7, perhaps first in a VM before upgrading on bare metal once the VM is to your satisfaction. The latest Google Chrome installs and runs out-of-the-box on RHEL/CentOS 7 (see below).

まあ、一旦使ってみるなら docker でもいいか。

$ docker run -it -d -v $(pwd):/var/www/puppeteer_test centos:latest
Unable to find image 'centos:latest' locally
latest: Pulling from centos
6c5159923047: Pull complete
acec82331181: Pull complete
1c1b67b33c28: Pull complete
Digest: sha256:57c91a43765de2147fa666a128477bc6101d6fda660feaaa5fbb1a8b110c934f
Status: Downloaded newer image for centos:latest
2be8ec65e6e4db3d852d563b82cc4c90ca90f62b4aaa6304d6e00f06d6a4a9e7

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
2be8ec65e6e4        centos:latest       "/bin/bash"         16 seconds ago      Up 16 seconds                           romantic_sinoussi

$ docker exec -it 2be /bin/bash

# cd /var/www/puppeteer_test/
# ls
index.js  node_modules  package-lock.json  package.json

# node -v
bash: node: command not found

// nodeがいないので入れる
# curl -sL https://rpm.nodesource.com/setup_8.x | bash -
# yum install nodejs

# node index.js
(node:114) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Failed to launch chrome!
/var/www/puppeteer_test/node_modules/puppeteer/.local-chromium/linux-497674/chrome-linux/chrome: error while loading shared libraries: libpangocairo-1.0.so.0: cannot open shared object file: No such file or directory


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

(node:114) [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.

// とりあえず yum provides で探しながら一個ずつ入れていく
// をまとめたものがこちら
# yum groupinstall "Development Tools"
# yum install pango libXScrnSaver libXcomposite libXcursor libXi libXtst cups-libs libXrandr GConf GConf2 alsa-lib atk gtk3

// 起動してみる
# node index.js
(node:11985) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Failed to launch chrome!
[0920/101508.987383:ERROR:zygote_host_impl_linux.cc(88)] Running as root without --no-sandbox is not supported. See https://crbug.com/638180.


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

(node:11985) [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.

root で --no-sandbox なしは認められないらしいのでソースを変える。

// index.js
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({args: ['--no-sandbox']});
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({path: 'example.png'});

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

再び実行。

# node index.js

# ls
example.png  index.js  node_modules  package-lock.json  package.json

キャプチャ取れたので、画像を確認。

勝ち。

というわけで puppeteer 動いた。CentOS6 で CentOS7 が動いてて~ってちょっとアレなので、バージョン上げてまた試……、じゃない、本来の目的だった認証通してキャプチャできるかをやらなくちゃ。続く。

   技術的な話題   

Rx 云々を見かけるたびに Web でそんな出番ないような…?非同期やすとりーむや配列的なのをよろしくするやつ?と、もはや知ることを放棄していて。今頃もったいないなーと思ったので、改めてちょっと調べるの巻。

Rx について

ReactiveX - Intro

オブザーバーパターンを拡張したもので、シーケンスなデータやイベントをサポートするため、スレッドやノンブロックIOとかを抽象化して組み立てることができる。オブザーバーパターン = 監視する人と通知する人がいるよー、というイメージでとりあえずはよい。

Promise について

JavaScript Promiseの本

非同期処理を上手くパターン化して書くための、統一的なインターフェース。ここではオブザーバーという話はない。 コードを見ても、非同期を取りまわすためのいい感じのインターフェースである、というイメージ(個人の感想です)

Rx とPromise はどう使い分けるとよさそう?

いくつかサイトを眺めてみて。

JavaScriptの非同期処理には何を使うべきか - Qiita
State, Promise & Reactive プログラミング
What are the differences between observables and promises in JavaScript? - Stack Overflow

で、 Stackoverflow の回答が結構それっぽいのかなあと。

Simply put: A promise resolves to a single value asynchronously, an observable resolves to (or emits) multiple values asynchronously (over time).

ざっくり訳すと。

Observable (= Rx として) は多数の非同期を継続的に処理したい
Promise は単発の非同期処理をしたい

なので。

Rx は配列操作とか、画面操作とか、とかと相性がよい
Promise は単発になりがちのもの、外部呼出し(Ajaxとか)と相性がよい

このボタンおしたら Ajax して、待機状態にして、結果が来たらここを書き換えて、イベント設定して、… なんてものは Rx と Promise を組み合わせるといいのかもしれない。が、昨今のフロントエンドにおいては Flux なんかでライブラリの中でよろしくやっていることが多いので、あえて開発する人が関与していくことは少ない…?

どちらかというとアプリ系で Rx が盛り上がってる気がしていて、 Web フロントではそうでもないような…。どっちも知識薄くてわからんのだけど、言語が違っても画面とロジック、裏でデータがほいほい、みたいなことってどちらも一緒のことだと思うんだけど、その差はなんなんなん?

   技術的な話題   

開発用だったり検証用だったりで docker をぼちぼち使っているのですが、ゲストのポートをホストのポートへバインドするときに、IPアドレスを指定できます。

$ docker run -it -d -p 127.0.0.1:10080:80 myapp

どこで使うんだよって話ですが、セキュリティを考えるときには使うんじゃないっすかね、たぶん。

IPアドレスの指定がないと 0.0.0.0 で待ち受けるので、接続をどこからでも受け付けます。そのため、例えばホスト側で nginx 等を使って何かしらの認証が必要なリバースプロキシをしていたとしても、指定ポートでコンテナに直接アクセスができてしまいます。

nginx で不特定多数から見られないよう Basic 認証を設定していたのですが、見れるのかな?ってポート指定してアクセスしたら無事に見れてしまって、うふふってなってました。

$ docker run -it -d -p 10080:80 nginx
485e21a84ea180bc69db198bcdb7e417fb61d2747642059b8bd4435873aa1503

$ netstat -nao | grep 10080
tcp        0      0 :::10080                    :::*                        LISTEN      off (0.00/0/0)

$ docker rm -f 485
485

$ docker run -it -d -p 127.0.0.1:10080:80 nginx
94ea5a9d74578fc69777cf0dc3b7dc918ce2e4ec74fef52441521a8d163680d8

$ netstat -nao | grep 10080
tcp        0      0 127.0.0.1:10080             0.0.0.0:*                   LISTEN      off (0.00/0/0)

ドキュメントはここ
https://docs.docker.com/engine/reference/commandline/run/#publish-or-expose-port--p-expose

   生きる   

プロポーズはおととしの 12 月にしていて、入籍は昨年 4 月にしていて、お金や時間の都合で時間差、今年の 5 月くらいに結婚式を挙げてました。

あ、結婚式の日に結婚式なう~~~みたいなツイートしそこねた…。

当然ながら人生初の結婚式だったわけですが、いわゆるホテルウェディングとか、神社でーとか、そういう形にはしませんでした。

株式会社 CRAZY がやっている、コンセプトや内容、演出などなど、1 からウェディングのプランニングしていって、最高の1日をみんなで作っていこう、というものを利用しました。クレイジーって最近テレビ出たりメディア出たりで結構盛り上がっているそうですよ☆

株式会社 CRAZY (株式会社クレイジー) | CRAZY,Inc.

コンセプトウェディングのプロデュースチーム | CRAZY WEDDING (クレイジーウェディング)

そんなクレイジーウェディングで迎えた、ぼくらの最高の1日の様子をちょっとだけご紹介。

余談ですけど Theta S + 自撮り棒 をもっていったので、ハットなのも相まってステッキ!?って驚かれました。集合写真とか、歩き回るときに動画とったりして面白い画になりましたとさ。おすすめ。

クレイジーウェディングでよかったこと

・これやるならウン万ですよみたいな営業がほぼされなかった
・現実的に出来ることは何でもできる(お金しだい)
・コンセプトをちゃんとすり合わせて決めるので本人たちの納得感、やった感が非常に強い
・家族メッセージしっかり伝えられた

自分たちがどういうことをしたいのかを考えたり、自分たちがどういう人生を歩んできたのかを話したり、そもそもなんで結婚式するんだっけを考えたり…。そうこうして、プロデューサーの方からワクワクするようなコンセプトが提案されました。
一部抜粋ではありますが、ぼくらの場合はこんなコンセプトです。


オモシロ屋
いつでもどこでも オモシロイこと 創ります 材料はこの世界にあるものすべて

新しいものを ゼロから創り出すことを 楽しんで生きてきた 僕と
誰よりユニークを愛し 好奇心を元に 手を抜かず生きてきた 私

ふたりでいたら最強です

こうしたい!という想像力と 遊びゴコロがあれば どんなものだって創り出せる
飽くなき探求心と 人を笑顔にしたい想い それがオモシロ屋の原動力


最初にこのコンセプトを見聞きしたときにちょっと感動しちゃって涙が出かかるほどに。で、このコンセプトを、結婚式当日直前の会場装飾と初対面ってときにも読まれて、会場ながめてこれまだ涙が。エモい言葉に弱いんですかね、ぼく。

コンセプトイメージがレトロなモダンな和風チックな感じで、それに合わせて会場の装飾だったり、席札だったり、ぼくらの衣装も見ていました。だから、その日、その会場はすべてが「オモシロ屋」です。っていうくらい作りこむ文字通りのクレイジーな集団で、こっちはめっちゃ驚くし感動するしでした。

クレイジーウェディングちょっと微妙だったところ

・プロデューサーさんめちゃんこいそがしそう

ほぼすべて良くて、はーーーーやってよかったなーーーー、みたいな空気感に包まれていたのですが、プロデューサーさんが掛け持ちしたりで、結果忙しそう(に見える)ので、連絡するのに気が引けてしまったり、とかとか。
話を聞くところによると、それで提供したいことや考えたいことがうまくできていなかったところもあったそうなので、体制ややり方を変えていっているそうですよ!これからやるひとはきっと大丈夫だと思います!

個人的な反省

・炎上プロジェクトだった(直前でもうれつにがんばらないといけなかった)
・人呼びたりなかった。。 Party !!にしたかったけど会場キャパとかコンテンツとか。。

二人で作っていくので、細かいスケジュールややること整理は自分たちで管理していかないといけないです。もちろんプロデューサーさんがお手伝いはしてくれますが、すでに書いてある"忙しそう"が相まって、煽りがされないこともしばしばありました。
一応 Trello を使ってやることと日程の管理はしていたのですが、直前 1-2 週間くらいは動画つくったりなんだりーってやっていました。
あ!ぼくらの場合は、ある程度自分たちでも作りたいっていう意思があったので、動画とか。プロにお任せするのがお手軽らくちんではあるのですが、自分たちでやったほうがやりたいようにできるんじゃないかなーと。

ちなみに動画作成は Vegas Pro 14 です。2,3 年くらいまえに 5000 円?だったかなあ、のセールをしてたところで買って、それからずっと使ってます。動画作成する仕事ではないのですが、ちょこちょこと動画つくってよ~~なんてお願いがあったりするので、そういうところで。

個人的にはめっちゃ人呼んでパーリナイにして高まる曲をもりもりと流したかったのですが、予算都合だったり、妻との調整の結果、ってところでですね。それでももう少し呼びたい人たちもいましたし、呼べなかったのマジゴメンの気持ち。会場キャパが 80 くらいだったんだよ~~~


というところで。

結婚式も披露宴も、こちらは非常に楽しくやっていましたし、ゲストの盛り上がりも良くて、後で話を聞いてもよかったねー、だったのも嬉しいポイントでした。自由度高くお金と頑張り次第でなんでもいけるのでクレイジーウェディングおすすめです!

あと干し芋を置いておきますね、お祝いの気持ちが湧いてきたらお願いします。
http://amzn.asia/j4BudTt

   技術的な話題   

NGINX Unit なるものがリリースされたらしい。

・NGINX 公式サイトの情報
NGINX Unit

・NGINX Unit 公式サイト
NGINX Unit

・見かけた記事
NGINXからアプリケーションサーバ「NGINX Unit」がオープンソースで登場。PHP、Go、Pythonに対応。Java、Node.jsにも対応予定 - Publickey

ドキュメントに書かれているインストール方法や設定を見てたらパッと出来そうだったので思いたってやったったの巻。

Read more »