Bug 1396784 - Lazy load Layout view when opening the inspector. r=gl
☠☠ backed out by 3b18e792cc3e ☠ ☠
authorAlexandre Poirot <poirot.alex@gmail.com>
Wed, 13 Sep 2017 10:56:18 +0200
changeset 430254 1061923744e8e89f9d7e36ead8a4f5d9b34979c5
parent 430253 08b377af73bba67a528167bdf68f3857b1b41491
child 430255 99f6b31d5f44f2a3106fac760a7546fbd598e1a8
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgl
bugs1396784
milestone57.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1396784 - Lazy load Layout view when opening the inspector. r=gl MozReview-Commit-ID: I5PiZbfy2J2
devtools/client/inspector/inspector.js
devtools/client/inspector/layout/layout.js
devtools/client/inspector/test/shared-head.js
devtools/client/shared/components/tabs/tabs.js
--- a/devtools/client/inspector/inspector.js
+++ b/devtools/client/inspector/inspector.js
@@ -626,18 +626,38 @@ Inspector.prototype = {
       "computedview",
       INSPECTOR_L10N.getStr("inspector.sidebar.computedViewTitle"),
       defaultTab == "computedview");
 
     // Grid and layout panels aren't lazy-loaded as their module end up
     // calling inspector.addSidebarTab
     this.gridInspector = new GridInspector(this, this.panelWin);
 
-    const LayoutView = this.browserRequire("devtools/client/inspector/layout/layout");
-    this.layoutview = new LayoutView(this, this.panelWin);
+    // Inject a lazy loaded react tab by exposing a fake React object
+    // with a lazy defined Tab thanks to `panel` being a function
+    let layoutId = "layoutview";
+    let layoutTitle = INSPECTOR_L10N.getStr("inspector.sidebar.layoutViewTitle2");
+    this.sidebar.addTab(
+      layoutId,
+      layoutTitle,
+      {
+        props: {
+          id: layoutId,
+          title: layoutTitle
+        },
+        panel: () => {
+          if (!this.layoutview) {
+            const LayoutView =
+              this.browserRequire("devtools/client/inspector/layout/layout");
+            this.layoutview = new LayoutView(this, this.panelWin);
+          }
+          return this.layoutview.provider;
+        }
+      },
+      defaultTab == layoutId);
 
     if (this.target.form.animationsActor) {
       this.sidebar.addFrameTab(
         "animationinspector",
         INSPECTOR_L10N.getStr("inspector.sidebar.animationInspectorTitle"),
         "chrome://devtools/content/animationinspector/animation-inspector.xhtml",
         defaultTab == "animationinspector");
     }
--- a/devtools/client/inspector/layout/layout.js
+++ b/devtools/client/inspector/layout/layout.js
@@ -96,24 +96,18 @@ LayoutView.prototype = {
       store: this.store,
       title: INSPECTOR_L10N.getStr("inspector.sidebar.layoutViewTitle2"),
       // @remove after release 56 (See Bug 1355747)
       badge: Services.prefs.getIntPref(PROMOTE_COUNT_PREF) > 0 ?
         INSPECTOR_L10N.getStr("inspector.sidebar.newBadge") : null,
       showBadge: () => Services.prefs.getIntPref(PROMOTE_COUNT_PREF) > 0,
     }, app);
 
-    let defaultTab = Services.prefs.getCharPref("devtools.inspector.activeSidebar");
-
-    this.inspector.addSidebarTab(
-      "layoutview",
-      INSPECTOR_L10N.getStr("inspector.sidebar.layoutViewTitle2"),
-      provider,
-      defaultTab == "layoutview"
-    );
+    // Expose the provider to let inspector.js use it in setupSidebar.
+    this.provider = provider;
   },
 
   /**
    * Destruction function called when the inspector is destroyed. Cleans up references.
    */
   destroy() {
     this.document = null;
     this.inspector = null;
--- a/devtools/client/inspector/test/shared-head.js
+++ b/devtools/client/inspector/test/shared-head.js
@@ -48,24 +48,26 @@ var openInspector = Task.async(function*
  * @return a promise that resolves when the inspector is ready and the tab is
  * visible and ready
  */
 var openInspectorSidebarTab = Task.async(function* (id) {
   let {toolbox, inspector, testActor} = yield openInspector();
 
   info("Selecting the " + id + " sidebar");
 
+  let onSidebarSelect = inspector.sidebar.once("select");
   if (id === "computedview" || id === "layoutview") {
     // The layout and computed views should wait until the box-model widget is ready.
     let onBoxModelViewReady = inspector.once("boxmodel-view-updated");
     inspector.sidebar.select(id);
     yield onBoxModelViewReady;
   } else {
     inspector.sidebar.select(id);
   }
+  yield onSidebarSelect;
 
   return {
     toolbox,
     inspector,
     testActor
   };
 });
 
--- a/devtools/client/shared/components/tabs/tabs.js
+++ b/devtools/client/shared/components/tabs/tabs.js
@@ -329,26 +329,33 @@ define(function (require, exports, modul
           // content of non-selected tab. It's faster (not sure why)
           // than display:none and visibility:collapse.
           let style = {
             visibility: selected ? "visible" : "hidden",
             height: selected ? "100%" : "0",
             width: selected ? "100%" : "0",
           };
 
+          // Allows lazy loading panels by creating them only if they are selected,
+          // then store a copy of the lazy created panel in `tab.panel`.
+          if (typeof tab.panel == "function" && selected) {
+            tab.panel = tab.panel(tab);
+          }
+          let panel = tab.panel || tab;
+
           return (
             DOM.div({
               id: id ? id + "-panel" : "panel-" + index,
               key: index,
               style: style,
               className: selected ? "tab-panel-box" : "tab-panel-box hidden",
               role: "tabpanel",
               "aria-labelledby": id ? id + "-tab" : "tab-" + index,
             },
-              (selected || this.state.created[index]) ? tab : null
+              (selected || this.state.created[index]) ? panel : null
             )
           );
         });
 
       return (
         DOM.div({className: "panels"},
           panels
         )