Coder Social home page Coder Social logo

Comments (8)

ruleeeer avatar ruleeeer commented on May 20, 2024

I looked at dynamic-system-host/app1/src/App.js, it feels more similar to a component that can switch remote rather than directly giving an interface like GET /api/services, similar to what dynamic-system-host/app1/src/App.js does It can be done, because the implementation of vite-plugin-federation refers to webpack, maybe later we will provide an example, but this may take some time, if you want to build a similar project, I suggest you check out any project host-side dist/index.js in the example directory, they show the initialization process of a remote component, here I attach a part of the example/vue3-demo-esm/layout/dist/assets/index.js file

const remotesMap = {
  'home': {url: 'http://localhost:5001/assets/remoteEntry.js', format: 'esm'},
  'common-lib': {url: 'http://localhost:5002/assets/remoteEntry.js', format: 'esm'},
  'css-modules': {url: 'http://localhost:5003/assets/remoteEntry.js', format: 'esm'}
};
const loadJS = (url, fn) => {
  const script = document.createElement('script');
  script.type = 'text/javascript';
  script.onload = fn;
  script.src = url;
  document.getElementsByTagName('head')[0].appendChild(script);
};
const scriptTypes = ['var'];
const importTypes = ['esm', 'systemjs'];
const metaGet = name => __federation_import(name);
const webpackGet = name => metaGet(name).then(module => () => module?.default ?? module);
const shareScope = {
  'vue': {
    '3.2.23': {
      metaGet: () => metaGet('./__federation_shared_vue.js'),
      get: () => webpackGet('./__federation_shared_vue.js'),
      loaded: 1
    }
  },
  'vuex': {
    '4.0.2': {
      metaGet: () => metaGet('./__federation_shared_vuex.js'),
      get: () => webpackGet('./__federation_shared_vuex.js'),
      loaded: 1
    }
  }
};

async function __federation_import(name) {
  return __vitePreload(() => import(name), true ? [] : void 0);
}

var __federation__ = {
  ensure: async (remoteId) => {
    const remote = remotesMap[remoteId];
    if (!remote.inited) {
      if (scriptTypes.includes(remote.format)) {
        // loading js with script tag
        return new Promise(resolve => {
          const callback = () => {
            if (!remote.inited) {
              remote.lib = window[remoteId];
              remote.lib.init(shareScope);
              remote.inited = true;
            }
            resolve(remote.lib);
          };
          loadJS(remote.url, callback);
        });
      } else if (importTypes.includes(remote.format)) {
        // loading js with import(...)
        return new Promise(resolve => {
          __vitePreload(() => import(/* @vite-ignore */ remote.url), true ? [] : void 0).then(lib => {
            if (!remote.inited) {
              lib.init(shareScope);
              remote.lib = lib;
              remote.lib.init(shareScope);
              remote.inited = true;
            }
            resolve(remote.lib);
          });
        })
      }
    } else {
      return remote.lib;
    }
  }
};

This code shows how to initialize a remote component, note that the logic of loading a remote component generated by webpack is different from that of loading a remote component generated by vite-plugin-federation, because webpack uses iife by default and needs to be loaded using <script src=... > to load them, while for vite-plugin-federation they will be loaded directly using esm's import

from vite-plugin-federation.

foot avatar foot commented on May 20, 2024

Brilliant! Thank you for the quick reply, I'll have a play around w/ the code.

it feels more similar to a component that can switch remote rather than directly giving an interface like GET /api/services

Yes indeed, the webpack example just switches things in and out. It looks it could be adapted into something more generic that could hopefully take a list of remotes from some other source and display them all in a navbar / menu for example.

from vite-plugin-federation.

foot avatar foot commented on May 20, 2024

Code works great for prod!

const RemoteButton = React.lazy(
  // Normal way of loading things
  // @ts-ignore
  // import("remote_app/Button")

  // Use new loader
  () => {
    remotesMap["remote_app"] = {
      url: "http://localhost:5001/assets/remoteEntry.js",
      format: "esm",
    };

    return __federation__
      .ensure("remote_app")
      .then((remote) => remote.get("./Button").then((factory) => factory()));
  }
);

Dev looks a bit more hairy.. 🤔 .

Could we expose the remotesMap for modification by the app code at runtime do you think? I've noticed __federation_shared__ around which I guess needs to be global for the expose code to hook in. Something like globalThis.__federation_remotes_map__ = remotesMap ?

