年末年始あたりにHyperapp関連の記事を沢山見かけたので試してみました
使ったのはHyperapp,バンドルにはparcel, ホスティングにはNetlifyを使った
これが成果物
Hyperapp
state, action, view だけのシンプルな感じはすぐに馴染めて楽しかった。
いきなりコード見せると(プログラミング苦手なのでレビューお願いします、もっといい方法とか🙇)
import { h, app } from 'hyperapp'
import picostyle from 'picostyle'
const ps = picostyle(h)
const STORAGE_KEY = 'MyNameIsBond'
const WEEK = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
const MONTH = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
const fetchTodos = () => {
return JSON.parse(window.localStorage.getItem(STORAGE_KEY)) || []
}
const today = new Date()
const dayName = () => {
return WEEK[today.getDay()]
}
const todayDate = () => {
return `${MONTH[today.getMonth()]} ${today.getDate()}, ${today.getFullYear()}`
}
const state = {
todoValue: '',
todos: fetchTodos(),
dayName: dayName(),
todayDate: todayDate()
}
const actions = {
onInput: value => state => {
state.todoValue = value
},
addTodo: () => state => {
if (!state.todoValue.length) return
state.todos.push({
id: state.todos.length,
value: state.todoValue,
completed: false
})
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(state.todos))
state.todoValue = ''
return state.todos
},
removeTodo: id => state => {
state.todos = state.todos.filter(todo => todo.id !== id)
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(state.todos))
return state.todos
},
handleCheckbox: index => state => {
state.todos[index].completed = !state.todos[index].completed
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(state.todos))
return state.todos
},
}
const view = (state, actions) => {
const Wrapper = ps('main')({
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
textAlign: 'center',
})
~~~ css 省略 ~~~
return(
<Wrapper>
<Content>
<Week>{ state.dayName }</Week>
<Date>{ state.todayDate }</Date>
<TodoLists>
{
state.todos.map((todo, index) => {
return(
<TodoListsItem
class={todo.completed ? "completed" : ""}
>
<span class="todo-value">{todo.value}</span>
<Checkbox
type="checkbox"
checked={todo.completed}
onclick={() => actions.handleCheckbox(index)}
></Checkbox>
{/* <span
class="delete-button"
onclick={() => actions.removeTodo(todo.id)}
>×</span>
*/}
</TodoListsItem>
)
})
}
</TodoLists>
<TodoInput
type="text"
placeholder="What needs to be done?"
value={state.todoValue}
oninput={e => actions.onInput(e.target.value)}
onkeydown={e => e.keyCode === 13 ? actions.addTodo() : ''}
oncreate={e => e.focus()}
/>
</Content>
</Wrapper>
)
}
export const main = app(state, actions, view, document.body)
シンプルなアプリなので説明する所はあまりないかも
Todo removeのコードはあるけど、UIが定まらなくてコメントアウトしちゃった
個人的にjsx書くの初めてだったので、色々勉強になった。(気になったのはみんなjsxの中にロジックとかガンガン書いてるんだけど、jsxでは普通?)
やっぱりもっとJS勉強して上手くならなきゃ...😰
Parcel, Netlify, おまけ
Parcel
ParceとHyperappの連携はこちらの記事を参考にさせてもらった
ほんとにお手軽にバンドルできて感動した🕺
ひとつだけ詰まったのはProduction用のbuild
parcel build index.html
だとデフォルトの dist
ディレクトリにバンドルされてJS, CSSのパスが /dist/foobar.js
になる。その状態でデプロイしちゃってそんなのねーよ!って怒られた。
Production buildは parcel build index.html --public-url ./
が正解みたい
Netlify
めっちゃ簡単、死ぬほど簡単
全部ブラウザで完結するのでHerokuより簡単だと思う
なかでもPrerenderをやってくれる機能があったので使いたかったけど有料プランからだったので諦めた、お金持ちになったら払いたい
おまけ(picostyle)
スタイリングにはpicostyleを使った
こちらの記事を読んでHyperapp使うならこれなんだなって勝手に解釈した
今までVueのsingle file compenentしか使ってなかったのでCSS in JSは新鮮だった。
特に悩むことはなかったけど、CSS in JS特有の普通のCSSの書き方から逸脱するのは結構辛かった
SketchかZeplinのデータそのままコピペが不可能でしんどいなーって感想
ex) marginRight: '16px' => margin-right: 16px;
[styled-components](https://github.com/styled-com
ponents/styled-components)はそこら辺普通のシンタックスでいけるのでpicostyleも対応してくれるとありがたいなぁ🤔
感想
自分みたいなレベルめた低いやろうでも理解はできました
なのでJavaScriptを学んでなんか簡単なアプリケーション作りたい!っていう人におすすめな気がします!
Vueとか色んな所で簡単!って言われるけどなんだかんだVue特有の何かみたいなのは存在するのでやっぱりハードルは高い気が前々からしてました。
Hyperappはその特有さがほぼ0。
かなりとっつき易いです。
このTODOアプリもちょっとずつ更新していこうと思います(アイテム消したり、コンプリートしたものだけのソートとか、リマインダー機能とか)