ESlintでAirbnbのスタイルガイド使用時のReact Component

概要

  • stateless functional component じゃないとeslintで怒られたりしたので書き方をまとめて置く

error Component should be written as a pure function

  • stateの変更がない場合、コンポーネントは関数で定義しなければいけないらしい

stateless functional component

  • 関数で書く状態変化のないコンポーネント
  • 1
    2
    3
    const Hello = (props) => {
    return (<div>Hello, {props.name}</div>);
    }

eslint, airbnb styleguide で valid な component

  • ESlint で Air bnb の スタイルガイドを使った際、エラーの出ないコンポーネントの書き方

state less functional component

  • 状態を持たず、関数で記述されたコンポーネント
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    import React from 'react';

    const Hello = () => (
    <div>
    Hello
    </div>
    );

    export default Hello;

functional component

  • 関数で記述されたコンポーネント
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    import React from 'react';
    import PropTypes from 'prop-types';

    const Hello = (props) => {
    const { id } = props;
    return (
    <div>
    Hello,
    {id}
    </div>
    );
    };

    Hello.propTypes = {
    id: PropTypes.string.isRequired,
    };

    export default Hello;

class component

  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    import React from 'react';

    export default class Hello extends React.Component {
    constructor(props) {
    super(props);
    this.state = {
    text: '',
    };
    }

    render() {
    return (
    <div>
    <input type="text" onChange={e => this.state({ text: e.targetValue })} />
    </div>
    );
    }
    }

参考

Laravel+React(+Redux)の構成を調査

概要

  • laravel で React + Redux 環境はどう作られてるか調べる
    • 後々以下のようにできるか検討したい
      • React + Rredux + webpack + eslint + perritier + Flow
  • 寄り道して調査したので手っ取り早く構築したい方は参考サイトをみてください

artisanでプロジェクトをReactを使用する構成にする

  • Laradockを使用しているのでartisanコマンドはDockerコンテナ内で使用

    • 1
      2
      3
      $ artisan preset react

      Please run "npm install && npm run dev" to compile your fresh scaffolding.
    • npm installと dev コマンドで新しいスカフォールド(土台、足場みたいな意味)をコンパイルしてと言われる

  • yarnが入っているので yarn コマンド使用

    • 1
      $ yarn && yarn dev
    • 割と時間かかります。yarn は npm より早いですが

  • これでどうなるかというと resources/assets 内のソースコードを laravel-mix というモジュールを使ってコンパイルしてくれるよう

artisanのReactスカフォールドはどのようになっているか

  • yarn dev で何が呼ばれているか package.json を見てみると
  • 1
    2
    "dev": "npm run development",
    "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
  • webpackのconfigファイルを呼んでいるよう

  • ちなみに cross-env は環境変数を設定してjsを実行してくれるパッケージ
    • この場合 NODE_ENV に development を代入して webpack を実行
    • webpack を実行する際のオプションとして –progress (進捗をパーセント表示) –hide-modules(モジュールの情報を隠す) が指定されている
  • 呼ばれた webpack の config ファイル

    • node_modules/laravel-mix/setup/webpack.config.js

      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        /**
        * As our first step, we'll pull in the user's webpack.mix.js
        * file. Based on what the user requests in that file,
        * a generic config object will be constructed for us.
        */
        let mix = require('../src/index');

        let ComponentFactory = require('../src/components/ComponentFactory');

        new ComponentFactory().installAll();

        require(Mix.paths.mix());

        /**
        * Just in case the user needs to hook into this point
        * in the build process, we'll make an announcement.
        */

        Mix.dispatch('init', Mix);

        /**
        * Now that we know which build tasks are required by the
        * user, we can dynamically create a configuration object
        * for Webpack. And that's all there is to it. Simple!
        */

        let WebpackConfig = require('../src/builder/WebpackConfig');

        module.exports = new WebpackConfig().build();
      • laravel-mix というモジュールの webpack.conf が呼ばれている

        • laravel-mix は webpack のラッパーでCSSとJSのプリプロセッサをさぽーとしている
        • 以下の記述をみる感じだとTS,CS,Sass,Less,Stylus等をコンパイルしてくれるモジュールのよう
        • 上のconfigで呼ばれている ComponentFactory.jsを見てみると以下の記述がある
        • 1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          let components = [
          'JavaScript',
          'Preact',
          'React',
          'Coffee',
          'TypeScript',
          'FastSass',
          'Less',
          'Sass',
          'Stylus',
          'PostCss',
          'Css',
          'Browsersync',
          'Combine',
          'Copy',
          'Autoload',
          'Version',
          'Extend',
          'Extract',
          'Notifications',
          'DisableNotifications',
          'PurifyCss'
          ];
        • 上の components を installAll というメソッドでインストールしてるっぽい

        • node_modules/laravel-mixディレクトリ内にnode_modulesディレクトリがある
        • node_modules/laravel-mix内のpackage.jsonをみると上記のモジュールが記述されてる

途中で気づいた

  • laravel-mix はあくまで webpack.config とかを細かく設定しなくても楽にバンドルするためのパッケージで、reduxとかその他いろいろプラグインを使いたい場合は向かない気がする
  • 自分でresourcesディレクトリのソースをpublicディレクトリにコンパイルしていった方が便利にフロント環境を使えそう