This is a bit hacky. I guess it would be neat to have some runtime lib import { addRemote } from "@originjs/vite-plugin-federation";

from vite-plugin-federation.

foot avatar foot commented on May 20, 2024

Sorry, I guess the "problem" now is how to get shareScope at runtime: (the main thing being the paths to the js code (__federation_shared_vue.js)).

const shareScope = {
  'vue': {
    '3.2.23': {
      metaGet: () => metaGet('./__federation_shared_vue.js'),
      get: () => webpackGet('./__federation_shared_vue.js'),
      loaded: 1
    }
  },
  'vuex': {
    '4.0.2': {
      metaGet: () => metaGet('./__federation_shared_vuex.js'),
      get: () => webpackGet('./__federation_shared_vuex.js'),
      loaded: 1
    }
  }
};

Perhaps we could always set __federation_shared__ in the code generated by vite that could be read at runtime even before trying to import/ensure another remote? There are perhaps hacks here like trying to load a dummy remote first to make sure window/__federation_shared__ is available before loading dynamic remotes..

from vite-plugin-federation.

ruleeeer avatar ruleeeer commented on May 20, 2024

I have something to say about dev mode, because vite does not support adding a bundle in dev mode (actually it is the remoteEntry.js file), so now the dev mode of vite-plugin-federation only supports the host side, the remote side cannot run in dev mode.

Code works great for prod!

const RemoteButton = React.lazy(
  // Normal way of loading things
  // @ts-ignore
  // import("remote_app/Button")

  // Use new loader
  () => {
    remotesMap["remote_app"] = {
      url: "http://localhost:5001/assets/remoteEntry.js",
      format: "esm",
    };

    return __federation__
      .ensure("remote_app")
      .then((remote) => remote.get("./Button").then((factory) => factory()));
  }
);

Dev looks a bit more hairy.. 🤔 .

Could we expose the remotesMap for modification by the app code at runtime do you think? I've noticed __federation_shared__ around which I guess needs to be global for the expose code to hook in. Something like globalThis.__federation_remotes_map__ = remotesMap ?

This is a bit hacky. I guess it would be neat to have some runtime lib import { addRemote } from "@originjs/vite-plugin-federation";

from vite-plugin-federation.

ruleeeer avatar ruleeeer commented on May 20, 2024

It sounds crazy to load the shared before loading the module,Perhaps we need to seriously consider how to achieve this, because in theory we need to determine which shared libraries are used by the component and then load the corresponding shared, it's the Chinese New Year, my reply may be late, don't mind

Sorry, I guess the "problem" now is how to get shareScope at runtime: (the main thing being the paths to the js code (__federation_shared_vue.js)).

const shareScope = {
  'vue': {
    '3.2.23': {
      metaGet: () => metaGet('./__federation_shared_vue.js'),
      get: () => webpackGet('./__federation_shared_vue.js'),
      loaded: 1
    }
  },
  'vuex': {
    '4.0.2': {
      metaGet: () => metaGet('./__federation_shared_vuex.js'),
      get: () => webpackGet('./__federation_shared_vuex.js'),
      loaded: 1
    }
  }
};

Perhaps we could always set __federation_shared__ in the code generated by vite that could be read at runtime even before trying to import/ensure another remote? There are perhaps hacks here like trying to load a dummy remote first to make sure window/__federation_shared__ is available before loading dynamic remotes..

from vite-plugin-federation.

T0miii avatar T0miii commented on May 20, 2024
__federation__ 
do you have an example project for this, im trying to implement the same thing in Vue that looks something like this:

const BataButton = defineAsyncComponent({
  loader: () => {
    remotesMap["bata-lib"] = {
      url: "http://localhost:4173/assets/remoteEntry.js",
      format: "esm",
    };

    return __federation__
        .ensure("bata-lib")
        .then((remote) => remote.get("./BataButton").then((factory) => factory()));
  },
  errorComponent: ErrorComponent,
});

I dont realy know how to get the missing variables remotesMap and federation

from vite-plugin-federation.

ruleeeer avatar ruleeeer commented on May 20, 2024

@T0miii I think the current does not fully provide open remoteMap and __federation ability, perhaps discuss how to achieve this part of the function, this is not a complex function, just I think similar to globalThis.remoteMap such a way too bad taste,and may lead to unknown security problems

from vite-plugin-federation.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.