Repository: bokeh/bokeh

Issue:
[BUG] Incorrect initialization when loading out of focus
#### ALL software version info (bokeh, python, notebook, OS, browser, any other relevant packages)

bokeh.version = 1.2.0
python: 3.6.8
OS: Windows 10
browser: all

#### Description of expected behavior and the observed behavior
When loading a bokeh document (served using the directory format) the jinja2 template is not filled as expected if page is not in focus within 30 seconds of loading. 
Root elements are added successfully in the positions indicated in the template, but figures and ui elements are appended to the bottom of the body instead of in their bk-root elements. 

#### Complete, minimal, self-contained example code that reproduces the issue
The code below places a single checkbox inside a jinja2 template. 
The console will print a counter going up to 25.000 as a simulated loading process and to give you an opportunity to click away to a different tab or minimize the window. When the counter stops running in your console wait another 30 seconds or more. After the waiting period you can click on the loaded tab and the bokeh document will reload (the counter runs again in your console). After it completes the checkbox will appear. Inspecting the element will show an empty bk-root inside the intended-div, and the checkbox appended to the bottom of the html body instead.

**main.py**
```
from bokeh.plotting import curdoc
from bokeh.models import CheckboxGroup

CHECKBOX = CheckboxGroup(labels=['test checkbox'],
                         name="test")

for x in range(25000):
        print("delaying add_root by " + str(x))

curdoc().add_root(CHECKBOX)
```
**templates/index.html**
```
{% from macros import embed %}
{% extends base %}
<!DOCTYPE html>
<html lang="en">
  <head>
      <meta charset="utf-8">
      <title>Test</title>
        <link
            href="https://cdn.pydata.org/bokeh/release/bokeh-1.2.0.min.css"
            rel="stylesheet" type="text/css">
        <link
            href="https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.2.0.min.css"
            rel="stylesheet" type="text/css">
        <link
            href="https://cdn.pydata.org/bokeh/release/bokeh-tables-1.2.0.min.css"
            rel="stylesheet" type="text/css">
        
        <script src="https://cdn.pydata.org/bokeh/release/bokeh-1.2.0.min.js"></script>
        <script src="https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.2.0.min.js"></script>
        <script src="https://cdn.pydata.org/bokeh/release/bokeh-tables-1.2.0.min.js"></script>
        <script type="text/javascript"> Bokeh.set_log_level("debug"); </script>
  </head>
  <body>
        {% block contents %}
            <div id="intended-div">
                {{ embed(roots.test) }}
            </div>
            <div>Checkbox should be above this element</div>
        {% endblock %}     
  </body>
</html>
```
#### Stack traceback and/or browser JavaScript console output
No errors thrown 

#### Screenshots or screencasts of the bug in action
Empty intended div, checkbox appended to bottom of body
![image](https://user-images.githubusercontent.com/53251525/61773239-823a6000-adf4-11e9-9b55-11a44929e767.png)





Discussion:
This issue breaks our application's layout when running it in a virtual environment. Any suggestions for how to deal with this issue are welcomed. 

We suspect it is due to some timeout being exceeded and that that causes the VM to have the issue more often (sometimes a refresh of the page will give a correct layout).
I have a similar bug when using panel serve (which uses the bokeh server) in https://github.com/holoviz/panel/issues/791
I'm having the same or a similar problem.

But my load time is ~5 secs. And I don't click away.

See https://github.com/holoviz/panel/issues/897

![image](https://user-images.githubusercontent.com/42288570/71268528-77590c80-234d-11ea-982c-925bdd39bb83.png)

![image](https://user-images.githubusercontent.com/42288570/71268610-a1123380-234d-11ea-8f16-ecafaacfd4b2.png)

Please note I cannot reproduce the problem locally even when running the exact same Docker container as deployed with the same ENTRYPOINT.
And another Panel user has a similar problem here https://github.com/holoviz/panel/issues/791.
I've tried removing --num-procs 0 in my Dockerfile i.e. changing

```bash
ENTRYPOINT [ "panel", "serve", "app.py", "--address", "0.0.0.0", "--port", "80", "--num-procs", "0"]
```

to

```bash
ENTRYPOINT [ "panel", "serve", "app.py", "--address", "0.0.0.0", "--port", "80"]
```

and **the problem goes away**. But then my app will not be able to handle a lot of users I guess?
I've got this response on the gitter channel

When you connect to a bokeh server with an HTTP(S) request Bokeh returns a template, and that template immediately turns arounds and makes a websocket connection back to the Bokeh server. But with --num-procs > 1 there is no guarantee that the websocket connection lands on the same original process. That's why e.g. the full HTTP request is not available in the app code— if the websocket lands on a new process, that new process never saw the HTTP request, knows nothing about, can't even in principle provide it.
Maybe it would be an idea to warn users using --num-procs > 1 in the log message of the app?
At this point the next release will be bokeh 2.0 and we've already worked out a potential solution to fix the issue by that time so we likely won't be adding the warning.
You are all working so fast @philippjfr . Take care.

Resolving patch:
diff --git a/bokeh/embed/util.py b/bokeh/embed/util.py
--- a/bokeh/embed/util.py
+++ b/bokeh/embed/util.py
@@ -193,6 +193,7 @@ def to_json(self):
 
         if self.roots:
             json["roots"] = self.roots.to_json()
+            json["root_ids"] = [root.id for root in self.roots]
 
         if self.use_for_title is not None:
             json["use_for_title"] = self.use_for_title


Test patch: