Category: JavaScript

  • Debugging Sencha Ext JS

    Debugging Sencha Ext JS

    See how to fix rendering/layout bugs, event handling issues, data/store problems, memory leaks, slow UIs or integration issues with backend APIs. Ext JS apps are component-heavy and stateful. Knowing how to inspect components, stores and layouts is essential for reliable maintenance and performance.

    High‑level process

    1. Find how to reproduce the issue
    2. Use framework and browser tools to locate the component/store/lifecycle point
    3. Inspect component config/state and store data
    4. Trace the event/data flow and network activity
    5. Use profiler/heap snapshots for performance and memory issues
    6. Verify fixes in production-like builds and multiple browsers

    Tools you’ll use

    • Browser DevTools (Chrome/Chromium, Firefox): Elements/Console/Network/Sources/Performance/Memory
    • Ext-specific: Ext Inspector (browser extension or standalone component tree, configs, layouts)
    • Sencha Cmd: build, dev server, generate source maps, and manage themes/build optimizations
    • Logging/monitoring: console, remote logging (Sentry/LogRocket), HAR exports
    • Optional: Source control, CI for automated smoke/perf tests, remote debugging tools for devices

    How Ext apps are structured

    • Components: Ext.Component subclasses (panels, grids, forms, windows). They have configs, items, listeners and methods
    • Views: component hierarchies and layouts (VBox/HBox/Border/Fit/Card)
    • Controllers / ViewControllers: event handlers and glue logic (MVC/MVVM patterns)
    • ViewModel & Data Binding: bindings, formulas and session/state management
    • Stores & Models: Ext.data.Store, Ext.data.Model, proxies (ajax/rest), readers/writers, paging
    • Layout managers: compute sizes, perform reflows. Many layout bugs start here
    • Plugins & Mixins: added behavior may inject listeners or modify lifecycle.
    • ComponentQuery & global registries: Ext.getCmp, Ext.ComponentQuery.query() for locating instances
    white spiral stair

    Step‑by‑step guide

    1. Locate the component instance
    • Use Ext Inspector to browse component tree and click components to highlight DOM and show config
    • In Console: Ext.getCmp(‘componentId’) if you know id. Use Ext.ComponentQuery.query(‘componentSelector’) (e.g., ‘grid[itemId=myGrid]’) to find components. Example:
    Code
    Ext.ComponentQuery.query('gridpanel[itemId=myGrid]')[0]
    
    var c
    
    • Use component.down(), up(), ownerCt, or getRefOwner() from controllers to navigate hierarchy.
    1. Inspect config, state, and runtime props
    • In Console, once you have a component:
      • console.dir(cmp) or inspect(cmp) (Chrome) to explore methods and properties
      • Examine cmp.config, cmp.items, cmp.getStore(), cmp.getView(), cmp.getEl(), cmp.el.dom, cmp.rendered, cmp.isVisible()
    • For grids: inspect columns (cmp.headerCt), store (cmp.getStore()), selection model, view (cmp.getView()), and bufferedRenderer plugin if used
    1. Trace event handlers and listeners
    • Check cmp.listeners and cmp.hasListener(eventName). Use cmp.events to inspect observable events
    • Use Ext.util.Observable APIs; for classes that extend Observable, check using cmp.getListeners? and cmp.getObservableListeners (API may vary by version)
    • Use DevTools “Event Listener Breakpoints” for DOM events and add conditional breakpoints in JS handlers
    1. Debug store, model, and proxy flows
    • Inspect store state:
      • store.getCount(), store.getTotalCount(), store.getData().items, store.getRange(0,100)
      • Check store.getProxy() — proxy.url, reader config, writer config, and extraParams
    • Monitor network requests in DevTools (Network tab) to see request/response payloads, status codes and headers. Export HAR for sharing
    • For paging: check start/limit params and server response shape (total property expected by reader)
    1. Use breakpoints and stack traces
    • Use source maps (Sencha Cmd generates them for dev builds) to set breakpoints in original source instead of minified files. Enable source maps in browser DevTools
    • Insert debugger; statements in suspect code paths (controllers, listeners). Use conditional breakpoints for loops or frequent events
    1. Layout and rendering debugging
    • Check layout managers: call cmp.doLayout() or cmp.updateLayout() to force recompute (use carefully in production)
    • Inspect element sizes via cmp.getWidth(), getHeight(), cmp.getEl().getBoundingClientRect()
    • Look for configs that affect size: flex, width, height, min/max sizes, margins/padding. For container layouts (hbox/vbox), ensure child items have proper flex or explicit dimensions
    • Watch for nested containers with 100% heights lacking parent height, this is a common “zero height” issue
    1. Performance profiling & memory
    • Use browser Performance tab to record interactions; look for long tasks, layout thrashing and paint counts
    • Use Memory/Heap snapshots to find detached DOM nodes or retained component instances. Search for Ext.Component instances in heap snapshots to see growth over time
    • Check for unremoved listeners (listeners referencing closures preventing GC) – Ext.util.Observable listeners should be removed in destroy handlers or use managed listeners (listeners config with scope and destroy cleanup)
    1. Ext-specific debugging tips
    • Ext.getVersion() gives Ext JS version this is helpful to know for API differences
    • Ext.Loader and dynamic class loading: watch network requests for class files in dev mode. In production, classes are bundled by Sencha Cmd, use separate dev builds to debug class loading
    • Use Ext.each, Ext.Array methods and Ext.apply/Ext.merge carefully, misuse can mutate shared configs. Prefer clone/copies when reusing config objects
    • For grids with buffered rendering or infinite scrolling, inspect bufferedRenderer plugin config (view.bufferedRenderer) and server-side total/offset behavior
    • Use ComponentQuery to find components even without ids, be careful with overly broad queries for performance reasons
    Eyeglasses reflecting computer code on a monitor, ideal for technology and programming themes.

    Common pitfalls and how to avoid them

    • Relying on global ids: prefer itemId and ComponentQuery in large apps to avoid id collisions
    • Mutating prototype objects used as configs. Always clone config objects when reusing
    • Forgetting to destroy components or remove listeners. Implement destroy handlers and use managed listeners when possible
    • Using synchronous Ajax in production or blocking UI during heavy processing. Offload heavy tasks to WebWorkers or break into async chunks
    • Not enabling source maps in dev. Makes stepping through original code much easier

    Practical examples (Console snippets)

    Find a grid and its store:

    Code
    var grid = Ext.ComponentQuery.query('gridpanel[itemId=myGrid]')[0];
    console.log(grid.getStore().getData().items);
    

    Get a component by id and inspect:

    Code
    var cmp = Ext.getCmp('myPanelId');
    console.dir(cmp);
    

    See listeners on a component:

    Code
    console.log(cmp.listeners || cmp.events);
    

    Force a layout recompute:

    Code
    cmp.updateLayout(); cmp.ownerCt && cmp.ownerCt.updateLayout();
    

    Sencha Cmd & builds

    • Use Sencha Cmd to generate dev builds with source maps: builds created via sencha app watch or sencha app build development include easier-to-debug outputs. Production builds minify and concat files—use dev builds to reproduce and debug before producing a production build. Sencha Cmd also manages theming and classpath resolution

    Logging, monitoring & sharing traces

    • Use console.debug/info/warn/error with clear tags (e.g., console.debug(‘[MyApp:Grid] rowData’, rowData))
    • Capture HAR from Network panel and share with teammates
    • Export performance traces or heap snapshots. Anonymize any sensitive payloads before sharing
    • Use remote logging (Sentry/LogRocket) for production errors, but pair with local reproductions for stateful bugs

    Versioning and API differences

    • Ext JS APIs and namespaces change across major versions. Always confirm Ext.getVersion() and consult corresponding docs for that version: https://docs.sencha.com/
    • Some debugging techniques (internal property names, loader behavior) differ between classic and modern toolkits. Check which toolkit your app uses.

    Resources and references

    • Ext Inspector project/resources (search for current extension or builds compatible with your Ext version).
    • Sencha Cmd docs: https://docs.sencha.com/cmd/
    • Browser DevTools guides: Chrome DevTools docs, Firefox DevTools docs.
  • Inspecting JavaScript Framework Internals

    Inspecting JavaScript Framework Internals

    Why inspect framework internals?

    • Debugging: locate where UI state is created or changed, find origin of events or render issues
    • Learning: understand architecture, lifecycle and data flow of unfamiliar frameworks
    • Integration: hook into lifecycle, extend components or migrate features safely
    • Security & performance: spot unsafe patterns, memory leaks or heavy render hotspots

    Which frameworks this applies to

    • Component-based: React, Vue, Angular, Svelte
    • Classic/class-system frameworks: Ext JS, Dojo, Ember
    • State-management heavy: Redux/MobX/Vuex, Flux patterns

    What you can learn by inspecting

    • Component/view tree and hierarchy
    • Instance properties: props, state, internal fields, DOM refs
    • Model/data stores: shape, current values, subscribers/listeners
    • Class names and inheritance chain (prototype / ES class)
    • Event listeners and where they attach (DOM vs. framework event bus)
    • Lifecycle hooks and order of operations
    • Templates, render output, and bindings to data
    • Network/data flows that populate models (XHR/fetch/GraphQL)

    Tools to use (built‑in + popular extensions)

    • Browser DevTools (Elements/Console/Sources/Network/Performance/Memory)
    • Framework DevTools:
      • React DevTools (components, hooks, profiler)
      • Vue Devtools (component tree, Vuex inspection)
      • Angular DevTools / Augury (component tree, change detection profiling)
      • Ember Inspector (routes, components, data, templates)
      • Svelte Devtools (component state)
      • Ext JS Inspector (for Ext JS apps, component tree, configs, layouts)
    • Generic helpers:
      • Wappalyzer / BuiltWith — detect framework used
      • Redux DevTools — inspect Redux action/state history
      • XHR/fetch breakpoints and Network HAR export
      • Source-map enabled Debugger for readable stack traces
    • Code instrumentation & runtime probes:
      • console.log/console.dir, console.table
      • debugger statements and conditional breakpoints
      • Performance.mark/measure and User Timing API
      • MutationObserver and EventListener breakpoint APIs
    • Automated tools & profilers:
      • Lighthouse, WebPageTest, and framework profilers (React Profiler)

    Sample basic workflow steps for any framework

    1. Identify the framework: use Wappalyzer or inspect global objects (window.React, window.Vue, Ext, Ember)
    2. Open the appropriate framework DevTools if available (React/Vue/Ext Inspector). If not available, use DOM + Console
    3. Locate the component/view of interest using the element picker. In framework devtools, follow the component tree; in DOM inspector, find nearest root node and inspect attached data via DOM properties or dataset attributes
    4. Inspect instance state: framework tools show props/state; otherwise check element.__reactFiber / vue / Ext.getCmp or global registries used by the framework
    5. Trace event handlers: set breakpoints on event listeners (Sources → Event Listener Breakpoints) or right‑click in Console to list listeners (getEventListeners(node))
    6. Trace data flow: monitor XHR/fetch in Network, set XHR/fetch breakpoints, or instrument store actions (Redux DevTools)
    7. Debug lifecycle: set breakpoints in constructor/connectedCallback/render/useEffect/mounted hooks via source maps in the Debugger
    8. Check memory: take heap snapshots before/after actions to find detached nodes or retained closures.
    9. Confirm fixes across browsers and with production minified bundles using source maps

    Specific toolsets

    a computer screen with a keyboard and a box with a logo
    • React
      • Use React DevTools to inspect component tree, props, state, and hooks. Use the Profiler to find expensive renders
      • In Console, React adds REACT_DEVTOOLS_GLOBAL_HOOK and elements may expose internal fibers at element._reactRootContainer or el[Object.keys(el).find(k=>k.startsWith(“__reactInternalInstance”))]. Use caution as internals change across versions
      • For class components, inspect instance methods; for hooks, use DevTools hook inspection
    • Vue
      • Vue Devtools shows component tree, reactive data, and Vuex store.
      • In Console, components attach to vue on DOM nodes. Access component instance with $vm0 after selecting in devtools or use document.querySelector(…).vue
    • Angular
      • Use Angular DevTools (and Augury historically) to inspect component trees and change detection
      • Access component instance via ng.getComponent(element) in modern Angular devtools-enabled pages
    • Ext JS
      • Use Ext JS Inspector (standalone extension) to browse component tree, configs, and layouts. Ext apps commonly expose Ext global; find components with Ext.getCmp(id) or Ext.ComponentQuery.query(selector). Inspect component.config, getStore(), and getView() for grids/lists
    • Generic/class inspection
      • Inspect prototype chain: in Console run Object.getPrototypeOf(instance) repeatedly or use console.dir(instance) to view methods
      • Identify classes by constructor.name (careful: minified builds rename names). For minified code, rely on source maps
    • Events & DOM listeners
      • getEventListeners(node) in Console (Chrome) or inspect via Event Listener Breakpoints in Sources. Use MonitorEvents(node) to log events
      • For framework-emitted events, inspect framework-specific event buses (e.g., Ember.Evented, Ext.util.Observable)
    • Stores & models
      • For Redux: use Redux DevTools or window.REDUX_DEVTOOLS_EXTENSION to replay actions and inspect state diffs
      • For MobX/Vuex/Ext data stores: inspect store objects, subscribe callbacks, and check mutation logs where available

    Tips

    • Enable source maps in production builds for easier debugging, if not available, use pretty-print in Sources
    • Use conditional breakpoints to avoid stepping through tight loops
    • Avoid relying on private internals in production code, use public APIs or official hooks.
    • When inspecting minified/prod builds, map stack traces with source maps or re-run a non-minified local build for debugging
    • Use read-only inspection first, prefer not to change app state in production unless safe and reversible

    Privacy/security note

    • Don’t paste secrets or PII into console or external debugging tools. Use sanitized HARs and recordings when sharing