2
votes

I think this is a very unusual use case, and I'm not talking about dynamically requiring components with webpack.

I want to be able to deploy "Apps" as Vue components on a completely different backend, so that the backend can return full .vue files over an API. The structure of the backend is irrelevant. So I need a way in my Vue application to achieve the following:

  • User clicks on an "app" name in the frontend Vue application
  • "app" name is async-requested at the backend
  • backend returns a .vue SFC file, with HTML, JS and CSS in it
  • frontend compiles the file to a Vue component with template and functionality
  • frontend inserts the component in the view, and the component can interact with the rest of the application (Vuex store etc.)

I found v-runtime-template which seems to be the solution for templates. But this doesn't include the JS part, does it?

Additional: I think I'm trying something like VueJS Dynamic Components, but the request URL has to be set dynamically.

2
The problem that I see here is that having the front-end interpret the raw .vue file means the front end has to interpret any template syntax that that Vue file has including less, scss, pug, and whatever else templating languages your Vue file might utilize. I think you still want the backend interpreting the file, but for the front-end to consume plain JSON definition of the Vue component. That's what Webpack is doing behind the scenes anyway. - zero298
I am free to extend the backend as I want, so compiling pug, sass etc. in the backend would be possible. But how would a plain JSON definition of a Vue component look like, especially the methods and computedProps? - Giacomo Voß

2 Answers

3
votes

Markus Oberlehner has an article that I think addresses your problem. The solution is through a externalComponent(url) function that takes the place of an import() function. I've copied Markus' function here for easy reference:

// src/utils/external-component.js
export default async function externalComponent(url) {
  const name = url.split('/').reverse()[0].match(/^(.*?)\.umd/)[1];

  if (window[name]) return window[name];

  window[name] = new Promise((resolve, reject) => {
    const script = document.createElement('script');
    script.async = true;
    script.addEventListener('load', () => {
      resolve(window[name]);
    });
    script.addEventListener('error', () => {
      reject(new Error(`Error loading ${url}`));
    });
    script.src = url;
    document.head.appendChild(script);
  });

  return window[name];
}

According to the article, you can use the externalComponent() helper function to load external components pretty much the same way as we are used to with import().

1
votes

You might get by using http-vue-loader. It's not generally recommended for production, but your use case might make it appropriate. Obviously there will be some limitations (e.g. importing other modules)