Separate your game's code into logic code and drawing code.
Put the logic code into a function which you execute at regular intervals with
SetInterval. Intervals still get executed when the tab is inactive. Note that if you use SetInterval on the main
window object, then most browsers will throttle it when the tab is inactive. When you are using a game loop with a variable time-step (you check how much time elapsed since the last update and take it into account when moving things) then this should not be a problem. But if you want to use a fixed timestep, then you can get around this by using a web worker. Web workers can use intervals which do not get throttled in inactive tabs.
Your drawing code should stay in the method you pass to
requestAnimationFrame. You can do canvas drawing in your interval method, but using requestAnimationFrame is recommended. It should be easier for the browser's rendering engine (whether this translates to a tangible performance benefit is implementation-specific) and there is little reason to waste the client's resources on drawing frames nobody is going to see.