今から始めるWebフロントエンド開発を読んで勉強した(パート2)

前回の記事の続きです。

多くなったので、2つに分けました。

前回はモダンなフロントエンド開発を行うためのライブラリ群の紹介になってましたが、今回はそれらのライブラリ + Reactを使用したTODOアプリを作成したいと思います。

TODOアプリを作成ながら、Reactの勉強になったところを記事にして、自分の知識にしていきたいと思います。

Redux

作成するTODOアプリでは、React + Reduxという枠組みで作成していくようです。

Reduxってなに?だったので調べました。

Reduxは 設計思想(デザインパターン) ということでした。

Reduxの大本にはFluxという物があるようで、そちらも調べてみました。

Fluxのポイントは、 データを一方向にしか流れない設計 ということのようです。

Action -> Dispatcher -> Store -> View

ReduxはFluxからの派生の設計ということです。

今回読んでいる本を見てみるとReduxの流れは以下のようです。

  1. Viewがユーザーの入力を受けつける
  2. ViewがActionCreatorに入力値をわたす
  3. ActionCreatorは「何をするのか」というActionをViewに返す
  4. Viewは受け取ったActionをそのままStoreに渡す
  5. Storeは受け取ったActionとStoreが保持している「今の状態」を示すStateをReducerに渡す
  6. Reducerは貰ったActionStateを解釈して、「新たな状態」となるStateをStoreに返す
  7. StoreはReducerから貰った新たな状態を持ち直して、その後Reactがデータバインディングを用いてViewに渡す(反映する)

登場人物がいっぱいいるようでしたが、View, ActionCreator, Store, Reducer です。

View

Viewに関するロジック以外は一切持たないことが特徴で、ユーザーから何かしらの入力があれば、ActionCreatorに通達して、そのまま横流しで貰ったActionをStoreに渡すだけなので、シンプルに実装できます。

View関係のロジックなのでDOMの変更なども行います。

View以外のロジックを持たないので、デザイナ・エンジニアで作業の切り分けが楽になります。

ActionCreator

どんな操作が生じるのか(できるのか)だけを知っているだけです。

その操作を行うことでどんな処理を実装するか、どんな影響があるかは気にしません。

アプリケーションで行う操作が増えたらActionCreatorに扱える操作を一つ増やすという感じです。

Store

「今の状態」を保持しているStateを管理する場所です。

Reducer

「○○が起きたら、○○の状態になる」という状態の変化についての知識を持つ場所です。

状態変化の知識のみで、データの状態や表示の変更はStoreやViewがやるので、そのあたりは一切管理しません。

Reactで簡単なものを作ってみる

早速何か作ってみます。

サンプルのTODOアプリそのままだと、流石にまずいので少し改良版で行きたいと思います。

また、今回はReduxのはなしにして、Reactだけしようしたものを作成したいと思います。

とりあえず、主要ライブラリ群をインストールします。

今回は、依存関係解決のためのツールは、browserifyではなく、 webpackを使ってみようと思います。

webpackのほうが後発で、jsだけでなく、css, imageなどもまとめることが出来る優れもののようです。

今回は yarn でインストールしてみます。

$ yarn add css-loader style-loader babel-loader babel-core babel-preset-es2015 babel-preset-react webpack webpack-dev-server --dev
$ yarn add react react-dom

webpack.config.js

webpackの設定ファイルは以下になりました。

const webpack        = require('webpack');
const path           = require('path');
const distPath       = path.resolve(__dirname, 'dist');
const nodeModulePath = path.resolve(__dirname, 'node_modules');

const config = {
    entry:  './src/app.js',
    output: {
        path:     distPath,
        filename: 'app.js'
    },
    module: {
        rules: [{
            test:    /\.js$/,
            exclude: distPath,
            loader:  'babel-loader',
            query:   {
                presets: ['react', 'es2015']
            }
        }, {
            test:    /\.css$/,
            exclude: nodeModulePath,
            loader:  ['style-loader', 'css-loader']
        }]
    },
    devServer: {
        contentBase: distPath,
        port:        5260
    }
};

module.exports = config;

webpack-dev-serverを立ち上げると、Reactの環境を実行できます。

今回作成したアプリはコチラに上げておきます。

とりあえず、今回はここまで・・・

周辺知識はなんとなくわかってきましたが、肝心のReactは難しいです。

最終的にはReact-Nativeでアプリを作るところがゴールなので、もう少し勉強します・・・!

今から始めるWebフロントエンド開発を読んで勉強した(パート1)

こんにちは。

フロントの勉強するにあたって、最近のモダンなフロントエンド開発を知らないため、コチラの本を購入しました。

Backbone.jsから止まっている自分の時間をすすめるため、頑張って勉強しました。

