LoginSignup
8
8

More than 5 years have passed since last update.

hyperappでコンポーネント単位でファイルを分割してみる

Last updated at Posted at 2017-06-03

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('./'))
});
8
8
2

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
8
8