Skip to main content
Version: 10

Migrate remote module functionality to the deferred format

Level: advanced

Creatio provides a dedicated public API that significantly extends the capabilities of Freedom UI Designer setup areas. To support this, the remote module structure separates runtime and design-time code into independent loading features. Learn more: Working with collection attributes when implementing Freedom UI Designer setup area.

If custom functionality was implemented using a remote module for Creatio version 8.3.3 and earlier, it follows the legacy structure. Migrate it to the deferred format to take advantage of the new API, improve startup performance, and make large remotes easier to maintain. In the deferred structure, the host discovers what the remote provides without loading all runtime code up front — runtime components, setup areas, and designer metadata activate only when actually needed. Migration involves refactoring the existing Angular project to match the deferred remote structure, not recreating it from a template. For manual migration, keep the deferred remote template open for reference.

Legacy and deferred remote structures​

A typical legacy remote has the following structure:

Structure of typical legacy remote
src/
main.ts
bootstrap.ts
app/
app.module.ts
components/...
handlers/...
validators/...
converters/...

A typical deferred remote has the following structure after migration:

Structure of typical deferred remote
src/
main.ts
app/
remote-app.module.ts
remote-app-context.ts
remote-entry.ids.ts
features/
runtime/
runtime-feature.ids.ts
runtime-feature.module.ts
runtime.feature-definition.ts
runtime.feature-activation.ts
runtime.designer-definitions.ts
view-elements/...
handlers/...
validators/...
converters/...
design/
design-feature.ids.ts
design-feature.module.ts
design.feature-definition.ts
design.feature-activation.ts
property-panels/...

The exact folder names can vary, but the important change is the same in every case:

  • In the legacy remote, one eager entry path bootstraps everything
  • In the deferred remote, the entry publishes definitions, and runtime and design code activate lazily through separate features
  • Runtime components, validators, converters, and handlers usually are placed under the "features/runtime" directory
  • Setup areas and other design-only elements usually are placed under the "features/design" directory

If you migrate manually, keep the deferred remote template open while working and compare the current project against this structure.

Before starting the migration, make sure the current remote module still follows the legacy remote module structure:

  • "src/main.ts" file imports "./bootstrap" file.
  • "bootstrap.ts" file bootstraps an Angular module.
  • The "app.module.ts" file eagerly registers runtime artifacts through the bootstrapCrtModule() method.
  • Runtime components use the @CrtInterfaceDesignerItem() or @CrtMobileInterfaceDesignerItem() decorator.

To migrate remote module functionality to the deferred format, complete the following steps.

General procedure​

1. Inventory the remote module​

  1. Inspect the entry, "bootstrap.ts," and "app.module.ts" files. Make sure to inspect files beyond "app.module.ts." Remote modules often spread behavior across nested CrtModule instances and imported Angular modules.

  2. Record the following:

    • the remote module name and webpack expose settings
    • all public runtime view elements, including mobile view elements if any
    • validators, converters, and request handlers
    • all custom setup areas
    • all usages of the @CrtInterfaceDesignerItem() and @CrtMobileInterfaceDesignerItem() decorators
    • any CrtModule.includes property
    • Angular modules imported by "app.module.ts"
    • app-wide initialization and APP_INITIALIZER logic
    • translation files and translation bootstrap

2. Replace the entry and webpack contract​

  1. Open the "src/main.ts" file.

  2. Export RemoteEntryDefinition.

    "main.ts" file
    export { RemoteEntryDefinition } from './app/remote-entry.ids';
  3. Open the "webpack.config.js" file.

  4. Complete the following to match the deferred entry contract.

    1. Use the withModuleFederationPlugin() method.
    2. Expose "./Main" from "./src/main.ts."
    3. Emit "remoteModuleEntry.js."
    4. Set the correct remote module name and output.uniqueName property.
  5. Open the "angular.json" file.

  6. Set the commonChunk property to true for the deferred baseline.

  7. Save the files.

3. Move runtime artifacts into the runtime feature​

  1. Open the "src/app/features/runtime/runtime-feature.module.ts" file.

  2. Import declarations, imports, and @CrtModule().

  3. Open the "src/app/features/runtime/runtime.feature-definition.ts" file.

  4. Import discovery metadata only. Keep the file lightweight — do not import runtime modules, icons, SVG strings, or other heavy assets there.

  5. Open the "src/app/features/runtime/runtime.feature-activation.ts" file.

  6. Import custom-element registration and bootstrapCrtModule().

  7. Make sure the following is moved into the "src/app/features/runtime/" directory:

    • public runtime components
    • mobile components
    • validators, converters, and request handlers
    • Angular imports they depend on
  8. Save the files.

4. Move designer metadata out of runtime components​

  1. Open the runtime component files.
  2. Remove @CrtInterfaceDesignerItem() and @CrtMobileInterfaceDesignerItem() from all runtime components.
  3. Keep @CrtViewElement(), @CrtMobileViewElement(), and normal inputs and outputs on the components.
  4. Open the "src/app/features/runtime/runtime.designer-definitions.ts" file.
  5. Move caption, icon, default values, and propertiesPanel property references into the file. Runtime components describe runtime behavior, while toolbox metadata belongs in the designer-definition loading path.
  6. Save the files.

5. Move setup areas into the design feature​

If the Freedom UI component has a custom setup area implemented using a remote module, complete the following steps:

  1. Move setup areas out of the "src/app/features/runtime/" directory and into the "src/app/features/design/" directory that includes the "design-feature.module.ts," "design.feature-activation.ts," and "design.feature-definition.ts" files.
  2. Reference each setup area by type using the propertiesPanel property in the "runtime.designer-definitions.ts" file. The design feature is responsible for discovering and activating the setup area component itself.

6. Split lightweight IDs from heavy data​

If the remote module has a shared "constants.ts" file, complete the following steps:

  1. Open the "constants.ts" file.

  2. Split the file into:

    • lightweight IDs and type names in the "src/app/features/runtime/runtime-feature.ids.ts" and "src/app/features/design/design-feature.ids.ts" files
    • activation-only constants in the "src/app/features/runtime/runtime.feature-activation.ts" and "src/app/features/design/design.feature-activation.ts" files
    • designer-only icons and defaults in the "src/app/features/runtime/runtime.feature-definition.ts" and "src/app/features/design/design.feature-definition.ts" files
  3. Keep the deferred entry, "src/app/features/runtime/runtime.feature-definition.ts," and "src/app/features/design/design.feature-definition.ts" files lightweight. Importing heavy icon or activation data into these files undermines the purpose of deferred loading.

7. Add localization​

Skip this step if the remote module does not use the @ngx-translate external library. Otherwise, complete the following steps:

  1. Add a localization module.
  2. Open the "remote-app.module.ts" file.
  3. Import the localization module.
  4. Keep translation files under the "src/assets/i18n/" directory.
  5. Open the "remote-app-context.ts" file.
  6. Extend the file so it can switch language culture before returning designer metadata.
  7. Save the files.

8. Relocate app-wide initialization​

  1. Open the files that contain startup logic.

  2. Distribute startup logic as follows:

    • keep true app-wide initialization in RemoteAppModule
    • keep localization initialization in the localization module
    • move feature-specific setup into the feature that needs it

    Do not recreate the legacy remote module structure just to preserve initialization order.

  3. Save the files.

9. Make sure the migration is successful​

After migration, confirm the following:

  • "src/main.ts" file exports RemoteEntryDefinition
  • the remote module no longer imports "./bootstrap" file
  • runtime discovery metadata is lightweight
  • runtime code loads through the activate() method
  • designer metadata loads through the loadDesignerDefinitions() method
  • runtime components no longer use designer decorators
  • setup areas are discovered through the design feature
  • entry and feature-definition files do not import heavy icon or activation data
  • the built remote module loads follow-up chunks correctly

Use the table below to verify the location of each legacy remote module artifact in the deferred format.

Legacy remote module artifact

Location in deferred format

Legacy entry and bootstrap

"src/main.ts," "src/app/remote-app.module.ts," and "src/app/remote-app-context.ts" files

Runtime @CrtModule() registrations

"src/app/features/runtime/runtime-feature.module.ts" file

Runtime activation logic

"src/app/features/runtime/runtime.feature-activation.ts" file

Runtime discovery metadata

"src/app/features/runtime/runtime.feature-definition.ts" file

Designer decorators on runtime components

"src/app/features/runtime/runtime.designer-definitions.ts" file

Setup areas

"src/app/features/design/" directory

Setup area discovery and activation

"src/app/features/design/design.feature-definition.ts" and "src/app/features/design/design.feature-activation.ts" files

Small IDs and type names

"src/app/features/runtime/runtime-feature.ids.ts" and "src/app/features/design/design-feature.ids.ts" files

Heavy constants, icons, and activation-only data

Lazy files used only by activation or designer-definition code

As a result, custom functionality implemented using a remote module will be migrated to the deferred format. The host can now discover what the remote module provides without activating all runtime code at startup. Runtime components, setup areas, and designer metadata load only when needed, reducing unnecessary startup overhead and making the remote module easier to structure and maintain.


See also​

Custom Freedom UI component

Custom Freedom UI Designer setup area

Custom validator

Custom converter

Custom request handler