コチラの本では、3分の1以上がJSの歴史と、現代の仮想DOM時代への流れが記載されていました。

その後簡単なTODOアプリを作成します。その際に、モダンなフロントエンドの技術を用いて開発を行います。

それぞれ名前はしっているけど、実際に使用したことはほぼないものばかりでした。

今回はこちらを自分なりに噛み砕きながら、覚えるためにブログ記事にしていこうと思います。

使用したツール群

BABEL

ES2015準拠で書かれたJSコードをES5のもの(各ブラウザで動かせるもの)に変換してくれるトランスパイラというものです。

開発時にES2015準拠でコードを書いていき、製品版として仕上げる際は、BABELを噛ませてES5のものに変更するという使い方だと思います。

インストール

# Babelのインストール
$ npm install --save-dev babel-cli

# ES2015からの変換を行うプリセットをインストール
$ npm install --save-dev babel-preset-es2015

セットアップ

.babelrc というファイルが、babelの設定ファイルとなります。コチラを作成し、以下になるように編集してください。

$ cat .babelrc 
{
  presets: ["es2015"]
}

使ってみる

テスト用のjsファイルを作成して、以下のコードを書いてみました。

# test.js
class A {
  constructor() {
    this.name = 'Aですよ';
  }

  getName() {
    return this.name;
  }
}

こちらをBabelで変換してみます。

変換のコマンドは以下になります。

# -oでファイルに書き出しする
node_modules/.bin/babel test.js -o compiled.js

出来上がったファイルの中身は以下になります。

# compiled.js

'use strict';
  
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var A = function () {
  function A() {
    _classCallCheck(this, A);

    this.name = 'Aですよ';
  }

  _createClass(A, [{
    key: 'getName',
    value: function getName() {
      return this.name;
    }
  }]);

  return A;
}();

正常に変換されているようでした。

Browserify / WebPack

各JSファイルの依存関係をよしなに解決してくれて、一つにまとめてくれる優れものツールということでした。

WebPackに関しては、JSに限らず、cssや画像などもまとめて1つのjsファイルにしてくれるようです。

該当のJSファイルに書かれているrequire関数を読み取り、依存関係を解決してくれます。

require関数とは?と思って調べると、CommonJS Modulesというものに含まれているということでした。

CommonJSとは?と調べると、以下引用です。

CommonJSとは、サーバーサイドなどのウェブブラウザ環境外におけるJavaScriptの各種仕様を定めることを目標としたプロジェクトである。

ツールというより仕様ということでした。

NodeJSのモジュールシステムはこれを元に動いているようです。

大本ということなのでしょうか?

どちらにしても、nodejs経由でインストールしているため、どちらもrequire関数を検知できるということなのだと理解しました。

(もう一つのモジュール管理でAMDというものがあり、そちらにRequireJSというのがあるようです。こちらもrequire関数と同等のものが使え、webpackに関してはコチラも対応しているということでした)

こちらの本では、Browserifyを使用していたので、自分も例にそって同じものを使ってみます。

インストール

$ npm install --save-dev browserify

使ってみる

早速使ってみます。 以下のような3つのJSファイルを作成します。

# test1.js
let a = require('./test2.js');
console.log(a.getName());

let b = require('./test3.js');
console.log(b.getName());
# test2.js
class A {
    constructor() {
      this.name = 'my name is A!';
    }

    getName() {
        return this.name;
    }
}
module.exports = new A;
# test3.js
class B {
    constructor() {
      this.name = 'my name is B!';
    }

    getName() {
        return this.name;
    }
}
module.exports = new B;

test1.jsはtest2.jsとtest3.jsに依存しているものがわかると思います。

こちらをbrowserifyで変換してみます。

$ node_modules/.bin/browserify test1.js -o bundle.js

後は確認のため適当なHTMLを作成します。

# test.html
<!DOCTYPE html>
<html>
<head>
    <title>test</title>
</head>
<body>
    <script type="text/javascript" src="bundle.js"></script>
</body>
</html>

test.htmlをブラウザで開きconsole.logを確認すると、以下のようになると思います。

f:id:kojirooooocks:20180115010855p:plain

実際の開発現場では、ES2015でJavaScriptコードを書いていき、Babelで各ブラウザ対応のJSへ変換し、Browserify(WebPack)を使用して依存関係を解決し1つにまとめるというのが流れのようです。

(この本は2016年8月くらいの本なのですが、今もそうなんでしょうか・・・?知ってる人いたら教えてください)

Babelify

コード修正の度に、Babelコマンド叩いて、Browserifyを叩いてとするのはとてもめんどいです。

さらに以下、引用ですが、重要なところが書かれていました。