他のreact + laravel 環境の例を見てみる

結論

  • LaravelのReactスカフォールドは使わずに自分で作る

todo

  • 実際の開発環境構築

参考

Javascriptを静的型付でかけるFlowの使い方

概要

  • FLOW
  • JavaScriptコードの静的型チェッカー
  • 静的型アノテーションを使用してコードのエラーをチェック
  • babel を使用する方法と flow-remove-types というモジュールを使用する方法がある
  • 今回は babel を使用して webpack でバンドルする感じで使う

Flow単体で使ってみる

インストール、準備

  • 1
    $ yarn add -D babel-cli babel-preset-flow
  • .babelrc ファイルを作成

    • 1
      2
      3
      {
      "presets": ["flow"]
      }
  • package.json の “scripts” に下記追加

    • このコマンドで src ディレクトリ直下のファイルをコンパイルして lib ディレクトリに作成できる
    • -d = 別ディレクトリに作成するオプション
    • 1
      2
      3
      "scripts": {
      "build": "babel src/ -- -d lib/"
      },
  • Flowをインストール

    • 1
      $ yarn add --dev flow-bin
  • VSCodeで書くのでついでに以下のプラグインもインストールしました

    • vscode-flow-ide
    • low Language Support
      • 型指定すると「TSファイルしか型指定できない」みたいなエラーがずっと出てしまうので UserSettings で “javascript.validate.enable”: false にした。ただjavascriptのバリデーションされなくなるので応急処置… eslint とかと一緒に使ってれば問題ないでしょうか…
  • .flowconfig ファイルの作成

    • 1
      $ yarn run flow init
  • .flowconfigに下記を追加

    • 1
      2
      [ignore]
      .*/node_modules/.*

使い方

  • ファイルの先頭に「 // @flow 」を記述してチェックの対象にする
  • 以下だと、返り値に string を指定してるのに、numberが帰ってくる可能性があるのでエラーになる
  • エディタにFlowIDEのプラグイン入れているとこの時点でエラーを教えてくれる

    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      // @flow

      hoge = (x: ?number): string => {
      if (x) {
      return x;
      };
      return "default";
      };

      hoge("q");
  • flow コマンドを打てばflowファイルを全て検証してくれる

    • 1
      flow
  • 上のファイルは以下のように引数の型をstringにして引数に渡す値もstringにすれば解決する

    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      // @flow

      const hoge = (x: ?string): string => {
      if (x) {
      return x;
      };
      return "default";
      };

      hoge("2");

型の種類

  • TypeSystem
    • 細かい型の種類とかは上記を見ながらコード書きながら覚えます
    • genericsとかあるしjavaのTypeSystemに近い感じがしました(javaのTypeSystemそこまで知りませんが)

eslint + prettier + webpack との使用

  • eslint用のプラグインインストール

    • 1
      $ yarn add -D eslint-plugin-flowtype
  • .eslintrcに下記追加

    • 1
      2
      3
      4
      5
      6
      "parser": ["babel-eslint"],
      "plugins": ["prettier"],
      "rules": {
      "flowtype/define-flow-type": 1,
      "flowtype/use-flow-type": 1
      }

reduxと使う場合

  • flowのバージョンに対応するredux用の型を探す

    • 1
      $ yarn run flow-typed search redux
    • こういうのが出てくるのでflow-binのバージョンにあったものを追加

    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      ╔══════════════════════════╤═════════════════╤═════════════════════╗
      ║ Name │ Package Version │ Flow Version ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-form │ v5.x.x │ >=v0.25.x <=v0.52.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-form │ v5.x.x │ >=v0.53.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ react-redux │ v5.x.x │ >=v0.63.0
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ react-redux │ v5.x.x │ >=v0.54.x <=v0.62.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ react-redux │ v5.x.x │ >=v0.53.x <=v0.53.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ react-redux │ v5.x.x │ >=v0.30.x <=v0.52.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux │ v4.x.x │ >=v0.55.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ react-redux │ v4.x.x │ >=v0.30.x <=v0.52.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ react-redux │ v4.x.x │ >=v0.53.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-oidc │ v3.x.x │ >=v0.55.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux │ v3.x.x │ >=v0.28.x <=v0.32.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux │ v3.x.x │ >=v0.33.x <=v0.54.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux │ v3.x.x │ >=v0.55.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux │ v3.x.x │ >=v0.25.x <=v0.27.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-loop │ v2.2.x │ >=v0.33.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-actions │ v2.x.x │ >=v0.34.x <=v0.38.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-devtools-extension │ v2.x.x │ >=v0.47.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-actions │ v2.x.x │ >=v0.39.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-mock-store │ v1.2.x │ >=v0.25.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-rsaa-middleware │ v1.x.x │ >=v0.66.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-act │ v1.x.x │ >=v0.39.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-actions │ v1.x.x │ >=v0.25.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-act │ v1.x.x │ >=v0.34.x <=v0.38.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-saga │ v0.16.x │ >=v0.56.0
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-observable │ v0.14.x │ >=v0.47.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-saga │ v0.13.x │ >=v0.28.x <=v0.37.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-saga │ v0.13.x │ >=v0.38.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-forms-react │ v0.11.x │ >=v0.34.x <=v0.52.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-forms │ v0.11.x │ >=v0.34.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-saga │ v0.11.x │ >=v0.38.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-saga │ v0.11.x │ >=v0.28.x <=v0.37.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-forms-react │ v0.10.x │ >=v0.34.x <=v0.52.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-forms │ v0.10.x │ >=v0.34.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-actions │ v0.9.x │ >=v0.25.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-saga-thunk │ v0.5.x │ >=v0.25.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-exr │ v0.4.x │ >=v0.65.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-entitize │ v0.3.x │ >=v0.45.x ║
      ╟──────────────────────────┼─────────────────┼─────────────────────╢
      ║ redux-entitize │ v0.2.x │ >=v0.45.x ║
      ╚══════════════════════════╧═════════════════╧═════════════════════╝
    • 追加

      • 1
        $ yarn run flow-typed install redux@v4
  • babelにプラグイン追加

    • 1
      $ yarn add -D babel-plugin-transform-flow-strip-types
  • .babelrc

    • 1
      2
      3
      4
      {
      "presets": [["env"],["react"]],
      "plugins": [["transform-flow-strip-types"]]
      }

