helen's blog

ずっとおもしろいことしてたいな。

GulpとEJSで設定をできるだけ減らしてみた

設定ファイルを手で書くとミスるし
ストレスマッハなのでがんばって減らしてみました

ファイル構成

ページの中身をcontentsとしてURLに合わせてディレクトリを切り、
それぞれのjndex.ejsの上下にheadやらfooterやらをくっつけて使います

.
├── contents # ページの中身
│   ├── index.ejs
│   └── hoge
│       └── fuga
│           └── piyo
│               └── index.ejs
└── layouts
    ├── common # front、mypageから使う共通系パーツ
    │   ├── _navi.ejs
    │   ├── _localNavi.ejs
    │   ├── _logged.ejs
    │   └── _notLogin.ejs
    ├── front # フロントで使用するパーツ
    │   ├── _footer.ejs
    │   └── _headTag.ejs
    ├── frontAfterContent.ejs # フロントの要素の後につけるパーツ
    ├── frontBeforeContent.ejs  # フロントの要素の前につけるパーツ
    ├── mypage # ログイン後に使用するパーツ
    │   ├── _footer.ejs
    │   ├── _headTag.ejs
    │   └── _header.ejs
    ├── mypageAfterContent.ejs # ログイン後の要素の後につけるパーツ
    └── mypageBeforeContent.ejs # ログイン後の要素の前につけるパーツ

headerやfooterの間をクルクル回すのをよく見るけど
for文書くとどこで何が動いてるのかわからなくなるので、
各contentsで何を呼ぶか明示します

gulpfile

ここでfor文で回すのをよく見るけどやらず、コンパイルして拡張子をhtmlにしてるだけ
contents/**/*.ejsな感じにすると
ディレクトリ階層を維持したままコンパイルしてくれるので設定書かなくて済む

const gulp = require('gulp');
const ejs = require('gulp-ejs');
const jsonData = require('./settings.json');

gulp.task('default', ['main']);
gulp.task('main', ['ejs']);

gulp.task('ejs', function(){
    return gulp.src(
        ['contents/**/*.ejs', '!' + 'contents/**/_*.ejs']
    )
        .pipe(ejs({jsonData:jsonData}, {'ext': '.html'}))
        .pipe(gulp.dest('../'));
});

setting.json

設定をまとめて名前をつけて呼び出せるようにして

{
    "default":{
        "title":"title",
        "description":"description"
    },
    "hogefugapiyo":{
        "title":"fugaaaa",
        "isLogin":true
    }
}

こんな感じで呼び出す

<% data = jsonData.default; %>

特に個別の指定がなければdefaultとか書いとく感じ
CakePHPだとcontrollerでtitle、descriptionを決めれるから(こうあるべきかは別の話)
URLのコントローラーまでの設定を作っとけば
同じコントローラーのアクションどうしはその設定を使いまわせるっていう幸せ

呼び出し

使いたい設定の名前を変えるだけ

<% data = jsonData.default; %>
<%- include('../layouts/frontBeforeContent', data); %>
<!-- 要素 -->
<%- include('../layouts/frontAfterContent'); %>
<!-- frontAfterContentは渡すデータがないから書いてないけどdataあると今後幸せになれそう -->

で、上下のパーツは

$ cat layouts/frontBeforeContent.ejs
<!DOCTYPE html>
<html>
  <%- include('../layouts/front/_headTag', data) %>
  <body class="lo1 skin-blue">
    <%- include('../layouts/common/_gnavi') %>
    <%- include('../layouts/common/_makeNavi') %>
    <%- include('../layouts/common/_akibaNavi', data) %>
$ cat layouts/frontAfterContent.ejs
    <%- include('../layouts/front/_footer') %>
  </body>
</html>

各小パーツを呼び出すだけにして、
1箇所いじれば全部に反映されるようになってる

ログイン判定

ログイン前ログイン後で表示が変わるものは設定ファイルで管理

ログイン済みにしたいページのみsettingにこれを追加して

"isLogin":true

パーツはこんな感じにする

<% if(data.isLogins){ %>
    <%- include('../common/_logged'); %>
<% } else { %>
    <%- include('../common/_notLogin'); %>
<% } %>

まあほんとはtrue,falseで管理されてるのかわかんないけどねー
isLoginがtureってイメージしやすいからそう書いてます

json書きたくねーymlにする!って言ってたけど
最終的にymlにするのがめんどうになりました

GulpとEJSやってみた

フロントのコーディングを早めるために使い始めるらしいのでやってみました

使うもの

Gulp

スクランナーしてくれるやつ
gulp.js - the streaming build system

EJS

JSをつかってHTMLを生成してくれる
includeとかして楽できる
EJS -- Embedded JavaScript templates

Gulpから試してみる

ファイルを移動するだけの簡単なお仕事です

インストール

$ npm install gulp --save-dev

設定ファイル作成