require関数はもともとはNode.jsで用意されていた関数で、importやexportはES2015で定義された仕様です。これに対してBabelは、importをrequire関数に変換しますが、多くのブラウザではrequire関数を読み込めず、モジュール間の依存解決を解決できません。

たとえば、A.jsでimportを、B.jsでexportを使用している場合、それぞれBabelを噛ませることで各ブラウザ対応のJSへ変更してくれます。

その際、A.jsのimportはrequireに変換されますが、対象ファイル自体はBabelを実行する前のES2015で記述されているファイルになります。

Browserifyを実行する前にわざわざファイルを開いて、Babel実行後のファイルに向き先を変更して上げる必要があります。

これはあまりにつらい作業です。。。

その辺の辛さを解消してくれるのがBabelifyというツールです。

BabelifyはBrowserifyの変換時にES2015の変換も同時に行ってくれるものです。つまりBabelの仕事も一緒にやってくれるということのようです。

インストール

$ npm install --save-dev babelify

使ってみる

例となるスクリプトはありませんが、以下が実行コマンドになります。

# -tオプションで babelifyを指定する
$ node_modules/.bin/browserify A.js -t babelify -o bundle.js

ESLint

本ではその他の取り組みとして、JSコードの静的解析を行うツールとして名前だけ紹介されていましたが、今回せっかくなので、どんなものか試してみたいと思います。

コチラを参考にしました。

インストール

$ npm install --save-dev eslint

セットアップ

eslintのセットアップを行います。

色々と質問されます。

CommonJS使いますか?JSX使いますか?React使いますか?などなど。

Yesとすると追加パッケージを落とすこともあります。 (Reactとかはそう)

$ ./node_modules/.bin/eslint --init
? How would you like to configure ESLint? Answer questions about your style
? Are you using ECMAScript 6 features? Yes
? Are you using ES6 modules? Yes
? Where will your code run? Browser
? Do you use CommonJS? Yes
? Do you use JSX? No
? What style of indentation do you use? Spaces
? What quotes do you use for strings? Double
? What line endings do you use? Unix
? Do you require semicolons? Yes
? What format do you want your config file to be in? JSON

回答が終了すると以下のようなファイルが作られます。

# .eslintrc.json
{
    "env": {
        "browser": true,
        "commonjs": true,
        "es6": true
    },
    "extends": "eslint:recommended",
    "parserOptions": {
        "sourceType": "module"
    },
    "rules": {
        "no-console": "off",
        "indent": [
            "error",
            4
        ],
        "linebreak-style": [
            "error",
            "unix"
        ],
        "quotes": [
            "error",
            "double"
        ],
        "semi": [
            "error",
            "always"
        ]
    }
}

使ってみた

eslintのテストをするため以下のファイルを作成しました。

# eslint_test.js
class Cats {
    Constructor(name) {
        this.name = name;
    }

    getName() {
        return this.name;
    }
}

let cats = Cats('ドラえもん');
console.log(cats.getName())

このファイルを対象にeslintを実行してみます。

$ ./node_modules/.bin/eslint eslint_test.js

/home/vagrant/eslint_test.js
  11:17  error  Strings must use doublequote  quotes
  12:1   error  Unexpected console statement  no-console
  12:28  error  Missing semicolon             semi

✖ 3 problems (3 errors, 0 warnings)
  2 errors, 0 warnings potentially fixable with the `--fix` option.

ダブルクォート使えよっていうのと、セミコロン付け忘れてるぞ!っていうのは理解できました。

no-consoleというのはなんだろうと、調べていると、最初のeslintが設定してくれているおすすめ設定の中に、console記述禁止の設定があるようです。

console.logは使いたいので、rulesを書き変えてみます。

.eslintrc.jsonrules の部分に以下を追記します。

"no-console": "off",

セミコロンとダブルクォートの修正も行い、再度実行してみます。

$ ./node_modules/.bin/eslint eslint_test.js

何も表示されなくなりました。つまり静的解析は問題なく通っているということになります。

便利ですね!

uglify

javascriptコードのminifyを行うさいには uglify を使うようです。

こちらは本で紹介されていませんが、まぁ実際にアプリケーションを使って本番に公開する際はきっと使うことになるでしょうし、実際使ってみます。

ちなみにこちらはgulp経由で使用した経験はありますが、ググりながらコピペで使ってたので、理解はしていませんでした。。

インストール

$ npm install --save-dev uglify

使ってみた

上の方でbabelコマンドを使って変換したjsファイルで実験してみます。中身は以下。

'use strict';

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var A = function () {
  function A() {
    _classCallCheck(this, A);

    this.name = 'Aですよ';
  }

  _createClass(A, [{
    key: 'getName',
    value: function getName() {
      return this.name;
    }
  }]);

  return A;
}();

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

$ node_modules/.bin/uglifyjs compiled.js -c -m -o compiled.min.js

