coexisting-angular-microfrontends icon indicating copy to clipboard operation
coexisting-angular-microfrontends copied to clipboard

Sharing dependencies between Angular 8 single-spa applications

Open Antarus66 opened this issue 5 years ago • 9 comments

Could someone share their experience of sharing Angular deps between several single-spa applications?

I made a recommended setup like in this repo: https://github.com/polyglot-microfrontends/shared-dependencies

It works for some libs but doesn't work for Angular.

What I've done for the moment:

  1. Additional set of imports for the root application:
{
  "imports": {
    "single-spa": "https://cdn.jsdelivr.net/npm/[email protected]/lib/system/single-spa.min.js",
    "single-spa-angular": "https://cdn.jsdelivr.net/npm/[email protected]/lib/browser-lib/single-spa-angular.min.js",
    "zone.js": "https://cdn.jsdelivr.net/npm/[email protected]/dist/zone.min.js",
    "rxjs": "https://unpkg.com/@esm-bundle/rxjs/system/rxjs.min.js",
    "rxjs/operators": "https://unpkg.com/@esm-bundle/rxjs/system/rxjs-operators.min.js",
    "@angular/core": "https://cdn.jsdelivr.net/npm/@angular/[email protected]/bundles/core.umd.js",
    "@angular/common": "https://cdn.jsdelivr.net/npm/@angular/[email protected]/bundles/common.umd.min.js",
    "@angular/compiler": "https://cdn.jsdelivr.net/npm/@angular/[email protected]/bundles/compiler.umd.js",
    "@angular/forms": "https://cdn.jsdelivr.net/npm/@angular/[email protected]/bundles/forms.umd.min.js",
    "@angular/platform-browser": "https://cdn.jsdelivr.net/npm/@angular/[email protected]/bundles/platform-browser.umd.min.js",
    "@angular/platform-browser-dynamic": "https://cdn.jsdelivr.net/npm/@angular/[email protected]/bundles/platform-browser-dynamic.umd.min.js",
    "@angular/animations": "https://cdn.jsdelivr.net/npm/@angular/[email protected]/bundles/animations.umd.min.js",
    "@angular/router": "https://cdn.jsdelivr.net/npm/@angular/[email protected]/bundles/router.umd.min.js",
    "moment": "https://cdn.jsdelivr.net/npm/[email protected]/moment.min.js"
  }
}
  1. Added externals to the extra-webpack-config.js
const singleSpaAngularWebpack = require('single-spa-angular/lib/webpack').default;
const webpackMerge = require("webpack-merge");

module.exports = (angularWebpackConfig, options) => {
  const singleSpaWebpackConfig = singleSpaAngularWebpack(angularWebpackConfig, options);

  const externalsConfig = {
    externals: {
      'zone.js': 'Zone',
      "rxjs": "rxjs",
      'moment': 'moment',
      "@angular/core": "@angular/core",
      "@angular/common": "@angular/common",
      "@angular/compiler": "@angular/compiler",
      "@angular/forms": "@angular/forms",
      "@angular/platform-browser": "@angular/platform-browser",
      "@angular/platform-browser-dynamic": "@angular/platform-browser-dynamic",
      "@angular/animations": "@angular/animations",
      "@angular/router": "@angular/router"
    },
  };
  const mergedConfig = webpackMerge.smart(singleSpaWebpackConfig, externalsConfig);

  console.log(mergedConfig);

  return mergedConfig;
}

It works fine for dependencies except of @angular/* On application loading I see:

image

Antarus66 avatar Mar 11 '20 15:03 Antarus66

This is something that people have done before, and I hope to create an example showing it at some point in the future. If you join our slack workspace there are several people there who can guide you on this.

internettrans avatar Mar 11 '20 15:03 internettrans

@Antarus66 you might be interested inhttps://indepth.dev/webpack-5-module-federation-a-game-changer-in-javascript-architecture/ :)

steve-todorov avatar Apr 02 '20 22:04 steve-todorov

@Antarus66 did you solve this problem? I have the same.

cihy2 avatar Jul 02 '20 14:07 cihy2

@joeldenning I'm facing a similar issue. Any example of sharing dependencies between angular apps? tried searching, couldn't get much information on this. TIA :)

kapiladiyecha avatar Jul 15 '20 17:07 kapiladiyecha

Angular's Ivy Compiler forbids runtime sharing of dependencies, which is why this example does not use it. If you use View Engine, you can do runtime sharing. More info about Ivy compiler at https://twitter.com/Joelbdenning/status/1253781652486017024

internettrans avatar Jul 16 '20 15:07 internettrans

Understand. Thanks for sharing the detailed information :)

kapiladiyecha avatar Jul 18 '20 11:07 kapiladiyecha

Works when I removed @ at the beginning of the angular dependencies names:

const singleSpaAngularWebpack = require('single-spa-angular/lib/webpack').default
const webpackMerge = require("webpack-merge");

module.exports = (angularWebpackConfig, options) => {
  const singleSpaWebpackConfig = singleSpaAngularWebpack(angularWebpackConfig, options);

  const externalsConfig = {
    externals: {
      "zone.js": "Zone",
      "rxjs": "rxjs",
      "rxjs/operators": "rxjs/operators",
      "moment": "moment",
      "angular/core": "@angular/core",
      "angular/common": "@angular/common",
      "angular/compiler": "@angular/compiler",
      "angular/forms": "@angular/forms",
      "angular/platform-browser": "@angular/platform-browser",
      "angular/platform-browser-dynamic": "@angular/platform-browser-dynamic",
      "angular/animations": "@angular/animations",
      "angular/router": "@angular/router"
    },
  };

  const mergedConfig = webpackMerge.smart(singleSpaWebpackConfig, externalsConfig);

  return mergedConfig;
}

Antarus66 avatar Oct 26 '20 14:10 Antarus66

I am wondering, if i have some import like this for moment

import 'moment' I have added moment's cdn to my import map

How do I use methods in moment like moment.now(). It currently says "moment cannot be found"

horlabyc avatar Jan 12 '21 07:01 horlabyc

I keep getting this error when trying to share angular dependencies like rxjs or @angular/core: Cannot use import statement outside a module

I have tried to disable Ivy but no changes, I'm using angular 9

zalito12 avatar Feb 13 '21 15:02 zalito12