There are countless blog posts detailing how to split a JavaScript array into chunks. However, many of these solutions fail with arrays containing hundreds of thousands of items.

This is frequently because they use recursion. Recursive solutions are problematic because barely any JavaScript engines support tail call optimisation.

To see this in action, run the following in Node:

const chunk = (items, size) => {
  return items.length <= size
    ? [items]
    : [items.slice(0, size), ...chunk(items.slice(size), size)]
}

const items = new Array(1000000).fill('nope')

console.log(chunk(items, 7))

The right way

The following solution is far more robust.

const chunk = (items, size) => {
  return Array.from({ length: Math.ceil(items.length / size) }, (_, index) =>
    items.slice(index * size, index * size + size),
  )
}

const items = new Array(1000000).fill('yep')

console.log(chunk(items, 7))