実行で出来たファイルの中身は以下。

"use strict";function _classCallCheck(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}var _createClass=function(){function e(e,n){for(var t=0;t<n.length;t++){var a=n[t];a.enumerable=a.enumerable||!1,a.configurable=!0,"value"in a&&(a.writable=!0),Object.defineProperty(e,a.key,a)}}return function(n,t,a){return t&&e(n.prototype,t),a&&e(n,a),n}}(),A=function(){function e(){_classCallCheck(this,e),this.name="Aですよ"}return _createClass(e,[{key:"getName",value:function(){return this.name}}]),e}();

圧縮・難読化されていました!

終わり

なんか周辺ツールの勉強だけで結構なボリュームになってしまった。。。

TODOアプリはReactを使って作成するので、今度はそちらの勉強記事をあげようと思います。

では。

投稿数が早くも2017年を超えた件

先ほど今週1発目の記事を上げたのですが、ふと見ると2017年の記事の総数を超えていました。

まぁ振り返り記事とかもあるので、実のある記事は6記事ですが。

それでも早くも超えたことに感激しました。

人間やろうと思えば出来るもんですね。

丁寧に記事を書いておけば、勉強しておいたことを思い出すきっかけにもなるし、本当に一石二鳥と思いました。

これからも頑張って記事書いて、自分の勉強を続けていこうと思います。

さて。筋トレしてねよ。

JavaScriptの復習を行った

概要

今までNode.jsやReactNativeに触れて、自分のJSの知識がいかに乏しいかというのを、しっかり理解することが出来ました。

今年度の目標として、フロントエンドの知識を身につけるというのがあるので、これを機会にしっかり基本から勉強し直して、自分のJSの知識の底上げをしていきたいと思います。

参考にした本

色々とJS関連の本を漁ったところまさに良さそうな内容の本が何冊かありましたので、それらを見ながら、復習をしていきたいと思います。

今回は以下の本を見ながら、脱初心者を目指そうと思います。

脱初心者のJavaScript力を底上げするための本

参考になったところ

argumentsオブジェクト

関数に渡された引数全てを管理しているオブジェクト

配列に似た構造を持ってるけど別物。

function test(aaa, bbb, ccc) {
    for (var p of arguments) {
        console.log(p);
    }
}

test('ドラえもん', 'のび太くん', 'しずかちゃん', 'ジャイアン', 'スネ夫');
// ドラえもん のび太くん しずかちゃん ジャイアン スネ夫と表示される

test('ドラえもん', 'のび太くん');
// ドラえもん のび太くんと表示される

test();
// 何も表示されない

定義している引数の数に見合わない呼び出しをしても問題ないということは知っていましたが、このオブジェクトの存在は知りませんでした。 でもそんな使わなそうな気がします。 引数ちゃんと合わせろよって話ですし。。。

変数の巻き上げ

関数内のどの位置にでもvar文を使用して変数を宣言できるが、関数内のどの位置に変数の宣言をしても、 その関数の先頭で宣言された と見なされる。

以下は本から引用させていただいたコードです。

var a = 'hoge';
var f = function() {
    console.log(a); // undefined
    var a = 'fuga';
    console.log(a); // fuga
}

実際にはf ファンクション内の、2行目で a変数に fugaという文字を入れたが、結果的にはファンクション内の1行目(先頭)で a変数を定義したことになってしまうということです。

しかも、宣言だけで、初期化は行われません。

なので、 undefined になっているということになります。

つまり fファンクション内は以下みたいなります。

var f = function() {
    var a;
    console.log(a);
    a = 'fuga';
    console.log(a);
}

これはまじで知りませんでした。 まぁ引数で渡しちゃったり、基本的に宣言・初期化は先にしちゃうので気づいてなかったというのもありますが。。 勉強になりました。

即時関数

無名関数を定義し、そのまま () をつけて実行することが出来る。無名関数は、function定義から全体を()で囲む必要がある。

自分が慣れていないだけなのですが、使ったことがありませんでした。

結構使う技術なんでしょうか??

(function(test) {
  console.log(test);
})('パリピ');
// パリピ

apply, call, bind

関数内で参照するthisを束縛するためのメソッド。 thisは呼び出される場面によって自身の参照先が変化するが、これらのメソッドを使うと常に指定した通りのthisで動作させることが出来る。

なお、bindに関しては、関数に渡す引数も束縛することが出来る。

これらは、jsのthisの勉強をしていたときに、なんとなく理解したのですが、実際にきちんと理解するために、今回もう一度勉強しようと思いました。

apply

applyの特徴は、引数をまとめて配列で渡すことのようです。

function profile(age) {
    console.log(this.name + "です。" + age + "才です。");
}

var user1 = { name: "ドラえもん" };
var user2 = { name: "のび太" };

