軽量で react ライクなライブラリである preact に hooks が入りそうなのをたまたま見つけたので久しぶりにやっていく
やっていくライン
- webpack-dev-server で hot-reload 開発
- webpack を介した bundle
- preact gzip で 3kb 説検証
- 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 くらい