Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: how to render an entire application as custom element in another apps #16

Open
billyjov opened this issue Apr 13, 2021 · 12 comments
Labels
bug Something isn't working

Comments

@billyjov
Copy link

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

@billyjov billyjov changed the title [Documentation] How to render an entire application as custom element in another apps (e.g) docs: how to render an entire application as custom element in another apps Apr 13, 2021
@billyjov
Copy link
Author

@alexlafroscia @Ravenstine any advice on this ?

@Ravenstine Ravenstine added the bug Something isn't working label Apr 14, 2021
@Ravenstine
Copy link
Owner

@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.

@billyjov
Copy link
Author

@Ravenstine what do you mean with

the tests are only testing apps that have an owner

?

@Ravenstine
Copy link
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:

Screen Shot 2021-04-14 at 8 21 11 AM

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.

@billyjov
Copy link
Author

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.

@Ravenstine
Copy link
Owner

@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

@billyjov
Copy link
Author

@Ravenstine i tried this and got following by importing vendor.js and ember-app.js inside my react app after a ember build command.

2021-04-19 23_10_45-

Am i missing something ?

Here is the repository where i gave a try.

https://github.com/billyjov/ember-react-microfrontend

@Ravenstine
Copy link
Owner

@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:

billyjov/ember-react-microfrontend@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:

billyjov/ember-react-microfrontend@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:
billyjov/ember-react-microfrontend@master...Ravenstine:master#diff-7739ef01a01d2fec2b9c7a40af453f92771007f509619e2c9a46917e5c90322a

Not required, but I also added the links to the CSS files:
billyjov/ember-react-microfrontend@master...Ravenstine:master#diff-e3dd9433216572a204d2ab589ccf291c89fc1a72de4e69ead4299b05d62eef24

All those changes give me this:
Screen Shot 2021-04-19 at 4 54 12 PM

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.

@billyjov
Copy link
Author

billyjov commented Apr 20, 2021

Thanks for the explanations.. its works correctly. I will go a little deeper in my example . Thanks :)🎉

@billyjov
Copy link
Author

billyjov commented Apr 20, 2021

@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 ?

@Ravenstine
Copy link
Owner

Ravenstine commented Apr 20, 2021

@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)

@billyjov
Copy link
Author

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants