Hone logo
Hone
Problems

Integrating SystemJS for Dynamic Module Loading in Angular

Angular's built-in module system is powerful, but sometimes you need more flexibility – the ability to load modules dynamically at runtime based on user interaction or configuration. This challenge tasks you with implementing a basic SystemJS loader within an Angular application, allowing you to load and utilize modules that aren't part of the initial Angular build. This is useful for plugins, dynamic features, or scenarios where you want to minimize the initial bundle size.

Problem Description

You need to create an Angular service that leverages SystemJS to dynamically load modules. The service should accept a module name (string) as input and return a Promise that resolves with the loaded module. The loaded module should be an Angular component that can be used within a template. The service should handle potential errors during module loading gracefully.

Key Requirements:

  • Dynamic Module Loading: The service must be able to load modules specified by their name (string) at runtime.
  • Promise-Based: The loading process should be asynchronous and return a Promise. The Promise should resolve with the loaded module (an Angular component class).
  • Error Handling: The service must handle errors that occur during module loading (e.g., module not found, SystemJS errors) and reject the Promise accordingly.
  • Angular Component Compatibility: The loaded module must be an Angular component class that can be instantiated and used within an Angular template.
  • SystemJS Configuration: The service should utilize a pre-configured SystemJS instance. You will be provided with a basic SystemJS configuration.

Expected Behavior:

  1. When loadModule(moduleName) is called with a valid module name, SystemJS should load the module asynchronously.
  2. Upon successful loading, the Promise should resolve with the Angular component class.
  3. If SystemJS encounters an error during loading, the Promise should reject with an appropriate error message.
  4. The loaded component should be usable within an Angular template (e.g., using *ngComponentOutlet).

Edge Cases to Consider:

  • Module not found: SystemJS fails to locate the module.
  • Invalid module name: The provided module name is not a valid module identifier.
  • SystemJS configuration errors: Issues with the SystemJS configuration itself.
  • Circular dependencies: Modules depending on each other in a circular fashion. (While not required to solve this, consider how your code might behave in such a scenario).

Examples

Example 1:

Input: moduleName = 'MyDynamicComponent'
SystemJS Configuration: { map: { 'MyDynamicComponent': './dynamic-components/my-dynamic-component' } }
Output: Promise resolves with the `MyDynamicComponent` class (an Angular component).
Explanation: SystemJS loads the module from the configured path, and the Promise resolves with the component class.

Example 2:

Input: moduleName = 'NonExistentComponent'
SystemJS Configuration: { map: { 'MyDynamicComponent': './dynamic-components/my-dynamic-component' } }
Output: Promise rejects with an error message like "Module 'NonExistentComponent' not found".
Explanation: SystemJS fails to find the module, and the Promise rejects with an appropriate error.

Example 3: (Edge Case)

Input: moduleName = ''
SystemJS Configuration: { map: { 'MyDynamicComponent': './dynamic-components/my-dynamic-component' } }
Output: Promise rejects with an error message like "Invalid module name provided."
Explanation: An empty module name is invalid, and the Promise rejects.

Constraints

  • SystemJS Configuration: You will be provided with a basic SystemJS configuration object. Do not attempt to modify this configuration within your service.
  • Module Format: Assume the dynamically loaded modules are standard TypeScript/Angular components compiled into JavaScript modules.
  • Performance: While not a primary focus, avoid unnecessary operations that could significantly impact performance. SystemJS loading itself is inherently asynchronous and can be slow.
  • Error Messages: Provide informative error messages when the Promise is rejected.
  • Angular Version: Assume Angular 14 or later.

Notes

  • You'll need to import SystemJS and import() from the systemjs package. Make sure this package is installed in your project (npm install systemjs).
  • Consider using try...catch blocks to handle potential errors during the module loading process.
  • The SystemJS configuration will map module names to their corresponding paths.
  • The loaded module is expected to be an Angular component class, not an instance of the component. You will need to instantiate it separately.
  • Focus on the core functionality of loading the module and resolving/rejecting the Promise. Component instantiation and template integration are outside the scope of this challenge.
  • The provided SystemJS configuration will be a simple map object. More complex configurations are not required for this challenge.
  • You are not required to handle all possible SystemJS errors, but should cover the most common ones (module not found, invalid module name).
Loading editor...
typescript