profile.apply(user1, [20]); // ドラえもんです。20才です。
profile.apply(user2, [10]); // のび太です。10才です。

call

callの特徴は、引数をそのままで渡すことが出来るようです。

function profile(age) {
    console.log(this.name + "です。" + age + "才です。");
}

var user1 = { name: "ドラえもん" };
var user2 = { name: "のび太" };

profile.call(user1, 20); // ドラえもんです。20才です。
profile.call(user2, 10); // のび太です。10才です。

bind

bindはほか2つと少し違っていて、引数も同時に束縛できることが出来ます。

userProfile3のように、引数を束縛しないことももちろん可能です。

function profile(age) {
    console.log(this.name + "です。" + age + "才です。");
}

var userProfile1 = profile.bind({ name: "ドラえもん"}, 20);
var userProfile2 = profile.bind({ name: "のび太"}, 10);
var userProfile3 = profile.bind({ name: "ジャイアン"});

userProfile1();   // ドラえもんです。20才です。
userProfile2();   // のび太です。10才です。
userProfile3(15); // ジャイアンです。15才です。

一度まとめるとスッキリわかりました。勉強になりました。

Map

ES2015からサポートされた map は従来のオブジェクトで書くよりいろいろメリットがあるとのことでした。特に以下です。

  1. キーを任意の型で指定できる
  2. 専用のメソッドが用意されている

専用のメソッドに関しては、名前でだいたい想像できますが、一応書いてみます。

メソッド名 詳細
set(key, val) mapにデータをセットする
delete(key) 指定のkeyのデータをmapから削除する
size mapの要素数を返す(こちらはメソッドではない)
has(key) 指定のkeyのデータがmap内にあるかどうかを確認する
get(key) 指定のkeyのデータをmapから取得する
keys() map内に存在するすべてのkeyを返す
values() map内に存在するすべてのvalueを返す
entries() mapの全てのkey, valueのペアを返す

それぞれ、サンプル書いてみました。

var testMap = new Map([
    ['name', 'ドラえもん'],
    ['age', 20],
    [12345, 'ppppp']
]);

console.log(testMap.set('isError', true));
// => Map(4) {"name" => "ドラえもん", "age" => 20, 12345 => "ppppp", "isError" => true}

console.log(testMap.delete('isError'));
// => true

console.log(testMap.size);
// => 3

console.log(testMap.has(12345));
// => true

console.log(testMap.get(12345));
// => ppppp

console.log(testMap.keys());
// => MapIterator {"name", "age", 12345}

console.log(testMap.values());
// => MapIterator {"ドラえもん", 20, "ppppp"}

console.log(testMap.entries());
// => MapIterator {"name" => "ドラえもん", "age" => 20, 12345 => "ppppp"}

ES2015に関しては、また別途勉強するつもりなので、簡単に書きましたが、こういうのもあるのですね。勉強になりました。

クラス

こちらもES2015でサポートされたもののようです。

class Animal
{
    constructor(name)
    {
        this.name = name;
    }

    getName()
    {
        return this.name;
    }
}

var animal = new Animal('ねこ');
console.log(animal.getName());
// => ねこ



class Cats extends Animal
{
    constructor(name, nickname)
    {
        super(name);
        this.nickname = nickname;
    }
    
    getNickName()
    {
        return this.nickname;
    }
    
    // オーバーライド
    getName()
    {
        return super.getName() + "(名前: " + this. getNickName() + ")";
    }
}

var cats = new Cats('ねこ', 'こじろう');
console.log(cats.getName());
// => ねこ(名前: こじろう)

classはphpで触り慣れているので、比較的すんなり入れました。

アクセス修飾子がないというところが少し気になりますが、無理やり作ることは出来るみたいなので、クラスは積極的に使っていきたいと思います。

勉強になりました!!

Promise

これもES2015でサポートされた機能のようです。

以下のようなコールバック地獄を回避するための デザインパターン ということです。

request1(function(response1) {
    request2(function(response2) {
        request3(function(response3) {
            request4(function(response4) {
                request5(function(response5) {
                    // まだまだ続く可能性あり・・・
                });
            });
        });
    });
});

↑のようなコードをPromiseを使って書くと以下のようにきれいに書けるようです。

request1()
    .then(function(response1) {
        return request2();
    }).then(function(response2) {
        return request3();
    }).then(function(response3) {
        return request4();
    }).then(function(response4) {
        return request5();
    }).then(function(response5) {
        // 処理はつづく・・・
    });

シンプルでわかりやすいです!勉強になりました。

Promiseはもう少し色々できそうなので、別でもう少し勉強してみようと思います。

ES2015

ES6とも呼ばれる事があるようなのですが、次バージョンのES2016はES7とは言わないようなので、ES2015で覚えておこうと思います。

