preact+redux-zeroでアプリ構築してみる

小さめのWebアプリを用意する必要があったのでサイズの小ささを売りにしているreactライクなアプリをかけるpreactを使って実装をしてみた。
最初はpreactだけでいこうかと思ったけど、バケツリレーはやっぱり面倒なので軽量版reduxのredux-zeroとセットで使ってみた。
Counterのサンプルで自分好みの環境を用意する。

サンプルはこちら

環境

NodeJS: 10.15.x
npm: 6.9

利用ライブラリ

  • babel
  • webpack
  • eslint (base airbnb)
  • stylelint
  • preact
  • redux-zero
  • CSS Modules(use CSS-loader)

webpack4の設定

webpack4を利用。今まで使っていたのはwebpack2だったので微妙に設定が変わってる。

modeを設定する必要があるようなのでprocess.env.NODE_ENVみてdevelopmentとproductionを切り替える

const isDebug = process.env.NODE_ENV !== 'production';
module.exports = {
  mode: isDebug ? 'development' : 'production',

自前コードと3rd partyのライブラリはファイルを分けたいのでsplitChunksを利用する。
node_modulesのものをvendorとして分離させる。


optimization: {
  splitChunks: {
    cacheGroups: {
      vendor: {
        test: /node_modules/,
        name: 'vendor',
        chunks: 'initial',
        enforce: true,
      },
    },
  },
},

moduleの設定

babel-loader, style-loader, postcss-loaderを適用。
babel7からはbabel-preset-envが@babel/preset-envに代わっていた。
polyfill周りの設定が楽になっている模様。
今回はchromeしか使わないのでpolyfillは設定せず。

eslint

reactでよく使うeslint-config-airbnbを持ってくる。
preactの場合、ルールが一部違うのでpreactに影響がありそうなところは無効化する。


  rules: {
    'no-console': 0,
    'react/prop-types': 0,
    'react/react-in-jsx-scope': 0,
    'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }],
  },

functional component

reactの時と同様の記述が可能


import { h } from 'preact'; // eslint-disable-line no-unused-vars
import Styles from './Counter.css';

const Counter = (props) => {
  const { count, onClickDecrement, onClickIncrement } = props;
  return (
    <div className={Styles.box}>
      <h1>{count}
      <div>
        <button type="button" onclick="{onClickDecrement}">
          decrement
        </button>
        <button type="button" onclick="{onClickIncrement}">
          increment
        </button>
      </div>
    </div>
  );
};

export default Counter;

CSSの読み込み

Style-Loaderを使っているのでCSS moduleとして読み込み可能。
scoped cssが問題なく使える。

container

reduz-zeroのConnectとmapToPropsを使う。
引数でstateとactionsが取れるようになる。
Connectの中がごちゃごちゃしないようにかけばreactと同じ感覚で書ける。


import { h } from 'preact'; // eslint-disable-line no-unused-vars
import { Connect } from 'redux-zero/preact';

import Counter from '../components/Counter';
import actions from '../actions';

const mapToProps = ({ count }) => ({ count });

const Container = () => (
  <connect maptoprops="{mapToProps}" actions="{actions}">
    {({ count, increment, decrement }) => (
      <counter count="{count}" onclickincrement="{increment}" onclickdecrement="{decrement}">
    )}
  </counter>
);

export default Container;

actionとstore

redux-zeroを使うのでactionが一番変わってくるところ。
storeは変数を定義しておくだけでactionがreduxでいうところのaction+reducerといった感じになりそう。
各methodの引数でstoreのデータもらってreturnしたObjectがstoreのデータにmergeされるようだ。


export default () => ({
  decrement: state => ({ count: state.count - 1 }),
  increment: state => ({ count: state.count + 1 }),
});

総括

全体通してreactとほぼ同じ感覚で書けそう。
preactのベースは最新のreactより少し遅いが、ちっちゃいアプリ書く分にはこの組み合わせで十分かも。
そこそこ大きくなってもactionをうまく管理できればredux-zeroでもいいような。
課題はactiveなUIComponentがほとんどないことか。かろうじてmaterial uiが生きているようでそれ以外はメンテされていなそう。
自前で作るかcssだけbootstrapとかsemantic-uiもってくればそこそこ見せられるかな。

人気記事

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

eight − one =