Flowを使っている時CSSを読み込んでいても解決できないと言われる

  • 拡張子が読み込めてないことが問題らしい(面倒くさい…)
  • .flowconfig に読み込める拡張子を追加する

    • 1
      2
      [options]
      module.file_ext=.styl //stylusを使っていたので
  • jsファイルでcss読み込むときは変数に格納せずにimportすると、「never use ~」みたいなエラーを防げる

    • 1
      import './assets/style.styl';

感想

  • 面倒くさい
  • 絶対Typescriptの方がいい気がする
  • Flowのメリットとしては通常のJSに戻すこともできるということ
  • 個人的にはTS使いたいけど諸々の事情でFlow学習する
    • TSは趣味ででも…

参考

eslint + prettier の使い方

概要

  • 規約に沿って可読性を保ったコーディングがしたい
  • eslint + prettier を併用してwebpackで使いたい

  • 基本的に eslint –fix 実行時に prettier を使う感じ

eslint

  • ESLint
  • avaScript のための静的検証ツール
  • コードを実行する前にバグを見つけたりする
  • C言語の lint が元祖検証ツール

  • 検証ルールを自由に有効・無効

  • カスタムルールを作れる
  • プラグインが多い
  • JSXサポート
  • Babelと連携可能

prettier

eslintを使う

eslintインストール

  • eslint-plugin-react もないとcliで実行時にエラーといわれた
  • 1
    $ yarn add  -D eslint eslint-plugin-react
  • nodeのバージョンが対応外と言われる

    • 1
      2
      3
      4
      eslint@5.0.1: The engine "node" is incompatible with this module. Expected version  "^6.14.0 || ^8.10.0 || >=9.10.0".

      $ node -v
      v9.8.0
  • 「 >=9.10.0 」と書いていたので9.10.0をインストール

    • 1
      2
      3
      $ sudo n 9.10.0
      $ node -v
      v9.10.0
  • 再度 yarn add してインストール完了

設定ファイル作成

  • プロジェクトのローカルの node_modules から eslint を実行

    • 1
      $ ./node_modules/.bin/eslint --init
  • 設問形式か自分でファイルを作成するか聞かれる

    • とりあえず最初なので設問形式で作成する
    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      ? How would you like to configure ESLint? Answer questions about your style
      ? Which version of ECMAScript do you use? ES2016
      ? Are you using ES6 modules? Yes
      ? Where will your code run? Browser
      ? Do you use CommonJS? No
      ? Do you use JSX? Yes
      ? Do you use React? Yes
      ? What style of indentation do you use? Tabs
      ? What quotes do you use for strings? Single
      ? What line endings do you use? Unix
      ? Do you require semicolons? Yes
      ? What format do you want your config file to be in? JSON
    • 質問に上記の回答をしていくと以下の設定ファイルが自動で生成される

      • よく記事で見る設定ファイルの形式がJSONなのでJSONを選択しました。他には yaml と js が選べます。
    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      {
      "env": {
      "browser": true,
      "es6": true
      },
      "extends": "eslint:recommended",
      "parserOptions": {
      "ecmaFeatures": {
      "jsx": true
      },
      "ecmaVersion": 2018,
      "sourceType": "module"
      },
      "plugins": [
      "react"
      ],
      "rules": {
      "indent": [
      "error",
      "tab"
      ],
      "linebreak-style": [
      "error",
      "unix"
      ],
      "quotes": [
      "error",
      "single"
      ],
      "semi": [
      "error",
      "always"
      ]
      }
      }

使い方

  • eslint単体ならCLIで使う

    • 1
      eslint hoge,js
  • webpackでの使い方はwebpackのセクションで説明