classやPromise以外にも色々とわかっておいたほうが良い機能があり、こちらも勉強しようと思います。

ES2015に関してはコチラの記事がとてもわかりやすくまとめて頂いているので、コチラを見ながら特に使いそうだなと感じたものを幾つか記載していきます。

let, const

let: 再宣言が出来ない

const: 再宣言・再代入が出来ない

アロー関数式

無名関数に対して、functionという記述を省略できるようです。

let sum_func = (a, b) => {
    return a + b;
};

console.log(sum_func(1, 2));
// => 3

分割代入

一度に複数の変数に、それぞれの値を代入できるようです。

var [name, age] = ['ドラえもん', 20];
console.log(name);
// => ドラえもん

console.log(age);
// => 20

デフォルト引数

これもPHPなど他の言語でも使われているので、分かりやすかったです。

function test(a = 1)
{
    console.log(a);
}

test();
// => 1

test(2);
// => 2

テンプレート文字列

PHPのヒアドキュメント的な感じでかけるようです。

var name = 'ドラえもん';

var message = `こんにちは!
ぼく${name}です。`

console.log(message);
// => こんにちは!
// ぼくドラえもんです。

終わり

今週一発目の記事は今週に入って1時間後にpostしました。

いろいろと勉強できて良かったです。

これだけ学べることがあったことで、自分が今まで理解できていなかったということがよくわかりました。

JSは流行り廃りが早いとかいいますが、そもそもそれを気にするレベルに達してないので、とりあえず貪欲に勉強し続けていこうと思います。

多分次の記事もJS関連だと思います。

ではでは。

1/8 〜 1/14の振り返り

ブログ記事(達成!)

ダイエット(達成!)

スクワット、腕立て、腹筋各20回を2セット継続中。

体重変化なし。

でも続けられていることに感激。

反省点

仕事の区切りが悪かったので深夜まで作業して、その日の勉強時間を捻出することができなかった。

毎日コンスタントに勉強することが大事なので、キチンと切り上げるようにする。

評価

日曜日がまだあるのですが、日曜は私用が多そうでまとめ記事を書くことが出来なそうだなと思い、今日書くことにしました。

ブログに関しては思いがけず3記事書けました。

特にLaravel-Breadcrumbが便利だった に関しては当初予定になかったんですが、便利だったのでサラーっとまとめて記事にできました。少しだけ記事を書くのに慣れたのかもしれません。

ダイエットについてもとりあえず筋トレを継続中です。

とりあえず1ヶ月続けて、2月からは3セットにする予定です。

2週間続けて意識の変化ですが、ダイエットの方に関しては少しありました。

昨日実は3時くらいまで仕事で起きていて、眠いから寝ようと思ってたのですが、筋トレをやってないことに気づき一気に筋トレをやりました。

やらないことがなんだか気持ち悪く感じたからです。

習慣化が少しだけ身についてきたのかもしれません。

何事も三日坊主だった自分が、 コチラの記事に触発されて、まだ2週間ですが途切れず続けられているのは、自分でも驚きです。

kakakakakku.hatenablog.com

1ヶ月続いたら自分へのご褒美に、ケーキでも買おうかな。

来週も頑張ります!

Node.js超入門を読んだ

自分は現在インフラよりのサーバサイドというポジションで今まで働いていたのですが、仕事でnodejsを触る機会がありませんでした。

個人的にインストールして、expressでなにかしら動かして、「なるほどこういうもんなのか」と納得して終わった記憶があります。

jsやcssのminifyをするためgulpを使いたいなーとおもい、インストールしたりしましたが、ググってとりあえず使ったりしているだけでしたので、この勉強+アウトプット年にこの際きちんと勉強しようと思い、この本を購入しました。

ちなみにこの本は買ってからずっと放置していた積み本でした。

大雑把な感想

流石に超入門とついているだけあり、全体的にかなり初心者よりな本でした。

言葉も噛み砕いて書かれていて、初心者にはとても良い内容だったと思います。

流れ的には、nodejsでサーバを立ててみようというノリだったので、自分が知りたい部分とはマッチしていなかったのですが、ただ、そのなかでも自分の無知で知らない部分があり、勉強になったところも多々有りました。

聞くは一時の恥、聞かぬは一生の恥

初心者レベルの本でも学べる部分があるという、自分の無知さへの落胆と、知れてよかったという安堵感がせめぎ合っております。

まぁそんな感じで、今回も勉強になった箇所を、書き残しておこうと思います。

勉強になったところ

偶数バージョン・奇数バージョン

知らなかったのですがググるとかなり出てきた情報だったので、常識なことなのですね。。

偶数バージョンはLTS

