ember-custom-elements
ember-custom-elements copied to clipboard
docs: how to render an entire application as custom element in another apps
Hi, thanks for this addon. I want to how i can build my app in other to render this in another react app. I did following like described in the README
app.js
:
import Application from '@ember/application';
import Resolver from 'ember-resolver';
import loadInitializers from 'ember-load-initializers';
import config from 'ember-app/config/environment';
import { customElement } from 'ember-custom-elements';
@customElement('ember-app')
export default class App extends Application {
modulePrefix = config.modulePrefix;
podModulePrefix = config.podModulePrefix;
Resolver = Resolver;
// needed for custom elements
autoboot = false;
}
loadInitializers(App, config.modulePrefix);
Then i ran ember build
.
Import dist/vendor.js
and dist/ember-app.js
in my react app does not work to render <ember-app></ember-app>
.
Is there a way to archieve this using the addon?
Thanks in advance
@alexlafroscia @Ravenstine any advice on this ?
@billyjov Looks like a bug to me. I think it wasn't caught before because the tests are only testing apps that have an owner. (honestly, I couldn't tell you exactly why that is).
I'm actually working right now on rolling out a new version with some fixes and improvements, so I will see if I can work this in.
@Ravenstine what do you mean with
the tests are only testing apps that have an owner
?
@billyjov If you look at the tests that test the use case of the decorator on an application class, it's actually registering the application class with the owner inside the test. This is on purpose since it's a conceivable use case where someone has an Ember app that imports/implements multiple other apps through custom elements, although I imagine that's a rare use-case. It was intended that your use case be supported as well, but I think I may have regressed it a while ago since there's no test that tests the use on application classes that don't have an owner associated with them.
In other words, it may be possible to get the existing version of this add-on to create a custom element to render an Ember app if it's owned by another app that has been booted(so that initializers are performed) but hasn't started routing (so that it doesn't render into the body element). However, I don't exactly recommend it and I couldn't guarantee whether that would work for what you want to do.
Last night I did some work to bring back this functionality (for apps that aren't owned by another container) so that it would support your use-case:
I've got to do some more work to make sure it's well-tested and solid, but in the next day or so I'll make a pre-release that will include this and other improvements.
Thanks.
Last night I did some work to bring back this functionality (for apps that aren't owned by another container) so that it would support your use-case
Can you pls release a new version of the addon so that i can try it locally too ? The steps you followed to archieve the result will also be helpful.
Thanks in advance.
@billyjov I've published a pre-release version that has changes that I hope will resolve your issue. If you could try installing [email protected]
and let me know if it works for you, it would be highly appreciated. Based on my own testing, it should work with your implementation that you've described.
https://www.npmjs.com/package/ember-custom-elements/v/2.1.0-1
@Ravenstine i tried this and got following by importing vendor.js
and ember-app.js
inside my react app after a ember build
command.
Am i missing something ?
Here is the repository where i gave a try.
https://github.com/billyjov/ember-react-microfrontend
@billyjov So there's a few things that your build setup needs to do (outside the bounds of the add-on) to get it to work.
The problem you're seeing is due to your React app not being able to serve the vendor.js
and ember-app.js
files because they are outside of its public/
directory. You can handle this a few different ways, but I'm not that experienced with React so I'm not exactly sure what the common way to handle this is.
In a fork I made of your repo, you can see I created a Makefile with some steps that force the necessary files to be located in your React public/
folder:
https://github.com/billyjov/ember-react-microfrontend/compare/master...Ravenstine:master#diff-76ed074a9305c04054cdebb9e9aad2d818052b07091de1f20cad0bbac34ffb52
Basically, it just builds the Ember app, copies the dist/
contents into the public/
, directory, and runs the React server. I'm sure there's a much better way to accomplish this, but at least it allows your React server to serve the Ember files. Someone better acquainted with React might be able to help you in this area.
Another thing that needs to happen (which I may add to the add-on documentation) is to tell Ember CLI to bundle the app config rather than place it in a <meta>
tag:
https://github.com/billyjov/ember-react-microfrontend/compare/master...Ravenstine:master#diff-10b286d8090b2d4154f505a29e7f80da7ab948813c06aabf235f51f8102cbc0f
You'll also notice I disabled fingerprinting the built Ember assets, since that makes it difficult to copy and serve them. It's definitely feasible to try and preserve these fingerprints, or perhaps generate your own, but for now I've left them out for simplicity's sake.
I also had to uninstall ember-web-component-container
because it was interfering:
https://github.com/billyjov/ember-react-microfrontend/compare/master...Ravenstine:master#diff-7739ef01a01d2fec2b9c7a40af453f92771007f509619e2c9a46917e5c90322a
Not required, but I also added the links to the CSS files: https://github.com/billyjov/ember-react-microfrontend/compare/master...Ravenstine:master#diff-e3dd9433216572a204d2ab589ccf291c89fc1a72de4e69ead4299b05d62eef24
All those changes give me this:
Hopefully this helps you. Again, I pretty much know nothing about how React apps typically bundle things like this. This add-on pretty much leaves that detail up to whomever is using it in this way, but I will add some of these details to the documentation, which I will be working on reorganizing soon.
Thanks for the explanations.. its works correctly. I will go a little deeper in my example . Thanks :)🎉
@Ravenstine I'm not familiar with the ember-cli build system (comming from Angular world). Using Shadow DOM to encapsulate the app is the way i want to try. However its actually difficult because ember-cli create a separate css file. How would you include styles inside the ember-app.js
directly and avoid styles to be override by external styles ? Does ember-cli provides something similar out of the box ?
@billyjov There isn't really a way out of the box to bundle CSS as part of the JS, although it's conceivably possible to create that functionality through an add-on. If you don't mind still having the CSS files be generated and served by the server, one way you could achieve a similar effect is to take the <link>
tags for the CSS out of the react-app/public/index.html
and add them to the top of ember-app/app/templates/application.hbs
without the %PUBLIC_URL%
part. That way you can pass { useShadowRoot: true }
to the customElement decorator, and the Ember app will be invoked inside the shadow root of your custom element and insert those link tags with the styles being isolated. (I tested that so I'm confident that works)
Of course, this requires the CSS files to always be served at the path at which your Ember app is expecting.
If you really want it so that you only need to serve the JS files for the Ember app, we'd have to figure out how to do it through ember-cli-build.js
or by creating an add-on. I don't think it would be tremendously complicated, but it's not something I have muscle memory with. I might be able to investigate that tonight just cuz I'm curious about that myself as well. (from what I could tell last night, there doesn't seem to be any existing add-ons up to that task)
@Ravenstine I found this package https://www.npmjs.com/package/ember-cli-concat that allow to concat all JS files into a single file and all css files into a single file.