Skip to content

Instantly share code, notes, and snippets.

View thomasboyt's full-sized avatar

Thomas Boyt thomasboyt

View GitHub Profile
const width = 100;
const height = 80;
const sprite = document.getElementById('sprite');
function withCanvas(id, cb) {
const el = document.getElementById(id);
if (!el) {
throw new Error(`no element named ${id}`);

No, .mjs is not a Python 3-like split

Seen a few tweets on this. I want to dispel some FUD.

Node is probably going to introduce a new file extension for JavaScript modules, .mjs. The reasons for this are long and perilous, and trying to summarize the discussion that led to it is maddening. The short version is that ES6 modules have different semantics from existing scripts, and need to be executed differently. In browsers, this is done with <script type="module">. In Node, this will be done by analyzing the file extension of the imported file.

I'll be honest: I don't love this solution! I was rooting for the TC39 counter-proposal. But I also understand the solution that the Node developers chose, and why they chose it.

The new file extension is a good enough solution. You can read the [draft spec](https://github.com/nodejs/node-eps/

Why I think Webpack is the right approach to build pipelines

(I've reposted this on my blog, which you may find more pleasant to read: http://devlog.disco.zone/2016/06/01/webpack/)

I was asked on Twitter why I think Webpack is the right approach to build tooling in JavaScript applications. My explanation is, uh, a bit longer than fit in a single tweet.

When I say "right approach," I'm specifically talking about the way Webpack's pipeline functions. There are certainly some deficiencies in various aspects of Webpack: it has a rather unintuitive API, and often requires quite a bit of boilerplate to set up. However, even with these issues, I think the core principles of how Webpack functions are sound.

I should also mention here this argument basically applies to SystemJS as well. I'm skeptical of various aspects of SystemJS, but I've only taken a very surface-level look at it, so I'm gonna withhold judgement until I've had a chance

basically, in typescript i can do:

interface MyObjectType {
  a: number;
  b?: number;
}

const obj: MyObjectType = {
 a: 1,

so there's two message types that matter for ball position: incoming "swing" messages and "sync" messages. swing messages come in as soon as another player swings. sync messages happen once a second and contain everyone's position and velocity.

both swings and sync messages have a timestamp associated with them. in perfect network conditions, the server runs slightly ahead of the client, so when yo uget a swing or sync message, you have to queue it until the client time catches up to the server.

in practice, sometimes, due to lag between the server sending you the message and you receving it, you may get a message that is "in the past." with syncs, this is fine: the world state is rolled back and synced from the past, then recalculated from that point. this is instant and, under perfect network conditions, unnoticable, since the recalculated should be the same as your current state.

with swings, however, there's an issue: due to implementation details, i can't "replay" the swing messages with a timestamp i

I'm finally getting around to putting "proper" netcode in my golf game, and I'm having a lot of trouble figuring out how to "sync" against a previous state. I've currently got it implemented in the most naive way: the server sends a "sync" message with everyone's positions and velocities to every client every second, and the client just resets all the positions/velocities of the physics bodies to whatever the server sent.

The problem is that the server state is often ahead of the client state, which I think makes sense: the server is sending each player's swing to the clients, so the network lag there causes the client simulation to be slightly behind. So when the sync happens, the balls of all the players "jump" forward a bit to whatever the server simulated.

I looked into implementing a clock, with the idea that the server would send a clock with its positions data the client could compare against. But I'm not sure what this should look like.

My first thought was that:

  • When the player connects to th
const arr = <any>[1,2,3];
// why does typescript think sum is `any` instead of `num`? shouldn't it use the type of
// initialValue here?
const arrSum = arr.reduce((acc, val) => acc + val, 0); // arrSum is `any`
// ImmutableJS does this correctly:
import I from 'immutable';
const list = I.List<any>().push(1).push(2).push(3);
const listSum = list.reduce((acc, val) => acc + val, 0); // listSum is `number`
/*
* Immutable JS's Record type allows you define maps that you can access with
* standard dot-notation instead of a get() method. It's mainly used for
* defining the shape of complex objects, such as the root state of a Redux
* component.
*
* Unfortunately, they basically don't work in TypeScript. Check this out:
*/
import * as I from 'immutable';

How I Build TypeScript

(super early draft)

I decided to add TypeScript to an existing JavaScript codebase, which ended up being one of the more terrible decisions of my life. Don't get me wrong, TypeScript-the-language seems great, and I'm excited to be able to improve my code using it. On the other hand, TypeScript-the-tool and TypeScript-the-ecosystem leave a lot to be desired.

This document covers how I integrated TypeScript into my build and tooling.

The Project

So, I'm making a browser-based golf game that's a shameless Desert Golf clone, with the added gimmick of being "massively multiplayer." The idea is that there's a server that generates levels, sends them to each connected client, and everyone plays a level together. The "multiplayer" component is that clients can see the "ghosts" of other balls, as well as a leaderboard at the end.

There's two parts to the netcode: the client needs to send some data about the ball to the server so the server knows where the ball is, and the server needs to then broadcast this data to the connected clients.

The solution I came up with was to run the same physics simulation (using p2.js) on the client and server. The client will send data for each swing to the server, which would contain the x and y velocity vector to apply to the ball. The server would broadcast this vector to each client along with the ID of the ball, so each client can visualize the "ghost" ball's movement. The server