♻️ Refactor route preload and component loading with core packs#2734
Open
b-l-i-n-d wants to merge 16 commits into
Open
♻️ Refactor route preload and component loading with core packs#2734b-l-i-n-d wants to merge 16 commits into
b-l-i-n-d wants to merge 16 commits into
Conversation
…y-loaded routes in the learning area
- Add error guard in route-preload chain to prevent Alpine startup failure - Remove drop_console from rspack config so console.error survives minification - Move copyToClipboard from media-editor to base pack - Remove duplicate previewTriggerMeta from form-controls pack
…ress bar animation
Collaborator
sazedul-haque
left a comment
There was a problem hiding this comment.
Please make a separate PR for comment updates @b-l-i-n-d
This reverts commit 384f9f6.
| return params.get('subpage'); | ||
| }; | ||
|
|
||
| const preloadedLearningAreaPage = getCurrentLearningAreaPage(); |
Collaborator
There was a problem hiding this comment.
The variable name should be currentPage or currentLearningAreaPage
| return dashboardRoutes[route]; | ||
| }; | ||
|
|
||
| const preloadedDashboardRoute = getCurrentPage(); |
Collaborator
There was a problem hiding this comment.
variable name should be currentPage.
| @@ -0,0 +1,8 @@ | |||
| import { type TutorComponentRegistry } from '@Core/ts/ComponentRegistry'; | |||
Collaborator
There was a problem hiding this comment.
We will need the player in course details page in future.
| selectMeta, | ||
| selectDropdownMeta, | ||
| statusSelectMeta, | ||
| stepperDropdownMeta, |
Collaborator
There was a problem hiding this comment.
There is no use of stepperDropdownMeta. Let's skip this.
| initializeDashboardRoute: initializeHome, | ||
| }; | ||
| }), | ||
| dashboard: createRouteConfig(withBasePack('core-form-controls'), async () => { |
Collaborator
There was a problem hiding this comment.
This looks duplicate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Code Splitting Architecture in Tutor LMS
This walkthrough explains how code-splitting is implemented in the Tutor LMS frontend using Rspack, TypeScript, and dynamic imports. Code splitting significantly improves website performance by breaking down large JavaScript bundles into smaller chunks, loading only the code necessary for the user's current view or interaction.
Overview
The code splitting architecture in this repository operates on two primary levels:
my-courses,quiz-attempts).High-Level Architecture Diagram
graph TD A["Browser Loads Entry Point<br/>(e.g., tutor-dashboard.js)"] --> B["getCurrentPage()<br/>Determine active subpage"] B --> C["getDashboardRouteConfig()<br/>Lookup route configuration"] C --> D["registerRoutePreload()<br/>Trigger parallel preloading"] subgraph Parallel Network Requests D --> E["Extract requested Core Packs<br/>(e.g., ['core-form-controls'])"] D --> F["Extract Route Loader<br/>(e.g., import('./pages/settings'))"] E --> G["requestCorePacks()<br/>Updates window.TutorRequestedCorePacks"] G --> H["window.TutorPreloadCorePacks()"] H -.-> |"Rspack dynamic import()"| I[("Download core pack chunk<br/>e.g., tutor-core-form-controls.js")] F -.-> |"Rspack dynamic import()"| J[("Download route chunk<br/>e.g., tutor-dashboard-settings.js")] end subgraph Initialization Sequence I --> K["Core Packs Promise"] J --> L["Route Module Promise"] K --> M{"chainRoutePreload()<br/>Promise.all([...])"} L --> M M --> N["alpine:init / DOMContentLoaded event"] N --> O["initializeDashboard() & initializePlugin()"] O --> P["Await window.TutorRoutePreload<br/>(Wait for network requests)"] P --> Q["registerOptionalCorePacks()<br/>Injects into TutorComponentRegistry"] Q --> R["Alpine.start()"] R --> S["initializeDashboardRoute()<br/>Executes route-specific logic"] S --> T((Application Ready)) end1. Rspack Configuration
Code splitting is fundamentally enabled by the bundler. In
rspack.config.mjs, specific optimizations and chunking strategies are defined:Tip
Dynamic Chunk Naming: Notice the use of
chunkFilename: 'js/lazy-chunks/[name].js'. This ensures that all dynamically imported files are separated from the main entry points and placed in a dedicated directory.optimization.splitChunksconfiguration targetsasyncchunks.tutorAsyncCommoncache group automatically extracts shared dependencies across multiple async chunks into a common file if they are used at least twice. This prevents code duplication across different lazy-loaded pages.2. Core Pack Code Splitting
Not every page needs a rich text editor or complex form controls. In
assets/core/ts/index.ts, core functionalities are mapped to dynamic imports:Using the
/* webpackChunkName: "..." */magic comment tells Rspack exactly what to name the generated chunk file. WhenpreloadOptionalCorePacksis called, it triggers these promises, downloading the network payload only when necessary.3. Route-Based Code Splitting
The entry points for major SPA-like areas (like the Instructor Dashboard and Learning Area) do not include the code for all their tabs.
In
assets/src/js/frontend/dashboard/index.tsandassets/src/js/frontend/learning-area/index.ts:Note
The
settingsroute explicitly requirescore-form-controlsandcore-media-editor. If the user navigates to the settings page, the route config guarantees that both the settings chunk and the required core packs are fetched.4. Preloading Infrastructure
To prevent a waterfall of network requests (e.g., waiting for a route to load before realizing it needs a core pack), the application coordinates preloading using
assets/src/js/frontend/route-preload.ts.The
registerRoutePreloadfunction is invoked immediately upon script execution. It usesPromise.allto fetch both the route module chunk and the requested core pack chunks in parallel:Performance Benefits
tutor-dashboard.jsandtutor-learning-area.jsentry points remain lightweight because they only contain the routing logic and common infrastructure.tutor-learning-quiz.jschunk. The browser can continue to use the cached versions of other pages.