Prototype toolkit

A collection of tools for rapid prototyping.

Web

Use Web, unless native features are required. Web presents the lowest barrier to entry in terms of development (across client and server), and deployment.

Build

Use watchify. It’s simple and stable.

Watch Rollup. Its dependency on ES6 syntax simplifies things, and its API is a balance of browserify’s simplicity and webpack’s configurability. Additionally, it uses a proactive form of dead code elimination, which may be more efficient.

NPM boilerplate:

1
2
3
4
5
6
7
8
9
10
{
"scripts": {
"start": "watchify main.js -o demo/bundle.js -v",
"serve": "serve"
},
"devDependencies": {
"serve": "^6.2.0",
"watchify": "^3.9.0"
...
}

Language

Use ES6 (for concision and to simplify client and server dev) 1

HTML diffing

Use diffhtml. Dodson enthusiastically recommends it and it’s worked well for me.

Custom elements

Use web components with ES6 classes. Dodson describes the benefits well.

Web components are well-supported natively and via polyfills.

Example widget:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import {html, innerHTML} from 'diffhtml'

class Widget extends HTMLElement {
static get is() { return 'x-widget' }
connectedCallback(){
this.emojis = {
smile: '🙂',
grin: '😁'
}
this.filter = ''
this.render()
}
render(){
const options = Object.keys(this.emojis)
.filter(name => name.startsWith(this.filter))
.map(name => {
const emoji = this.emojis[name]
return html`
<span data-name="
${name}">${emoji}</span>
`

})
innerHTML(this, html`
<div class="options">
${options}
</div>
`
)
}
}
export default Widget

Registration boilerplate:

1
2
3
4
5
[Widget].forEach(el => {
if (!window.customElements.get(el.is)) {
window.customElements.define(el.is, el);
}
})

Note is naming convention consistent with Polymer.

Note event listeners bound externally to separate behavior from markup, and to survive template inlining, eg via Babel:

1
2
3
4
5
connectedCallback(){
this.render()
this.composer = this.querySelector('textarea')
this.composer.addEventListener('keyup', this.onKeyUp.bind(this))
}

Footnotes

  1. Type safety is helpful for non-trivial code bases, but the goal in prototyping is to get customer feedback for the lowest cost; we can refactor to something type-safe once we’ve found product-market fit. 

Feedback

Thoughts? Suggestions? Hit me up @erikeldridge

License

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 International License, and code samples are licensed under the MIT license.