Here is a somewhat compact copy-pasteable snippet that will run Game of Life at 30 fps from a random initial state.

<!DOCTYPE html>
<html><body><canvas id="c"></canvas><script>
const c = document.getElementById('c'), ctx = c.getContext('2d');
const size = 4, r = 100, cols = c.width = r * size, rows = c.height = r * size;
const fps = 30, frameTime = 1000 / fps;
let g = Array.from({length: r}, () => Array.from({length: r}, () => Math.random() < 0.5 ? 1 : 0));
let now, last = performance.now(), dt = 0;

function update(time) {
    requestAnimationFrame(update);
    now = performance.now();
    dt += now - last;
    if (dt < frameTime) return;
    dt = 0;
    g = g.map((row, y) => row.map((cell, x) => {
      let n = 0;
      for (let dy = -1; dy <= 1; dy++) for (let dx = -1; dx <= 1; dx++) if (dx || dy) {
        const ny = (y + dy + r) % r, nx = (x + dx + r) % r;
        n += g[ny][nx];
      }
      return n === 3 || (cell && n === 2) ? 1 : 0;
    }));
    ctx.clearRect(0, 0, cols, rows);
    g.forEach((row, y) => row.forEach((cell, x) => {
      if (cell) { ctx.fillRect(x * size, y * size, size, size); }
    }));
    last = now;
}

requestAnimationFrame(update);
</script></body></html>

And here is the resulting output. If it has reached a steady or oscillating state, just refresh the page.