Preactをはじめる


はじめる

この記事は preact の動作するプロジェクトの初期状態を組み立てるところまでです。preactならびに React に関するプログラミングの知見は一つも含まれません。ご注意下さい。

preactはサイズ軽量な React.js 「ぽい」ライブラリです。公式でも「Reactの再実装ではない」とうたわれていますが、まず同等の書き味が楽しめます。(JSXによるものが大きい気もする)

プロジェクトを作成する

mkdir preact-entry
cd preact-entry
npm init -y

関連ライブラリのインストール

webpackのインストール

npm install --save-dev webpack webpack-cli webpack-dev-server

babel のインストール

オブジェクトスプレッド代入とかクラスプロパティとか欲しい気がするので preset-state-2 を入れています。babel-preset-preactは更新1年前ですがまあいいでしょう。(やってることこれだけだし)

npm install --save-dev babel-core babel-loader babel-preset-env
npm install --save-dev babel-preset-stage-2
npm install --save-dev babel-preset-preact

preact のインストール

npm install --save-dev preact

eslint のインストール

JSX周りのルールを使いたいので eslint-plugin-react を入れます。

npm install --save-dev eslint eslint-config-eslint eslint-plugin-react

設定ファイルの作成

webpack.config.js

エントリポイントは ./src/index.js、出力先は dist/、開発用サーバのベースディレクトリは public/ とします。

module.exports = {
  entry: [
    './src/index.js'
  ],
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: ['babel-loader']
      }
    ]
  },
  resolve: {
    extensions: ['*', '.js', '.jsx']
  },
  output: {
    path: __dirname + '/dist',
    publicPath: '/',
    filename: 'bundle.js'
  },
  devServer: {
    contentBase: './public'
  }
};

.babelrc

{
  "presets": [
    "env",
    "preact",
    "stage-2"
  ]
}

.eslintrc.js

ベースとして eslint:recommended を利用し、カスタマイズする方針でいきます。

react/jsx-uses-reactreact/jsx-uses-vars あたりをまず追加します。no-console はデバッグ時にほしいので残す。no-empty-pattern は props とか state とりあえず使わないけど消さないパターンが多いので残す。・・・などなど。とりあえずこのくらいあれば違和感はないかと。

module.exports = {
  extends: "eslint:recommended",
  env: {
    browser: true,
    commonjs: true,
    es6: true
  },
  parser: "babel-eslint",
  parserOptions: {
    sourceType: "module",
    ecmaFeatures: {
      jsx: true
    }
  },
  rules: {
    "no-console": "off",
    "no-empty-pattern": "off",
    "linebreak-style": ["error", "unix"],
    "react/jsx-no-bind": ["error", { "ignoreRefs": true }],
    "react/jsx-no-duplicate-props": "error",
    "react/self-closing-comp": "error",
    "react/prefer-es6-class": "error",
    "react/no-string-refs": "error",
    "react/require-render-return": "error",
    "react/jsx-uses-react": "error",
    "react/jsx-uses-vars": "error",
  },
  plugins: [
    "react"
  ],
  settings: {
    react: {
      pragma: "h"
    }
  }
}

.eslintignore

VSCodeなどで webpack.config.js を開いた時にいちいち指摘がされて嫌なので .eslintignore にチェック対象外となるファイルについて書いておきます。

webpack.config.js
dist/*

プログラミング

public/index.html

以下のような index.html を作って public/ 以下に置きます。

<html>
<head>
  <title>Preact Entry</title>
  <script src="/bundle.js" ></script>
</head>
<body>
  <div id="mount"></div>
</body>
</html>

src/index.js

以下のようにしました。

import { h, render } from "preact";

/**
 *
 * @param {props} props
 * @param {state} state
 */
const Hello = ({ }, { }) => <div>Hello Preact</div>;

document.addEventListener("DOMContentLoaded", () => {
    render(
        <Hello />,
        document.getElementById("mount")
    );
});

package.json

実行スクリプトを用意します

  "scripts": {
    "eslint": "eslint src/",
    "start": "webpack-dev-server --config ./webpack.config.js --mode development"
  },

実行します

npm run start

動いた。よしよし。

まとめ

この段階で build した結果がだいたいディスク上で10kbを切るくらいです。Mac標準の gzip で圧縮すると 3.8KB。

$ ls -lh dist/
total 24
-rw-r--r--  1 ma2saka  staff   9.5K  4 25 14:33 bundle.js
-rw-r--r--  1 ma2saka  staff   3.8K  4 25 14:33 bundle.js.gz

「3kb」を標榜するのも納得のサイズ感かな?