hyperappとは
ここに作者の@jbucaranさんの記事があるので、そちらをご覧あれ。
この記事は?
最近hyperappを使って作っているものがあって、それ用の備忘録です。
# 当然、人目に晒すことで、いろいろアドバイスをもらおうって魂胆も
本題
悩み
hyperappでコンポーネントごとにファイルを分けるには、どう書いてどう読み込めばいいか。
あるissue内のコメントやforkされたリポジトリに、コンポーネントごとに分ける例はあった。
ただこれもindex.jsのような単一のファイルに全て書かれていて、コンポーネントごとに更新していくのがツラいかもと思い、ファイル分割を色々試行錯誤してみた。
もっといいやり方をご存知の方はコメントください。
お題
分割のお題はCodePen上のサンプル。下記のような1ファイルのjsx。
index.jsx
const { h, app } = hyperapp
/** @jsx h */
const Slider = ({ color, value, update }) =>
<div>
<input
type="range" min="0" max="255"
value={value}
oninput={e => update({
color: color,
value: e.target.value
})}
/>
</div>
app({
state: { red: 255, green: 255, blue: 255 },
actions: {
changeColor: (state, actions, { color, value }) => ({ [color]: value }),
updateBgColor: (state, actions, data) => {
document.body.style.backgroundColor = `rgb(${state.red}, ${state.green}, ${state.blue})`
actions.changeColor(data)
}
},
view: (state, actions) =>
<div>
<p>Use the sliders to change the background color.</p>
{Object.keys(state).map(color =>
<Slider
color={color}
value={state[color]}
update={actions.updateBgColor}
/>)}
</div>
})
これを思いのままに分割してみる。
結果
以下のようなファイル構成に分割してみた。
src/js
├── components
│ ├── slider.js
│ └── sliderList.js
└── index.js
それぞれのファイルの中身は下記に。
index.jsx
import { h, app } from 'hyperapp';
import SliderList from './components/sliderList';
/** @jsx h */
app({
state: { red: 255, green: 255, blue: 255 },
actions: {
changeColor: (state, actions, { color, value }) => ({ [color]: value }),
updateBgColor: (state, actions, data) => {
document.body.style.backgroundColor = `rgb(${state.red}, ${state.green}, ${state.blue})`
actions.changeColor(data)
}
},
view: (state, actions) =>
<SliderList
colorValues={state}
update={actions.updateBgColor}
/>
})
sliderList.js
import { h } from 'hyperapp';
import Slider from './slider';
export default ({ colorValues, update }) =>
<div>
<p>Use the sliders to change the background color.</p>
{Object.keys(colorValues).map(color =>
<Slider
color={color}
value={colorValues[color]}
update={update}
/>)}
/>
</div>
slider.jsx
import { h } from 'hyperapp';
export default const ({ color, value, update }) =>
<div>
<input
type="range" min="0" max="255"
value={value}
oninput={e => update({
color: color,
value: e.target.value
})}
/>
</div>
ビルドはgulp&browserifyで。こちらもアドバイス&突っ込みが欲しい。
gulpfile.js
var gulp = require("gulp");
var babel = require("gulp-babel");
var uglify = require('gulp-uglify');
var babelify = require('babelify');
var transform = require('vinyl-transform');
var source = require('vinyl-source-stream');
var buffer = require("vinyl-buffer");
var browserify = require('browserify');
var collapse = require('bundle-collapser/plugin');
/*
* (中略)
*/
gulp.task( 'browserify', function() {
return browserify('./src/js/index.js', { debug: false })
.transform(
babelify,
{
presets: ["es2015"],
plugins: [
[
"transform-react-jsx",
{
"pragma": "h"
}
]
]
}
)
.plugin(collapse)
.bundle()
.on("error", function (err) { console.log("Error : " + err.message); })
.pipe(source('dist/js/bundle.js'))
.pipe(buffer())
.pipe(uglify())
.pipe(gulp.dest('./'))
});