$ vim gulpfile.js

const gulp = require('gulp');

gulp.task('ejs', function() { // タスク定義
    gulp.src(
        ['./*.ejs', '!' + './_*.ejs'] // _から始まるejsファイルを除外
    )
        .pipe(gulp.dest('../dist')); // 出力先
});

ejsファイルをdist/に出力という設定です

実行してみた

$ vim ejs/hoge.ejs
hoge
$ gulp ejs 
Local gulp not found in ~/hoge/ejs
Try running: npm install gulp

あるぇー入れたのになー
link | npm Documentation
どうやらグローバルのnpmにリンクを貼らないといけない模様

$ npm link gulp
/Users/heleeen/hoge/node_modules/gulp -> /usr/local/lib/node_modules/gulp

$ gulp ejs 
module.js:338
    throw err;
          ^
Error: Cannot find module './lib/_stream_transform.js'
    at Function.Module._resolveFilename (module.js:336:15)
    at Function.Module._load (module.js:278:25)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at Object.<anonymous> (/Users/heleeen/hoge/node_modules/gulp-ejs/node_modules/through2/node_modules/readable-stream/transform.js:1:80)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)

モジュールが足りないらしいので
足りないものを一気に入れちゃいます
ちなみに入れ直しでごちゃごちゃエラー出たので
一旦node_modulesディレクトリ抹消しました

$ npm install -g npm-install-missing
/usr/local/bin/npm-install-missing -> /usr/local/lib/node_modules/npm-install-missing/bin/npm-install-missing
npm-install-missing@0.1.4 /usr/local/lib/node_modules/npm-install-missing
├── async@2.0.1 (lodash@4.15.0)
└── npm@3.10.6

【Node.js】足りないモジュールをたったの一行でインストールするコマンド - Qiita

今度こそ

$ gulp ejs
[12:49:29] Using gulpfile ~/work/gulp/gulpfile.js
[12:49:29] Starting 'ejs'...
[12:49:29] Finished 'ejs' after 15 ms

# 確認
$ less dist/hoge.ejs
hoge

できた

ejsでhtmlをincludeして楽しちゃう

次はejsをパーツ化してincludeして
共通パーツは1つのファイルを編集すれば同じ箇所が変わるようにしちゃいます

インストール

$ npm install gulp-ejs --save-dev

準備

# 荒れそうなのでsource/からdist/に出力します
$ vim gulpfile.js
const gulp = require('gulp');
const ejs = require('gulp-ejs');

gulp.task('ejs', function() {
    gulp.src(
        ['./source/*.ejs', '!' + './source/_*.ejs']
    )
        .pipe(ejs({}, {'ext': '.html'})) // 拡張子指定
        .pipe(gulp.dest('./dist'));
});

# 用意したファイル
$ ls -l source
-rw-r--r--  1 helen  staff  46  9 11 12:59 _footer.ejs # htmlにしたくないファイルは_つける自己ルール
-rw-r--r--  1 helen  staff  66  9 11 12:58 _header.ejs # htmlにしたくないファイルは_つける自己ルール
-rw-r--r--  1 helen  staff  63  9 11 13:01 hoge.ejs

$ vim source/hoge.ejs
<%- include('./_header') %> # _header.ejsをinclude
hoge
<%- include('./_footer') %> # _footer.ejsをinclude

# 実行
$ gulp ejs
[00:23:31] Using gulpfile ~/work/gulp/gulpfile.js
[00:23:31] Starting 'ejs'...
[00:23:31] Finished 'ejs' after 13 ms
# 確認
$ ls -l 
ls -l dist
total 8
-rw-r--r--  1 helen  staff  121  9 12 00:23 hoge.html # できてる!

$ less dist/hoge.html # いい感じ!
<head>
  <meta charset="utf8">
  <title>gulp test</title>
</head>
hoge
- 
<footer>
  <p>Copyright heleeen</p>
</footer>

拡張子変換してるとこ

さっきのにあるこれだけ
jsonファイルを使わないため適当にかっこつけたのですがうまくいきました

 .pipe(ejs({}, {'ext': '.html'}))

gulp-ejs 2.0.0 で .html ファイルを出力する場合拡張子の指定が必須に - Qiita

deployerをちょろっとためしたいだけなのにいきなりsyntax errorされた件

deployerについてはこちら↓
Deployer — Deployment Tool for PHP

ちなみに選定理由はPHP製デプロイツールをググって一番最初に出てきたことです
あと公式サイトがかっこよすぎてやばい

導入

$ curl -L -O http://deployer.org/deployer.phar

エラー内容

PHP Parse error:  syntax error, unexpected '[' in phar:///home/vagrant/deployer.phar/bin/dep on line 14

原因

deployerはPHP5.5以上が必要
yum install phpしたときは5.3のためエラー

PHP5.5以上をインストール