試用

  • 下記コードに対してcliから試用
  • 1
    2
    3
    hoge = () => {
    console.log("aaa");
    }
  • 1
    $ ./node_modules/.bin/eslint hoge.js
  • 結果が以下

  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    hoge.js
    1:1 error 'hoge' is not defined no-undef
    2:1 error Expected indentation of 1 tab but found 4 spaces indent
    2:5 error Unexpected console statement no-console
    2:17 error Strings must use singlequote quotes
    3:2 error Missing semicolon semi

    5 problems (5 errors, 0 warnings)
    3 errors, 0 warnings potentially fixable with the `--fix` option.
  • console.log も怒られているが rules に “no-console”: “off” を追加すればok

  • tab でインデントしてたんですがVSCodeの仕様でスペース4つになっていますね…これはVSCode側の設定でなんとかする部分でしょう
  • あとは hoge関数 が使われていないこと、ダブルクオートが使われていること、関数の最後にセミコロンがないことが怒られています
  • –fix コマンドを使用すると整形もしてくれるっぽいです(prettierいらないんでは…?)

Airbnbのスタイルガイド導入

  • air bnb という会社のスタイルガイドを導入します
  • airbnb/javascript
  • eslint-config-airbnb
  • eslint-config-airbnbの導入

  • eslint-config-airbnb@latest の依存関係を調べる

    • 1
      2
      3
      4
      5
      6
      $ npm info "eslint-config-airbnb@latest" peerDependencies

      { eslint: '^4.19.1',
      'eslint-plugin-import': '^2.12.0',
      'eslint-plugin-jsx-a11y': '^6.0.3',
      'eslint-plugin-react': '^7.9.1' }
    • eslint-plugin-import、eslint-plugin-jsx-a11y、eslint-plugin-reactが必要

    • 1
      yarn add -D eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react eslint-config-airbnb
  • configの設定

    • 1
      2
      3
      4
      5
      6
      7
      {
      "env": {
      "browser": true,
      "es6": true
      },
      "extends": ["eslint:recommended","airbnb"]
      }

eslint を使用しないファイルを設定

  • .eslintignore というファイルを作成する
    • node_modulesは書かなくてもデフォルトでignoreになってるかも
    • 1
      2
      3
      dest
      webpack.config.js
      node_modules

prettier

  • Prettier
  • 下記をサポートするコードフォーマッタ
    • JavaScript(ES2017含む)
    • JSX
    • Flow
    • TypeScript
    • CSS, Less, ,SCSS
    • JSON
    • GraphQL
    • Markdown(GFM含む)
    • YAML
  • オリジナルな記述を全て一貫した規約に沿った記述に自動で整形する
  • 一行にまとめられているコードとかを複数行の可読性のある形にできたりする

  • 公式サイト要約

    • 自動で整形できるからコーディング規約導入による面倒がかなり減るよ。多少思った通りの整形にならなくてもメリットの方が大きいよ。

使い方

  • CLIオプション一覧
  • API使用法

  • prerrie単体ならcliで

  • 以下のファイルに対して
  • 1
    2
    3
    hoge = () => {
    console.log("aaa");
    }
  • プロジェクトのnode_modulesから使う

  • 1
    ./node_modules/.bin/prettier --single-quote --trailing-comma es5 --write "./hoge.js"
  • 整形後

  • 1
    2
    3
    hoge = () => {
    console.log('aaa');
    };
  • –debug-check コマンドでコードの正確性が変更される可能性を検出できる。(–writeと併用はできない)

eslintとの併用

  • ESLintとの統合
  • eslint-plugin-prettier が必要
  • 1
    yarn add -D eslint-plugin-prettier eslint-config-prettier

VSCodeで保存時に整形されるようにする

  • VSCodeというエディタを使う場合のみです
  • Prettier - JavaScript formatter のプラグインをインストール
  • command + , で User Settings を開いて、「”eslint.autoFixOnSave”: true,”prettier.eslintIntegration”: true」を追加
  • 保存するたびにeslint-prettierが実行される

git commit 時に整形されるようにする

  • HuskyとLint-stagedを使う方法
  • 1
    yarn add -D lint-staged husky
  • package.jsonに以下追加

    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      "scripts": {
      "precommit": "lint-staged"
      },
      "lint-staged": {
      "*.{js,jsx}": [
      "eslint --fix",
      "git add"
      ]
      },