奇数バージョンは半年程度のサポートのみ。奇数バージョンで、新しい技術を積極的に取り組んでいって、偶数バージョンで、確実に動くものとして提供する。

という運用のようです。

勉強になりました。

npm install -g

グローバルにinstallするのは -g オプションをつけてinstall

ローカルにinstallするのは何もつけずにinstall

ここも結構どっちがどっちとかあまり気にせずやっていたな。。。 気をつけます。

package.json

npmで使用するパッケージ情報が記述されているもの。

これもちゃんと理解していなかったので、確認できてよかった。

npm init した際に作られるpackage.jsonが以下。

他にも様々な項目がある用で、コチラで詳しく書かれていたので、参考にさせてもらいながら自分でもまとめてみる。

{
  "name": "express-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.16.2"
  }
}
項目 詳細
name パッケージの名前
version パッケージのバージョン
description パッケージの説明文
main メインプログラム。モジュール内で最初に呼ばれるスクリプトファイルという感じ?
scripts 自分で指定したShell Scriptを実行できるエイリアスコマンドを定義できる。サンプルだと npm start というコマンドが打てて、 node index.js を実行してくれるようになる。
author 作者名
license ライセンス
dependencies このパッケージが依存するモジュールとバージョン

npm install パッケージ名 --saveオプション

--save オプションを指定することで、 package.jsondependencies にインストールしたパッケージが追記される。

他の人がこのpackage.jsonを使ってnpm installすると、dependenciesに記載されているパッケージ全てがインストールされるようになる。

これも普通に使いそう。勉強になりました。

npm install --save jquery

jqueryのnpm install出来るとのこと。全然知らなかったです。。

ラスト

とまあこんな感じで、最初にもいいましたが、初心者向けの本でも勉強できることは多かったです。 初心者というよりも超初心者向けという感じでしたがw

最後の章でJSの書き方についても丁寧に説明されているので、本当に真っ白の状態から、勉強するには良いかと思いました。

今年の目標でフロントエンドの知識をつけたいというのがあるので、今度もフロントエンド系の知識が身につく本を買って勉強しようと思います。

Node.js超入門

Node.js超入門

Laravel-Breadcrumbが便利だった

今とあるプロジェクトで現行サイトをLaravelに載せ替える作業をしているのですが、そのさい、べた書きで実装されていたパン屑をどうやって実装しようかとPackagistを漁っていたところ、laravel-breadcrumbsという超便利ライブラリがあったので、早速使ってみました。

作業環境

  • Laravel: 5.5
  • PHP: 7.1.5
  • laravel-breadcrumbs: 4.2.0

Laravelインストール

以下でLaravelプロジェクトを作成します。

$ composer create-project --prefer-dist laravel/laravel breadcrumbs_test

laravel-breadcrumbsインストール

以下でlaravel-breadcrumbsをインストールします。

$ cd breadcrumbs_test
$ composer require davejamesmiller/laravel-breadcrumbs

config/breadcrumbs.phpを作成

以下でbreadcrumbsの設定ファイルを作成します。

$ php artisan vendor:publish --provider='DaveJamesMiller\Breadcrumbs\BreadcrumbsServiceProvider'

routes/breadcrumbs.phpを作成

上で作ったconfig/breadcrumbs.phpを見ると分かるのですが、パン屑設定を記述するファイルはroutes/breadcrumbs.php というファイルになります。

なので、routes/ にファイルを作成します。

$ touch routes/breadcrumbs.php

パン屑の設定を書いていく

作成したroutes/breadcrumbs.phpにパン屑の設定を書いていきます。

せっかくなので、公式に書いてあったものの似たような感じで作ってみます。

<?php

// Home
Breadcrumbs::register('home', function ($breadcrumbs) {
    $breadcrumbs->push('Home', route('home'));
});

// Home > About
Breadcrumbs::register('about', function ($breadcrumbs) {
    $breadcrumbs->parent('home');
    $breadcrumbs->push('About', route('about'));
});

// Home > Blog
Breadcrumbs::register('blog', function ($breadcrumbs) {
    $breadcrumbs->parent('home');
    $breadcrumbs->push('Blog', route('blog'));
});

// Home > Blog > [Category]
Breadcrumbs::register('category', function ($breadcrumbs, $category) {
    $breadcrumbs->parent('blog');
    $breadcrumbs->push($category->title, route('category', $category->name));
});

// Home > Blog > [Category] > [Post]
Breadcrumbs::register('post', function ($breadcrumbs, $post) {
    $breadcrumbs->parent('category', $post->category);
    $breadcrumbs->push($post->title, route('post', [$post->category->name, $post->id]));
});

パン屑に対応するrouteを書いていく

せっかくパン屑の設定を書いても、laravelのプロジェクトを作ったばかりの場合は、対応するrouteが存在しません。

