Helper functions for using single-spa and ember together.
single-spa / single-spa-ember Goto Github PK
View Code? Open in Web Editor NEWHelper functions for using single-spa and ember together.
License: Apache License 2.0
Helper functions for using single-spa and ember together.
License: Apache License 2.0
Helper functions for using single-spa and ember together.
Problem Statement
Issue with mounting the Ember shopping engine into the app when running it from Single Spa, and receive an error related to the execution of Ember engine code, while the standalone Ember app works fine.
Error
"Error while processing route: mfe-engine-shopping.shopping.index Cannot read properties of null (reading 'externalRoutes') TypeError: Cannot read properties of null (reading 'externalRoutes')".
About the ember engine loading issue
I followed the Single Spa tutorials and used single-spa-ember for the Ember micro frontend with Single Spa. Everything works fine if the app doesn't have an engine, but I'm having trouble mounting the Ember shopping engine with dependencies into the app.
Specifically, when I try to load the shopping engine from a link in the dashboard component of the product app, I receive the following error: "Error while processing route: mfe-engine-shopping.shopping.index Cannot read properties of null (reading 'externalRoutes') TypeError: Cannot read properties of null (reading 'externalRoutes')".
Data communication between multiple ember app Issue
We leveraged the utility module provided by create-single-spa to enable data sharing between multiple Ember front-end apps. By using observables in the utility module, we exposed a method for all other Ember apps to publish and subscribe to data. However, despite attempting to make the utility module global through import maps, we were unable to do so, which prevented us from sending data through the utility module because of the utility module not loaded in global.
Technical Analyse of ember engine loading issue
The execution of Ember engine code differs between mounting the Ember app to Single Spa and running it standalone. When working in a standalone Ember app, the order of method invocation is as follows:
The _constructEngineInstance function is triggered from "ember-engines/addon/-private/router-ext.js".
Subsequently, it calls owner.buildChildEngineInstance, which then invokes buildChildEngineInstance in engine-instance-ext.js. This is one method used to assign the engine dependencies to the new object and pass it to the cloneParentDependencies method in engine-instance-ext.js.
However, when running from Single Spa, instead of triggering buildChildEngineInstance from engine-instance-ext.js, it calls buildChildEngineInstance from instance.js in the Ember JS package. Then, it makes a call to cloneParentDependencies in engine-instance-ext.js. Therefore, the dependencies are cloned to the new object from the mounted engine. The calling of buildChildEngineInstance in engine-instance-ext.js is missing here.
This seems to be the cause of the error "Error while processing route: mfe-engine-shopping.shopping.index Cannot read properties of null (reading 'externalRoutes') TypeError: Cannot read properties of null (reading 'externalRoutes')", as the cloneParentDependencies method throws this error.
The standalone Ember app works correctly, but it isn't working properly within Single Spa.
Please let me know if any repo's to refer how the ember engine will works under single spa with ember.
Any suggestions would be very helpful
Thanks in advance
I am trying to load multiple ember apps but each one is of different version. For the test I tried to add following 3 apps:
ember-1 -> "ember-cli": "1.13.8", "ember": "1.10.1"
ember-2 -> "ember-cli": "2.14.2", "ember": "2.14.1"
ember-3 -> "ember-cli": "2.18.0", "ember": "2.18.0"
ember-2 has the same version/setup as one in the single-spa-examples and it works perfectly fine.
But the other 2 versions ember-1 and ember-3, I am unable to get them to load properly.
For "ember-1" app I get
Could not find module single-spa-ember
imported from ember-1/app
For "ember-3" app I get
deprecations.js:2 Uncaught ReferenceError: define is not defined at deprecations.js:2 at deprecations.js:10
UPDATE: ember-3 is working now, was probably caused by some node module caching. Updated my build script to clear out node_modules folder before doing a build and that fixed the issue
The test application can be found here: https://github.com/dshrestha/ember-spa
It definitely seems like its again related to the loading of js modules as you had mentioned here : https://stackoverflow.com/questions/45438094/issue-in-loading-ember-app-as-child-application-in-single-spa
I am not sure if I am missing a dependency or the way I am importing the single-spa-ember is wrong for the 2 versions. Your help will be much appreciated. Thanks.
Continuing the discussion with #3, I am able to somewhat bypass that with this hacky solution. But needed a better approach or refined one with the official library itself:
function mount(opts) {
return Promise
.resolve()
.then(() => {
window.dcx.desk = window.dcx.desk || {};
if(window.dcx.desk.Ember) {
const {Ember, entries} = window.dcx.desk;
window.Ember = Ember;
window.require.entries = entries;
}
opts.applicationInstance = opts.App.create(opts.createOpts);
})
}
function unmount(opts) {
return Promise
.resolve()
.then(() => {
opts.applicationInstance.destroy();
opts.applicationInstance = null;
window.dcx.desk = window.dcx.desk || {};
window.dcx.desk = {
Ember: window.Ember,
entries: window.require.entries
}
delete window.Ember;
});
}
Still I am getting error when switching back to different Ember apps something like:
Uncaught Error: Could not find module `desk/router` imported from `(require)`
at vendor.js:12
at l (vendor.js:12)
at requireModule (vendor.js:6)
at r._extractDefaultExport (vendor.js:4410)
at resolveOther (vendor.js:4378)
at resolve (vendor.js:4388)
at vendor.js:1673
at e.resolve (vendor.js:1676)
at e.resolve (vendor.js:1677)
at p (vendor.js:1652)
@joeldenning Please let me know your thoughts on this.
This helper function https://github.com/single-spa/single-spa-ember/blob/master/src/single-spa-ember.js#L64 allow us to add app and vendor js files as params. What about css files ? Where should we import app specific styles?
I'm using this guide as a reference - https://single-spa.js.org/docs/ecosystem-ember/
ember-cli: 3.28.0
node: 14.17.5
os: darwin x64
That's my root-config
import { registerApplication, start } from "single-spa";
import {
constructApplications,
constructRoutes,
constructLayoutEngine,
} from "single-spa-layout";
import { loadEmberApp } from "single-spa-ember";
const isLocal = true;
const routes = constructRoutes(document.querySelector("#single-spa-layout"), {
loaders: {
topNav: "<h1>Loading topnav</h1>",
},
errors: {
topNav: "<h1>Failed to load topnav</h1>",
},
});
const navbarDomain = isLocal
? "http://localhost:4200"
: "https://ember-micro-frontends.github.io/navbar";
const navbarApp = registerApplication(
"navbar",
() => {
const appName = "navbar";
const appUrl = `${navbarDomain}/assets/navbar.js`;
const vendorUrl = `${navbarDomain}/assets/vendor.js`;
return loadEmberApp(appName, appUrl, vendorUrl);
},
(location) => location.pathname.startsWith("/")
);
const paymentsDomain = isLocal
? "http://localhost:4202/payments"
: "https://ember-micro-frontends.github.io/payments";
const paymentsApp = registerApplication(
"payments",
() => {
const appName = "payments";
const appUrl = `${paymentsDomain}/assets/payments.js`;
const vendorUrl = `${paymentsDomain}/assets/vendor.js`;
return loadEmberApp(appName, appUrl, vendorUrl);
},
(location) => location.pathname.startsWith("/payments")
);
const applications = [];
applications.concat(navbarApp);
applications.concat(paymentsApp);
applications.forEach(registerApplication);
const layoutEngine = constructLayoutEngine({ routes, applications });
layoutEngine.activate();
start();
I'm getting this error when I try to access http://localhost:9000/payments
The first app navbar
is working well, but when I try to load a second app I have this error related with glimmer
It's only checked to see if the user passed it, but it's never called after that.
Hi, I made an example of the issue here on this git hub repo to help explain/show the issue I'm seeing.
The README.MD has setup instructions.
[email protected]:genechan/single-spa-ember-bug.git
https://github.com/genechan/single-spa-ember-bug
I'm trying to setup ember with single-spa-ember, I see my vendor and ember.js file load but the ember application does not start. For a test, I'm using the default ember quick start as the ember app to avoid any personal ember code mistakes. https://guides.emberjs.com/release/getting-started/quick-start/
thank you in advance for looking at this.
Problem Statement
Issue with mounting the Ember shopping engine into the app when running it from Single Spa, and receive an error related to the execution of Ember engine code, while the standalone Ember app works fine.
Error
"Error while processing route: mfe-engine-shopping.shopping.index Cannot read properties of null (reading 'externalRoutes') TypeError: Cannot read properties of null (reading 'externalRoutes')".
About the issue
I followed the Single Spa tutorials and used single-spa-ember for the Ember micro frontend with Single Spa. Everything works fine if the app doesn't have an engine, but I'm having trouble mounting the Ember shopping engine with dependencies into the app.
Specifically, when I try to load the shopping engine from a link in the dashboard component of the product app, I receive the following error: "Error while processing route: mfe-engine-shopping.shopping.index Cannot read properties of null (reading 'externalRoutes') TypeError: Cannot read properties of null (reading 'externalRoutes')".
Technical Analyse
The execution of Ember engine code differs between mounting the Ember app to Single Spa and running it standalone. When working in a standalone Ember app, the order of method invocation is as follows:
The _constructEngineInstance function is triggered from "ember-engines/addon/-private/router-ext.js".
Subsequently, it calls owner.buildChildEngineInstance, which then invokes buildChildEngineInstance in engine-instance-ext.js. This is one method used to assign the engine dependencies to the new object and pass it to the cloneParentDependencies method in engine-instance-ext.js.
However, when running from Single Spa, instead of triggering buildChildEngineInstance from engine-instance-ext.js, it calls buildChildEngineInstance from instance.js in the Ember JS package. Then, it makes a call to cloneParentDependencies in engine-instance-ext.js. Therefore, the dependencies are cloned to the new object from the mounted engine. The calling of buildChildEngineInstance in engine-instance-ext.js is missing here.
This seems to be the cause of the error "Error while processing route: mfe-engine-shopping.shopping.index Cannot read properties of null (reading 'externalRoutes') TypeError: Cannot read properties of null (reading 'externalRoutes')", as the cloneParentDependencies method throws this error.
The standalone Ember app works correctly, but it isn't working properly within Single Spa.
Please let me know if any repo's to refer how the ember engine will works under single spa with ember.
Any suggestions would be very helpful
Thanks in advance
With a new app built with single-spa Ember, I get the warning: https://single-spa.js.org/error/?code=41 ("single-spa is loaded on the page multiple times") whenever the Ember app mounts. Other single-spa applications are using Webpack, so have externals: ['single-spa']
in their webpack config.
I've tried a few things to accomplish the same in Broccoli, but with no success yet.
const EmberApp = require('ember-cli/lib/broccoli/ember-app');
const Funnel = require('broccoli-funnel');
module.exports = function (defaults) {
let app = new EmberApp(defaults, {
/* ...other stuff */
trees: {
vendor: funnel('vendor', {
exclude: ['./node_modules/single-spa/**/*'],
}),
},
});
/* ...other stuff */
return app.toTree();
};
externals
option to webpack
module.exports = function (defaults) {
let app = new EmberApp(defaults, {
/* ...other stuff */
autoImport: {
webpack: {
externals: ['single-spa'],
},
},
/* ...other stuff */
});
return app.toTree();
};
exclude
optionPractical impact: with multiple instances of single-spa on the page, I have been unable to get navigateToUrl working correctly, so every transition between applications is causing a full page reload.
Hi Guys,
i have the same issue as the last person within this topic:
ember-cli/loader.js#151
I am trying the addon single-spa-ember and I am facing the same issue when adding this in ember-cli-buid.js file.
app.import('node_modules/single-spa-ember/amd/single-spa-ember.js', {
using: [
{ transformation: 'amd', as: 'single-spa-ember' }
]
});
do you have any solution?
I'm using the latest version of ember (5.7)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.