$ sudo rpm -Uvh http://ftp.iij.ad.jp/pub/linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
$ sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm

$ sudo yum -y install --enablerepo=remi --enablerepo=remi-php56 php php-opcache php-devel php-mbstring php-mcrypt php-mysqlnd 

$ php deployer.phar deploy


  [RuntimeException]
  You need to specify at least one server or stage.


deploy [-p|--parallel]

動きはした
一旦動かしたいだけなので不思議な動かし方をしていることは気にしない

vagrantでWarning: Authentication failure. Retrying...が出まくる時

仮想環境準備

Vagrant by HashiCorp
Downloads – Oracle VM VirtualBox
A list of base boxes for Vagrant - Vagrantbox.es

$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Box 'bento/centos-6.7' could not be found. Attempting to find and install...
   default: Box Provider: virtualbox
   default: Box Version: >= 0
==> default: Loading metadata for box 'bento/centos-6.7'
   default: URL: https://atlas.hashicorp.com/bento/centos-6.7
==> default: Adding box 'bento/centos-6.7' (v2.2.7) for provider: virtualbox
   default: Downloading: https://atlas.hashicorp.com/bento/boxes/centos-6.7/versions/2.2.7/providers/virtualbox.box
==> default: Successfully added box 'bento/centos-6.7' (v2.2.7) for 'virtualbox'!
==> default: Importing base box 'bento/centos-6.7'...
==> default: Matching MAC address for NAT networking...
==> default: Checking if box 'bento/centos-6.7' is up to date...
==> default: Setting the name of the VM: default_1470938359502_67401
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
   default: Adapter 1: nat
   default: Adapter 2: hostonly
==> default: Forwarding ports...
   default: 22 (guest) => 2222 (host) (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
   default: SSH address: 127.0.0.1:2222
   default: SSH username: vagrant
   default: SSH auth method: private key
   default:
   default: Vagrant insecure key detected. Vagrant will automatically replace
   default: this with a newly generated keypair for better security.
   default:
   default: Inserting generated public key within guest...
   default: Removing insecure key from the guest if it's present...
   default: Key inserted! Disconnecting and reconnecting using new SSH key...
   default: Warning: Authentication failure. Retrying...
   default: Warning: Authentication failure. Retrying...
   default: Warning: Authentication failure. Retrying...

   ...

   default: Warning: Authentication failure. Retrying...
   default: Warning: Authentication failure. Retrying...
Timed out while waiting for the machine to boot. This means that
Vagrant was unable to communicate with the guest machine within
the configured ("config.vm.boot_timeout" value) time period.

If you look above, you should be able to see the error(s) that
Vagrant had when attempting to connect to the machine. These errors
are usually good hints as to what may be wrong.

If you're using a custom box, make sure that networking is properly
working and you're able to connect to the machine. It is a common
problem that networking isn't setup properly in these boxes.
Verify that authentication configurations are also setup properly,
as well.

If the box appears to be booting properly, you may want to increase
the timeout ("config.vm.boot_timeout") value.

ひたすら
default: Warning: Authentication failure. Retrying...
した挙句にエラーを吐き、vagrant sshでパスワードを求められる

原因

vagrant1.7以降の仕様です

vagrant upすると、対象のゲストOSに対して新たな鍵のペアを生成して配置するため、
環境によってはデフォルトのinsecure_private_keyとの合わずにエラーが発生する

config.ssh.insert_key - If true, Vagrant will automatically insert a keypair to use for SSH, replacing Vagrant's default insecure key inside the machine if detected. By default, this is true.


This only has an effect if you do not already use private keys for authentication or if you are relying on the default insecure key. If you do not have to care about security in your project and want to keep using the default insecure key, set this to false.



ssh.insert_key がtrueの場合、
vagrantvagrant内のデフォルトの安全でないキーが検出されると、SSHで使用する鍵ペアを置き換える

未使用の秘密鍵の場合、デフォルトの安全でないキーを使用している場合にのみ影響がある
セキュリティを気にする必要があり、デフォルト安全でないキーを使用したい場合、これをfalseに設定してください

config.ssh - Vagrantfile - Vagrant by HashiCorp

直し方

Vagrantfileに下記追加

config.ssh.insert_key = false

追加前

vagrant ssh-config                                                                                                    ⏎
Host default
  HostName 127.0.0.1
  User vagrant
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile /Users/heleeen/work/infra/deploy_test/.vagrant/machines/default/virtualbox/private_key
  IdentitiesOnly yes
  LogLevel FATAL

追加後

$ vagrant ssh-config
Host default
 HostName 127.0.0.1
 User vagrant
 Port 2222
 UserKnownHostsFile /dev/null
 StrictHostKeyChecking no
 PasswordAuthentication no
 IdentityFile /Users/heleeen/.vagrant.d/insecure_private_key # ここが変わる
 IdentitiesOnly yes
 LogLevel FATAL