webpackで eslint + prettier の設定を使用する

  • loaderにeslintを使用していくイメージ
  • eslint-loader を追加
  • 1
    $ yarn add eslint-loader
  • 以下を webpack.config.js に追加

  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    module: {
    rules: [
    {
    enforce: 'pre',
    test: /\.(js|jsx)$/,
    exclude: /node_modules/,
    loader: 'eslint-loader',
    }
    }
  • エディタとかgit commit時の設定してたらいらん気もする

todo

  • css、stylusのlintもする
  • スタイルガイド毎の違いとか調べてみたい

参考

開発用のwebpack.configとpackage.jsonとか(随時更新)

概要

  • 自宅開発用にまとめておきます
  • まだ作成中ですができるだけ最新の状態に保って、開発途中のツールとかでもバンバン入れて行きたいと思います(趣味用なので)
  • todoのセクションに今後追加・作成予定の項目のリストがあります
  • 一応、実行環境も…

    • Mac OS Sierra
    • MacBook Pro (Retina)
  • 更新履歴

    • 2018 6/27 eslint と prettier 導入
    • 2018 6/28 Flow 導入

React(jsx) + Redux で開発する場合

ディレクトリ構成

開発用ファイル

package.json

  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    {
    "name": "redux",
    "version": "1.0.0",
    "main": "index.js",
    "license": "MIT",
    "dependencies": {
    "autoprefixer": "^8.6.3",
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.4",
    "babel-preset-env": "^1.7.0",
    "babel-preset-react": "^6.24.1",
    "create-react-app": "^1.5.2",
    "css-loader": "^0.28.11",
    "eslint": "^4.19.1",
    "eslint-config-airbnb": "17.0.0",
    "eslint-config-prettier": "^2.9.0",
    "eslint-loader": "^2.0.0",
    "eslint-plugin-import": "^2.12.0",
    "eslint-plugin-jsx-a11y": "^6.0.3",
    "eslint-plugin-prettier": "^2.6.1",
    "eslint-plugin-react": "^7.9.1",
    "extract-text-webpack-plugin": "^4.0.0-beta.0",
    "husky": "^0.14.3",
    "lint-staged": "^7.2.0",
    "postcss-loader": "^2.1.5",
    "prettier": "^1.13.6",
    "prettier-eslint": "^8.8.2",
    "react": "^16.4.1",
    "react-dom": "^16.4.1",
    "react-redux": "^5.0.7",
    "redux": "^4.0.0",
    "style-loader": "^0.21.0",
    "stylus": "^0.54.5",
    "stylus-loader": "^3.0.2",
    "webpack": "^4.12.0"
    },
    "devDependencies": {
    "babel-eslint": "^8.2.5",
    "babel-plugin-transform-flow-strip-types": "^6.22.0",
    "eslint-plugin-flowtype": "^2.49.3",
    "flow-bin": "^0.75.0",
    "flow-typed": "^2.4.0"
    }
    }

webpack.config.js

  • extract-text-webpack-pluginを使用しない場合はccsがjsに含まれることになる。
    使用した場合はoutputで指定したディレクトリをルートとして任意のファイル名で書き出される
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    const path = require('path');
    const ExtractTextPlugin = require('extract-text-webpack-plugin');

    module.exports = {
    mode: 'production',
    entry: './routes.js',
    output: {
    path: path.resolve(__dirname, 'dest'),
    filename: 'bundle.js',
    publicPath: '/assets/',
    },
    module: {
    rules: [
    {
    enforce: 'pre',
    test: /\.(js|jsx)$/,
    exclude: /node_modules/,
    loader: 'eslint-loader',
    },
    {
    test: /\.(js|jsx)$/,
    use: [
    {
    loader: 'babel-loader',
    },
    ],
    exclude: /node_modules/,
    },
    {
    test: /\.styl$/,
    use: ExtractTextPlugin.extract({
    fallback: 'style-loader',
    use: 'css-loader!stylus-loader',
    }),
    exclude: /node_modules/,
    },
    ],
    },
    resolve: {
    extensions: ['.js', '.jsx', 'stylus'],
    },
    plugins: [
    new ExtractTextPlugin('style.css'),
    ],
    };

.babelrc

  • この配列の中に配列ネストするみたいな書き方がややこしいので注意
  • 1
    2
    3
    4
    {
    "presets": [["env"],["react"]],
    "plugins": [["transform-flow-strip-types"]]
    }

.eslintrc.json

  • eslint + prettier の設定
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    {
    "env": {
    "browser": true,
    "es6": true
    },
    "extends": ["prettier","eslint:recommended","airbnb","plugin:flowtype/recommended"],
    "parser": "babel-eslint",
    "parserOptions": {
    "ecmaFeatures": {
    "jsx": true
    },
    "ecmaVersion": 2018,
    "sourceType": "module"
    },
    "plugins": [
    "prettier",
    "flowtype"
    ],
    "rules": {
    "linebreak-style": [
    "error",
    "unix"
    ],
    "quotes": [
    "error",
    "single"
    ],
    "semi": [
    "error",
    "always"
    ],
    "no-console": "off",
    "flowtype/define-flow-type": 1,
    "flowtype/use-flow-type": 1
    }
    }

.eslintignore

  • eslint を使用しないファイルを指定
  • node_modulesはいらんかも
  • 1
    2
    3
    dest
    webpack.config.js
    node_modules

.flowconfig

  • 静的型付けチェックにflowを使ってます
    • tsに切り替えます絶対
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    [ignore]
    */node_modules/*
    [include]

    [libs]
    ./interfaces/global.js
    [lints]

    [options]
    module.file_ext=.styl
    [strict]

Vue + vuex で開発する場合

  • todo

現状で対処しているエラー 2018/6/21

todo

  • 画像をcssスプライトするプラグイン入れる
  • css内のurlに関するプラグイン入れる
  • stylus + postcss
  • テストやバリデーション用モジュールの追加
  • vueバージョンの作成
  • FlowとTypescriptとか
  • 脱webpack対策
    • parcelでバンドルする記述も作成
    • gulpでバンドルする記述作成(優先度低)
    • 各モジュール単体での使用方法(優先度低)

URL

LaradockでDocker上にLaravel開発環境を作る

概要

  • 手っ取り早くLaravel開発環境を構築して開発に取り掛かりたい

  • 1.laradock をダウンロード

  • 2.準備
  • 3.docker image,docker container作成
  • 4.コンテナ内でlaravelプロジェクト作成
  • 5..envのアプリのパスを作成したlaravelプロジェクトに設定
  • 6.nginxのrootをlaravelプロジェクトのpublicに変更
  • 7.docker-compose を再起動してlocalhostにアクセス

1.laradock をダウンロード

  • プロジェクト用ディレクトリを作成して git からcloneしてくる

    • 1
      2
      3
      mkdir -p project | cd project

      $ git clone https://github.com/laradock/laradock.git
    • laradockディレクトリが作成される

2.準備

  • 作成したプロジェクトディレクトリ内の env-example を .env にコピー

    • 1
      $ p env-example .env
    • envファイル

      • docker-compose.yml で使用する変数が記述されている
      • envファイルを編集することで自分のプロジェクトにインストールするソフトウェアを指定できる
      • COMPOSE_FILE の値を編集するとき、macなら区切り文字に 「:」windows なら「;」を使用する必要がある

3.docker-compose.yml を実行

  • docker-compose.yml ファイルを実行

    • Getting Started では mysql でしたが heroku へのデプロイを考えて postgres を指定してみます
    • 1
      $ docker-compose up -d nginx postgres php-fpm
    • かなり時間かかります…(各ディレクトリにあるDockerfileからimage,contenaを生成しているため)

4.コンテナ内でlaravelプロジェクト作成

  • workspaceコンテナに入り、シェルを実行する

    • 1
      $ docker-compose exec workspace bash
    • artisan,composer,php unit,gulp 等のコマンドが実行されるらしい

    • laradockはデフォルトで、プロジェクトのいるディレクトリの一階層上のディレクトリをvolumeとしてマウントする
    • 今回の例では「project/」の中にlaradockを作成したので「project/」がマウンティングされている
  • laravelプロジェクトを作成
  • 1
    $ composer create-project laravel/laravel my-app
  • volumeとしてマウンティングされているのでローカルの「project/」にもlaravelプロジェクトが生成される

5. .envのアプリのパスを作成したlaravelプロジェクトに設定

  • docker-composeを使用する一階層上にあるので下記のように指定
  • .envファイル
    • 1
      APP_CODE_PATH_CONTAINER=../my-app:cached

6.nginxのrootをlaravelプロジェクトのpublicに変更

  • project/laradock/nginx/sites 内の default.conf を編集
    • 1
      2
      3
      root /var/www/public;
      から
      root /var/www/my-app/public;

7.docker-compose を再起動してlocalhostにアクセス

  • docker-composer を down させて再度コンテナ起動
  • 1
    2
    $ docker-compose down
    $ docker-compose up -d nginx postgres php-fpm
  • localhostにアクセスしてlaravelプロジェクト初期画面が表示されれば成功

参考

VM上のubuntu18.04でnginxを使いLaravelプロジェクトを動かす

概要

0.準備

0-1.ubuntu18.04へのLravelインストール

0-2.ubuntuの準備

  • リポジトリ一覧を更新 & パッケージを更新
  • 1
    sudo apt update && sudo apt upgrade -y
  • ubuntuに新しいuserを作成 後述のphp-fpmとnginxの設定に使用します

    • nginxという名前のグループとユーザを作成、ログインシェルにbashを指定
      • 1
        sudo useradd -U nginx -s /bin/bash

1.php-fpmの設定

1-1.php-fpmインストール

  • 1
    $ sudo apt install php-fpm
  • 下記コマンドでソケットファイルを確認できる

    • 1
      2
      3
      $ ls /run/php

      php7.2-fpm.pid php7.2-fpm.sock
  • 後述のNginxの設定ファイルにphp7.2-fpm.sockへのパスを設定する

1-2.php-fpmのww.conf編集

  • www-data になっているところを nginx に変更
  • 1
    2
    3
    4
    5
    6
    $ vi sudo /etc/php/7.2/fpm/pool.d/www.conf

    user = nginx
    group = nginx
    listen.owner = nginx
    listen.group = nginx

2.Nginxの設定

2-1.Nginxインストール

  • 1
    $ sudo apt install nginx
  • etc/nginxの所有者をユーザ nginx にする

    • 1
      sudo chown -R  nginx /etc/nginx

2-2.Nginx設定

  • /etc/nginx/conf.d/default.conf
  • 追加するphp7.2-fpm.sockのパスはunix:/run/php/php7.2-fpm.sock

nginx.confの編集

  • /etc/nginx/nginx.confuserの値を nginx に変更
    • 1
      user nginx;

defaultの編集

  • /etc/nginx/sites-enabled/defaultを編集
  • 編集前のdefault

    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      ##
      # You should look at the following URL's in order to grasp a solid understanding
      # of Nginx configuration files in order to fully unleash the power of Nginx.
      # https://www.nginx.com/resources/wiki/start/
      # https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
      # https://wiki.debian.org/Nginx/DirectoryStructure
      #
      # In most cases, administrators will remove this file from sites-enabled/ and
      # leave it as reference inside of sites-available where it will continue to be
      # updated by the nginx packaging team.
      #
      # This file will automatically load configuration files provided by other
      # applications, such as Drupal or Wordpress. These applications will be made
      # available underneath a path with that package name, such as /drupal8.
      #
      # Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
      ##

      # Default server configuration
      #
      server {
      listen 80 default_server;
      listen [::]:80 default_server;

      # SSL configuration
      #
      # listen 443 ssl default_server;
      # listen [::]:443 ssl default_server;
      #
      # Note: You should disable gzip for SSL traffic.
      # See: https://bugs.debian.org/773332
      #
      # Read up on ssl_ciphers to ensure a secure configuration.
      # See: https://bugs.debian.org/765782
      #
      # Self signed certs generated by the ssl-cert package
      # Don't use them in a production server!
      #
      # include snippets/snakeoil.conf;

      root /var/www/html;

      # Add index.php to the list if you are using PHP
      index index.html index.htm index.nginx-debian.html;

      server_name _;

      location / {
      # First attempt to serve request as file, then
      # as directory, then fall back to displaying a 404.
      try_files $uri $uri/ =404;
      }

      # pass PHP scripts to FastCGI server
      #
      #location ~ \.php$ {
      # include snippets/fastcgi-php.conf;
      #
      # # With php-fpm (or other unix sockets):
      # fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
      # # With php-cgi (or other tcp sockets):
      # fastcgi_pass 127.0.0.1:9000;
      #}

      # deny access to .htaccess files, if Apache's document root
      # concurs with nginx's one
      #
      #location ~ /\.ht {
      # deny all;
      #}
      }


      # Virtual Host configuration for example.com
      #
      # You can move that to a different file under sites-available/ and symlink that
      # to sites-enabled/ to enable it.
      #
      #server {
      # listen 80;
      # listen [::]:80;
      #
      # server_name example.com;
      #
      # root /var/www/example.com;
      # index index.html;
      #
      # location / {
      # try_files $uri $uri/ =404;
      # }
      #}
  • 編集後のdefault

    • location ~ \.php$ から始まるブロックを追加している
    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      ##
      # You should look at the following URL's in order to grasp a solid understanding
      # of Nginx configuration files in order to fully unleash the power of Nginx.
      # https://www.nginx.com/resources/wiki/start/
      # https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
      # https://wiki.debian.org/Nginx/DirectoryStructure
      #
      # In most cases, administrators will remove this file from sites-enabled/ and
      # leave it as reference inside of sites-available where it will continue to be
      # updated by the nginx packaging team.
      #
      # This file will automatically load configuration files provided by other
      # applications, such as Drupal or Wordpress. These applications will be made
      # available underneath a path with that package name, such as /drupal8.
      #
      # Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
      ##

      # Default server configuration
      #
      server {
      listen 80 default_server;
      listen [::]:80 default_server;

      # SSL configuration
      #
      # listen 443 ssl default_server;
      # listen [::]:443 ssl default_server;
      #
      # Note: You should disable gzip for SSL traffic.
      # See: https://bugs.debian.org/773332
      #
      # Read up on ssl_ciphers to ensure a secure configuration.
      # See: https://bugs.debian.org/765782
      #
      # Self signed certs generated by the ssl-cert package
      # Don't use them in a production server!
      #
      # include snippets/snakeoil.conf;

      root /var/www/html;

      # Add index.php to the list if you are using PHP
      index index.html index.htm index.nginx-debian.html;

      server_name _;

      location / {
      # First attempt to serve request as file, then
      # as directory, then fall back to displaying a 404.
      try_files $uri $uri/ =404;
      }

      location ~ \.php$ {
      root /usr/share/nginx/html;
      fastcgi_pass unix:/run/php/php7.2-fpm.sock;
      fastcgi_index index.php;
      fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
      include fastcgi_params;
      }

      # pass PHP scripts to FastCGI server
      #
      #location ~ \.php$ {
      # include snippets/fastcgi-php.conf;
      #
      # # With php-fpm (or other unix sockets):
      # fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
      # # With php-cgi (or other tcp sockets):
      # fastcgi_pass 127.0.0.1:9000;
      #}

      # deny access to .htaccess files, if Apache's document root
      # concurs with nginx's one
      #
      #location ~ /\.ht {
      # deny all;
      #}
      }


      # Virtual Host configuration for example.com
      #
      # You can move that to a different file under sites-available/ and symlink that
      # to sites-enabled/ to enable it.
      #
      #server {
      # listen 80;
      # listen [::]:80;
      #
      # server_name example.com;
      #
      # root /var/www/example.com;
      # index index.html;
      #
      # location / {
      # try_files $uri $uri/ =404;
      # }
      #}

2-3.Nginx起動

  • nginxを起動

    • 1
      $ sudo service nginx start
  • サーバIP(今回は192.168.33.11/info.php)にアクセス

    • Nginx初期画面が表示されるか確認

試しにファイルを作成

3-1.LaravelプロジェクトをNginxのルートに設定

  • Laravelのインストール
  • 2-2 で編集した/etc/nginx/sites-enabled/defaultのrootをLaravelプロジェクトのルートに変更、location /に「index index.php index.html index.htm;」を追加
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    root /home/vagrant/laravel_project/public;

    # Add index.php to the list if you are using PHP
    index index.html index.htm index.nginx-debian.html;

    server_name _;

    location / {
    # First attempt to serve request as file, then
    # as directory, then fall back to displaying a 404.
    index index.php index.html index.htm;
    try_files $uri $uri/ =404;
    }
    location ~ \.php$ {
    root /home/vagrant/laravel_project/public;
    fastcgi_pass unix:/run/php/php7.2-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
    include fastcgi_params;
    }
  • サーバIP(http://192.168.33.11/)へアクセス

    • エラーになる
    • 1
      2
             UnexpectedValueException
      The stream or file "/home/vagrant/laravel_project/storage/logs/laravel.log" could not be opened: failed to open stream: Permission denied
  • ユーザ nginx がLaravelプロジェクトに対して権限を持っていないのが原因っぽい

  • /home/vagrant/laravel_projectの所有者もユーザ nginx にしてみる

    • 1
      sudo chown -R  nginx /home/vagrant/laravel_project
  • 一応サーバを再起動して実行

  • 1
    sudo service php7.2-fpm restart && sudo service nginx restart
  • Laravelのデフォルトページが表示されたら成功です。

感想

参考

Nginx各ファイルと構成

概要

  • 各ファイル、ディレクトリと全体の構成について調べました

各ファイルの役割

  • Nginxファイル構成

    • 1
      conf.d  fastcgi_params  koi-utf  koi-win  mime.types  modules  nginx.conf  scgi_params  uwsgi_params  win-utf
  • conf.d

    • nginx.confがこのディレクトリ内の.confを読み取る
  • nginx.conf
    • nginxの初期設定
  • fastcgi_params
    • FastCGI サーバに渡されるべきパラメータ
  • koi-utf, koi-win, win-utf
    • ロシア語文字のエンコーディングの設定ファイルらしい。ほぼ不要とのこと
  • mime.types
    • MIMEタイプと拡張子の関連付けを定義
  • scgi_params
    • SCGI用の変数を定義
  • uwsgi_params
    • uWSGI用の変数を定義
  • modules
    • nginx1.9.11から動的モジュール機能がリリースされた。
    • GeoIP、Mail、Image-Filter、Stream 、XSLTなど webサーバの機能に何かに特化した機能(モジュール)を追加するときに利用
    • 初期構成は空ディレクトリ

参考

php-fpmの設定ファイル(php-fpm.conf)等について

概要

  • 設定方法など詳細に分かればと思い調べました
  • ubuntu18.04、php7.2 、Nginxで使用

ubuntuにインストール

  • 1
    apt install php-fpm

設定ファイルの各パラメータ

Nginxでの使用方法

PHP実行環境

概要

  • php開発環境の概要をさらう

実行環境

ローカル実行環境

  • phpをローカルで実行できる環境をひとまとめにしたパッケージ

サーバ環境

  • LAMP環境
    • Linux・Apache・MySQL・PHP(or Python or Perl)
  • Nginx + PHP-FPM
    • FPM = FastCGI Process Manager
    • PHPのFastCGI 実装のひとつ
      • CGI
        • Common Gateway Interface、ウェブサーバ上でユーザプログラムを動作させるための仕組み
      • FastCGI
        • CGIの問題を解決するために Open Market社によって1990年代中頃に開発されたもの
    • 高負荷のサイトで有用な追加機能を用意

FastCGIとは

  • CGI は、ユーザーから要求がある度に、プロセスの生成と破棄を行う
  • 大量の要求があると、生成と破棄の実施によりパフォーマンスが悪化
  • FastCGI は、初回リクエスト時に起動したプロセスをメモリ上へ保持、次回流クエストからはメモリ場のプロセスを実行する
    • 動作速度、サーバ負荷を軽減

CGI版とモジュール版

  • PHP には、モジュール版とCGI版の二種類がある

モジュール版

  • webサーバのプロセスの中でphpを実行
  • Apacheがモジュール版の環境を提供する
  • サーバを動かすユーザでPHPmp動作
    • 複数ユーザの場合、セキュリティ面に問題
  • セーフモードという、ユーザ間ファイル干渉を防ぐ仕組みがある
  • 動作速度はCGI版に比べ速い

CGI版

  • 実行ファイル形式と呼ばれる
  • Webサーバーとは別のプロセスで実行
    • webサーバを動かすユーザと異なるユーザが動かす
  • 他ユーザに干渉することがない
  • 実行するたびにサーバで別プロセスを動かしメモリを使うのでモジュール版にくらべ処理速度は遅くなる
  • レンタルサーバではユーザ毎に負荷を計測しやすいのでCGI版がよく使われる
CGI形式にも二通りある
  • 参考 あなたのサイトの PHPは,CGI方式ですか? Module方式ですか?
  • php-cgiという外部プログラムを通じてphpコードを実行する場合
    • apacheがphpコードを環境変数、引数つきでphp-cgiに投げてその結果をクライアントへ返す
  • phpコード自体を実行形式とする場合
    • 「#!/usr/local/bin/php & chmod +x」のような形でapacheがPHPコードを外部で実行してhttpクライアントに返す

todo

  • webサーバの仕組みについて低いレイヤで理解する
  • php実行の仕組みについても上に同じ

参考