LoginSignup
5
1

More than 3 years have passed since last update.

preact にも hooks が生えそうなのでやっていく

Last updated at Posted at 2019-06-09

軽量で react ライクなライブラリである preact に hooks が入りそうなのをたまたま見つけたので久しぶりにやっていく

やっていくライン

  1. webpack-dev-server で hot-reload 開発
  2. webpack を介した bundle
    1. preact gzip で 3kb 説検証
  3. webpack 外で静的ホスト

setup

もろもろ準備する

package.json

package.json
  "scripts": {
    "dev": "webpack-dev-server --config ./webpack.config.js --mode development",
    "build": "npm run clean && npm run build:webpack && cp ./dist/bundle.js ./public/",
    "build:webpack": "webpack --config ./webpack.config.js",
    "clean": "rm -rf ./dist/ ./public/bundle.*",
    "start": "serve ./public",
    "init": "npm i && mkdir src public && touch src/index.js public/index.html babel.config.js webpack.config.js",
    "gzip": "gzip -k9rn ./dist"
  },
  "dependencies": {
    "preact": "10.0.0-beta.2"
  },
  "devDependencies": {
    "@babel/cli": "7.4.4",
    "@babel/core": "7.4.5",
    "@babel/plugin-transform-react-jsx": "7.3.0",
    "@babel/preset-env": "7.4.5",
    "babel-loader": "8.0.6",
    "serve": "11.0.1",
    "webpack": "4.33.0",
    "webpack-cli": "3.3.3",
    "webpack-dev-server": "3.7.1"
  },
  • webpack, babel
    • 近代では必須
  • preact
    • やっていく module
  • serve
    • 静的ホスト簡易サーバ

初期化コマンドで諸々用意する

npm run init

babel

babel.config.js
const presets = [
  [
    '@babel/env',
    {
      targets: {
        chrome: '75',
      },
    },
  ],
];
const plugins = [['@babel/plugin-transform-react-jsx', { pragma: 'h' }]];
module.exports = { presets, plugins };

とりあえず chrome で動けばいいので targets は適当に指定しとく
公式に載ってる通りに JSX をコンパイルできるようにする plugin だけ入れとく

webpack

webpack.config.js
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',
  },
};

まあ packer の皆さんなら特に難しいところもないと思うので割愛

development

まずはハロワを目指す

public/index.html
<!DOCTYPE html>
<html>
  <head>
    <title>preact starter</title>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <script src="/bundle.js" async></script>
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
src/index.js
import { h, render } from 'preact';

const App = ({}, {}) => <div>Hello Preaaaaaaaaact</div>;

render(<App />, document.getElementById('app'));
dev-server
npm run dev

多分これでいけてると思う
あとは好きに修正すればokということでやっていきライン1はクリア

ここで build も試す

npm run build && npm run gzip && ls -lah dist/
# ... 3.5K ... bundle.js.gz

import cost と同じ数値なので成功ということでやっていきライン2もクリア
続けて3のクリアも目指す

npm start

全クリできたと思う
静的ホスティングはnowでもねっとりファイでもなんでもいいと思う

hooks

ついでに preact の hooks をいくつか書いて終わりたいと思う

src/index.js
import { h, render } from 'preact';
import { useState, useMemo, useLayoutEffect, useCallback } from 'preact/hooks';

const Clock = () => {
  const [time, setTime] = useState(0);

  const double = useMemo(() => {
    return time * 2;
  }, [time]);

  const increment = useCallback(() => {
    setTime(time + 1);
  }, [time]);
  const decrement = useCallback(() => {
    setTime(time - 1);
  }, [time]);

  useLayoutEffect(() => {
    time !== 0 && time % 3 === 0 && setTime(time + 1);
  }, [time]);

  return (
    <div>
      {time}
      {double}
      <button onclick={increment}>++</button>
      <button onclick={decrement}>--</button>
    </div>
  );
};

const App = () => (
  <div>
    Hello Preaaaaaaaaact
    <Clock />
  </div>
);

render(<App />, document.getElementById('app'));

流石に書き味は同じだった
ちなみに preact/hooks の bundle size は gzip で 3.5kb くらい

5
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1