Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Collaborative JS
Search
Ben Foxall
August 10, 2016
Technology
1
160
Collaborative JS
How to build a collaborative browser-based editor (and why)
Ben Foxall
August 10, 2016
Tweet
Share
More Decks by Ben Foxall
See All by Ben Foxall
Web Sites & Fairy Lights
benfoxall
0
120
Making Simple Things
benfoxall
2
240
Simpler Things
benfoxall
0
1.7k
Using Browsers to Visualise Data
benfoxall
0
79
Serving Data From Browsers
benfoxall
0
62
Building multi-device interfaces with the web
benfoxall
1
170
Other Decks in Technology
See All in Technology
「良さそう」と「とても良い」の間には 「良さそうだがホンマか」がたくさんある / 2025.07.01 LLM品質Night
smiyawaki0820
1
430
プロダクトエンジニアリング組織への歩み、その現在地 / Our journey to becoming a product engineering organization
hiro_torii
0
140
OPENLOGI Company Profile for engineer
hr01
1
33k
OPENLOGI Company Profile
hr01
0
67k
使いたいMCPサーバーはWeb APIをラップして自分で作る #QiitaBash
bengo4com
0
1.3k
事業成長の裏側:エンジニア組織と開発生産性の進化 / 20250703 Rinto Ikenoue
shift_evolve
PRO
1
520
あなたの声を届けよう! 女性エンジニア登壇の意義とアウトプット実践ガイド #wttjp / Call for Your Voice
kondoyuko
4
510
2025-06-26_Lightning_Talk_for_Lightning_Talks
_hashimo2
2
110
ビギナーであり続ける/beginning
ikuodanaka
2
270
Model Mondays S2E03: SLMs & Reasoning
nitya
0
240
Tokyo_reInforce_2025_recap_iam_access_analyzer
hiashisan
0
140
GitHub Copilot の概要
tomokusaba
1
150
Featured
See All Featured
A Tale of Four Properties
chriscoyier
160
23k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.7k
Practical Orchestrator
shlominoach
188
11k
Designing for Performance
lara
609
69k
Mobile First: as difficult as doing things right
swwweet
223
9.7k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.4k
Reflections from 52 weeks, 52 projects
jeffersonlam
351
20k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
30
2.1k
Git: the NoSQL Database
bkeepers
PRO
430
65k
Music & Morning Musume
bryan
46
6.6k
Testing 201, or: Great Expectations
jmmastey
42
7.6k
RailsConf 2023
tenderlove
30
1.1k
Transcript
HELLO! I'm @benjaminbenben!
I work at @Pusher
None
I co-organise @JSOxford
None
I've not really said this stuff yet 1. Tell me
if we've been here too long 2. I'd be happy (and sorry) if you tell me this is rubbish
Live coding across all the things
Live coding across all the things
How to build a collaborative browser-based editor (and why)
䡿 Browser-based editors
None
side note - not just frontend
None
cojs.co
!
/
/ 䡿 The challenges
None
The challenges —Making a textarea feel nice —Showing content —Code
transpilation —External modules —Not breaking things
/ 䡿 The challenges Making a textarea feel nice
Web based code editors (maybe don't write one yourself) —Ace
Editor —Monaco —CodeMirror —~Atom~
None
Integration with our textarea CodeMirror.fromTextArea(source)
…tonnes more stuff
/ 䡿 The challenges Showing content <iframe id="target" href="/mypage"></iframe> (normal
answer: host it somewhere) !
Option 1.
"Upload" to ServiceWorker Web page → Service Worker → Network
hmmmmm —trendy —cool —persistant urls —overkill possibly —support is …
positive? —really cool
Option 2.
Data URIs
data:[<mediatype>][;base64],<data>
data:text/html,<h1>Hello! !
iframe.src = 'data:text/html;charset=utf-8,'+ '%3Cbody%3E%3Cscript%3E' + encodeURI(source.value) + '%3C/script%3E'
hmmm —lack of error handling —length limitations —random encoding issues
—restrictions…
None
Option 3.
Blobs new Blob(blobParts[, options])
b = new Blob(['…'], {type: 'text/html'})
b = new Blob(['…'], {type: 'text/html'}) url = URL.createObjectURL(b) //
"blob:https%3A/…/2084018…ab3a2cec02" // later URL.revokeObjectURL(url) !
var blob = generate(source.value) URL.revokeObjectURL(target.src) iframe.src = URL.createObjectURL(blob)
hmmm! —not stored on the stack —safe, and lots of
control —sounds cool
/ 䡿 The challenges Code transpilation
ES2015 const hey = (you) => console.log(`HELLO ${you}`) !
Tracuer Babel Bublé
All pretty cool, though personally ♥Bublé
Bublé —inspired by Babel —no shims / polyfills —compact transforms
only —less extensibility —fast —Nice one, Rich Harris
buble.transform(source.value).code
/ 䡿 The challenges External modules
// commonjs const utils = require('utils') utils.say('yeah!') // ES2015 modules
import {say} from 'utils' say('yeah!')
bundling !
Webpack Browserify Rollup
All pretty cool, though… ♥Rollup
Rollup —embracing ES2015 modules —minimal code-rewriting —tree shaking —d3, THREE.js
Rollup —embracing ES2015 modules —minimal code-rewriting —tree shaking —d3, THREE.js
—Seriously, Rich Harris you're the best
rollup.rollup({ entry: '__main__', plugins:[ { resolveId: (i) => i, load:
(id) => { if(id == '__main__') return source.value return fetch('/module/' + id + '.js') } } ] }).then(bundle => bundle.generate({ format: 'iife' }).code )
/ 䡿 The challenges Not breaking things
for(var i = 99; i > 0; i++) { console.log(`${i}
bottles of beer`) }
jsbin/loop-protect Super props, Remy Sharp loopProtect(`for(var i = 99; i
> 0; i++) { console.log(\`${i} bottles of beer\`) }`)
{;loopProtect.protect({ line: 1, reset: true }); for(var i = 99;
i > 0; i++) { if (loopProtect.protect({ line: 1 })) break; console.log(`${i} bottles of beer`) } !
/
/ 䡿 Why
Closing the loop
Closing the loop change, save, tab, ftp, wait, tab, refresh
Uploading stuff to a server
Closing the loop change, save, tab, refresh Local development
Closing the loop change, save Live reload+
Closing the loop change In place editing
This is a good thing
/ 䡿 Why Multi Device Development Experiments
/1 Collaboration
None
/2 Broadcast
/2.1 (Broadcast) For development
/2.2 (Broadcast) For talk-workshops
/3 Social inspired development
/
/ demo? let's build a "musical instrument"
People & user experience are the difficult things (so let's
focus on them)
Thank you, I'm @benjaminbenben (also, right here)