Repository: bokeh/bokeh

Issue:
Put WebGL functionality in separate bokeh-gl.js?
Currently, we have a `bokehgl.coffee` which kept growing as features were added. With over 1400 lines, its time to split it up into a few separate files. Further we could build a separate `bokeh-gl.js` (similar to `bokeh-widgets.js` to reduce the size of the main `bokeh.js`, though this needs some discussion to establish when WebGL support should be included.

Tasks:
- [x] Refactor into smaller chunks (#4341)
- [ ] Decide on building a separate `bokeh-gl.js`
- [ ] Build a separate `bokeh-gl.js` (#4331)?



Discussion:
> There is a file size cost to splitting things up. Could we make a completely  separate and optional .js to reduce normal loads?

@bryevdv would that extra cost be due to the overhead for a "module"? What's that cost, proximately?

What do you mean with separate, more like a third party lib? If that means I can split that code up without affecting the total file size, that might be good.

How would optional actually work? At what point is decided a user/dev that webgl functionality is included in a plot?

I mean like we have already split bokeh-widgets.js off we could split off bokeh-gl.js potentially too. It not great that everyone who is never using webgl has to pay for 1400 lines of code all the time. 

Bryan

> On May 14, 2016, at 15:57, Almar Klein notifications@github.com wrote:
> 
> There is a file size cost to splitting things up. Could we make a completely separate and optional .js to reduce normal loads?
> 
> @bryevdv would that extra cost be due to the overhead for a "module"? What's that cost, proximately?
> 
> What do you mean with separate, more like a third party lib? If that means I can split that code up without affecting the total file size, that might be good.
> 
> How would optional actually work? At what point is decided a user/dev that webgl functionality is included in a plot?
> 
> —
> You are receiving this because you were mentioned.
> Reply to this email directly or view it on GitHub

By splitting off webgl stuff we should get at least 60 kB reduction in size of `bokeh.min.js`.


Resolving patch:
diff --git a/bokeh/embed.py b/bokeh/embed.py
--- a/bokeh/embed.py
+++ b/bokeh/embed.py
@@ -238,6 +238,22 @@ def _needs_widgets(obj):
     else:
         return False
 
+def _use_gl(objs):
+    from .models.plots import Plot
+
+    def _needs_gl(obj):
+        return isinstance(obj, Plot) and obj.webgl
+
+    for obj in objs:
+        if isinstance(obj, Document):
+            if _use_gl(obj.roots):
+                return True
+        else:
+            if any(_needs_gl(ref) for ref in obj.references()):
+                return True
+    else:
+        return False
+
 def _bundle_for_objs_and_resources(objs, resources):
     if isinstance(resources, BaseResources):
         js_resources = css_resources = resources
@@ -256,11 +272,14 @@ def _bundle_for_objs_and_resources(objs, resources):
 
     # XXX: force all components on server and in notebook, because we don't know in advance what will be used
     use_widgets =  _use_widgets(objs) if objs else True
+    use_gl      =  _use_gl(objs)      if objs else True
 
     if js_resources:
         js_resources = deepcopy(js_resources)
         if not use_widgets and "bokeh-widgets" in js_resources.components:
             js_resources.components.remove("bokeh-widgets")
+        if use_gl and "bokeh-gl" not in js_resources.components:
+            js_resources.components.append("bokeh-gl")
         bokeh_js = js_resources.render_js()
     else:
         bokeh_js = None
diff --git a/scripts/build_upload.py b/scripts/build_upload.py
--- a/scripts/build_upload.py
+++ b/scripts/build_upload.py
@@ -346,7 +346,7 @@ def upload_cdn(cdn_token, cdn_id):
     version = CONFIG.version
 
     content_type = "application/javascript"
-    for name in ('bokeh', 'bokeh-api', 'bokeh-widgets'):
+    for name in ('bokeh', 'bokeh-api', 'bokeh-widgets', 'bokeh-gl'):
         for suffix in ('js', 'min.js'):
             local_path = 'bokehjs/build/js/%s.%s' % (name, suffix)
             cdn_path = 'bokeh/bokeh/%s/%s-%s.%s' % (subdir, name, version, suffix)


Test patch:
diff --git a/bokehjs/test/common/selection_manager.coffee b/bokehjs/test/common/selection_manager.coffee
--- a/bokehjs/test/common/selection_manager.coffee
+++ b/bokehjs/test/common/selection_manager.coffee
@@ -52,7 +52,7 @@ describe "SelectionManager", ->
       'y_mappers':
         {'default': mapper_normal}
     canvas_view:
-      ctx: {'glcanvas': null}
+      ctx: {}
     model:
       plot_model_stub
   }
@@ -64,7 +64,7 @@ describe "SelectionManager", ->
       'y_mappers':
         {'default': mapper_reverse}
     canvas_view:
-      ctx: {'glcanvas': null}
+      ctx: {}
     model:
       plot_model_stub
   }
diff --git a/bokehjs/test/size.coffee b/bokehjs/test/size.coffee
--- a/bokehjs/test/size.coffee
+++ b/bokehjs/test/size.coffee
@@ -7,10 +7,11 @@ build_dir = path.normalize("#{__dirname}/../build")
 
 LIMITS = {
   "css/bokeh-widgets.min.css": 160
-  "css/bokeh.min.css":         60
+  "css/bokeh.min.css":          60
   "js/bokeh-widgets.min.js":   380
   "js/bokeh-api.min.js":        75
-  "js/bokeh.min.js":           699
+  "js/bokeh-gl.min.js":         70
+  "js/bokeh.min.js":           650
 }
 
 for filename, maxsize of LIMITS