なので、ルーティングファイルを編集します。

今回はパン屑設定に対応するルーティングを設定しました。

<?php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('home');
})->name('home');

Route::get('/about', function () {
    return view('about');
})->name('about');

Route::get('/blog', function () {
    return view('blog');
})->name('blog');

Route::get('/blog/{category_name}', function ($category_name) {
    $category        = new StdClass;
    $category->title = 'カテゴリ1';
    $category->name  = $category_name;
    return view('category', ['category' => $category]);
})->where('category_name', '[A-Za-z]+')->name('category');

Route::get('/blog/{category_name}/{id}', function ($category_name, $id) {
    $category        = new StdClass;
    $category->id    = 1;
    $category->title = 'カテゴリ1';
    $category->name  = $category_name;

    $post            = new StdClass;
    $post->id        = $id;
    $post->title     = "ポスト{$id}";
    $post->category  = $category;
    return view('post', ['post' => $post]);
})->where('category_name', '[A-Za-z]+')->where('id', '[0-9]+')->name('post');

カテゴリやポストは本来はDBから取得するものですが、今回はテストなのでべた書きしています。

viewファイル作成

ルーティングに対応するbladeファイルを作成してください。

$ touch resources/views/home.blade.php
$ touch resources/views/about.blade.php
$ touch resources/views/blog.blade.php
$ touch resources/views/category.blade.php
$ touch resources/views/post.blade.php

各ファイルは以下みたいな感じで書いておきます。

h1やtitle部分は脳内補完してください。

<!DOCTYPE html>
<html>
<head>
    <title>home</title>
</head>
<body>
    <h1>Home</h1>
</body>
</html>

テンプレートにパン屑を表示する

早速表示してみます。

例えばaboutページであれば、h1の下に以下を記述してください。

{{ Breadcrumbs::render('about') }}

早速確認してみます。

f:id:kojirooooocks:20180111004816p:plain

パン屑表示されてますね!!

引数も渡せます。categoryページの場合は、以下のように記述します。

{{ Breadcrumbs::render('category', $category) }}

f:id:kojirooooocks:20180111004821p:plain

表示されてます!

テンプレートの切り替え

スタイルを効かせたい場合など当然あると思います。

その場合は、設定ファイルでパン屑が表示されるテンプレートを変更することが出来ます。

config/breadcrumbs.php の以下の項目を変更します。

'view' => 'breadcrumbs::bootstrap4',
    ↓
'view' => 'elements/breadcrumbs'

上のように変更すると、laravel-breadcrumbsは resources/views/elements/breadcrumbs.blade.phpを見るようになります。

新たにファイルを作り、以下のように記述します。

@if (count($breadcrumbs))
    <ul class="breadcrumb">
        @foreach ($breadcrumbs as $breadcrumb)
            @if ($breadcrumb->url && !$loop->last)
                <li class="breadcrumb-item"><a href="{{ $breadcrumb->url }}">{{ $breadcrumb->title }}</a></li>
            @else
                <li class="breadcrumb-item active">{{ $breadcrumb->title }}</li>
            @endif
        @endforeach
    </ul>
@endif

f:id:kojirooooocks:20180111004827p:plain

ulに変更したとことで、ナンバリングがなくなっています。

新しいテンプレートが使われていることがわかると思います。

JSON-LDでのパンくずリスト対応

ここまでやったのでschema.orgパンくずリストも一緒に実装してみます。

上で作った、新たなテンプレート(elements/breadcrumbs.blade.php)に記述する感じで実装します。

@if (count($breadcrumbs))
    <ul class="breadcrumb">
        @foreach ($breadcrumbs as $breadcrumb)
            @if ($breadcrumb->url && !$loop->last)
                <li class="breadcrumb-item"><a href="{{ $breadcrumb->url }}">{{ $breadcrumb->title }}</a></li>
            @else
                <li class="breadcrumb-item active">{{ $breadcrumb->title }}</li>
            @endif
        @endforeach
    </ul>
    <script type="application/ld+json">
    {
      "@context": "http://schema.org",
      "@type": "BreadcrumbList",
      "itemListElement":
      [
        @foreach ($breadcrumbs as $k => $breadcrumb)
        {
          "@type": "ListItem",
          "position": {{ $k + 1 }},
          "item":
          {
            "@id": "{{ $breadcrumb->url }}",
            "name": "{{ $breadcrumb->title }}"
          }
        }
        @if (!$loop->last)
        ,
        @endif
        @endforeach
      ]
    }
    </script>
@endif

f:id:kojirooooocks:20180111004830p:plain

問題なく表示されてますね。

感想

laravelはいろんなライブラリがあって面白いですね。

こらからどんどん移植をしていくうちに、他にもいいライブラリをみつけたら、また紹介したいと思います。