DEV Community

Fima Taf
Fima Taf

Posted on • Updated on

Including Vuejs application in another web application (with vue-cli >3 and Vite)

Update:

Scroll to the bottom of the page if you want to achieve the same with Vite.

Recently I've got a task at my current company to write a small vue application (1 page only) and inject it into an existing legacy project (JSP in that case - I know it's old and ugly, but sometimes it's part of the job...).
I've been told that there is already a vue application that is being injected into the legacy application and it is working pretty nice, so I thought to my self 'Lets see how they configured it there, and use the same way to implement the new app'.
And then I realized that's not gonna work because the existing vue application was created 2 years ago and it was probably created with vue-cli 1 or 2 with all the 'pure' webpack configurations, while I am using vue-cli 3 in the new application (which has the vue.config.js file instead all the previous webpack config, and the other app has too much custom webpack configuration that it became too messy).

After I've searched the web for a solution for this problem, I didn't found something that solved my problem. Finally I've managed to solve it and I wanted to share it so maybe it'll help to someone else.

Overview

Vue is by default using the SPA (What is SPA?) approach which in this case is an advantage.
This example is probably not gonna work with SSR approach (What is SSR?).

After running npm run build command, you'll have all the generated files inside the dist folder.
In our case the generated index.html won't be used because we are going to include our vue application in another html file.
The files that we will use are app.[hash].js and chunk-vendors.[hash].js.
These 2 files are enough for vue to work, the app file is gonna import all the others files (js/css/etc..) that the application needs in order to work properly.

Including vue inside another app

1) Move the generated files:

As I mentioned before vue is by default using the SPA approach, so basically what we need to do is to take the content of the generated dist folder and put it somewhere in the existing app. (Don't forget to remove the index.html)
It is important to keep the content order as it (don't move the js files from the js folder or the css files because the app file will import the other files relative to his location).

2) Let the existing app to import vue app files:

Choose the html file in which you want the vue app to be included, and add the following:

<div id="app"></div>
<script src="js/app.[hash].js"></script>
<script src="js/chunk-vendors.[hash].js"></script>
Enter fullscreen mode Exit fullscreen mode

Make sure that the scripts will be loaded after vue's root div (<div id="app"></div>) - If the scripts will be loaded before the root div, the vue application won't work.

Basically this is it, if you run your existing application, your vue app will work inside the html page that you've chosen to include it in.

Extras

Running on local environment

Of course before building the vue app you'll want to develop and test your vue app on your local environment.
In order to do that, you just need to replace the path of the js files at the html file to:

<script src="http://localhost:8080/js/app.js"></script>
<script src="http://localhost:8080/js/chunk-vendors.js"></script>
Enter fullscreen mode Exit fullscreen mode

Notice that when running the vue app at dev mode it doesn't use the hash at the file name, the hash is being used only when building the app for production.

Import the files from external source

In some cases you'll want to keep the build files of the vue app in a different location and configure your existing app to loaded it from an external source (your-domain.com, AWS S3, Azure Blob, etc...).
There is a great webpack plugin that will help you with that -
webpack-require-from

Example:

If you have some server that is running on the domain your-cool-domain.com and this server will hold the vue app files, you can add a global variable at your existing app:

<script> window.vueAppSrc = "https://your-cool-domain.com/files/" </script>
Enter fullscreen mode Exit fullscreen mode

Now in your vue app install the plugin npm install webpack-require-from -D.
Then in the vue.config.js file add the following:

const WebpackRequireFrom = require('webpack-require-from')
module.exports = {
  chainWebpack: config => {
    config.plugin('require-from').use(WebpackRequireFrom, [{ variableName: 'vueAppSrc' }])
  }
}
Enter fullscreen mode Exit fullscreen mode

Now all the files of your vue app will be loaded from the url you've set in the global variable. (https://your-cool-domain.com/files/app.[hash].js)

Why there are 2 'base' files and not only 1?

Until webpack v4 we didn't had the chunk-vendors.[hash].js file, and all the third party modules were inside the app file, but since webpack v4 (vue-cli 3 is using webpack v4) webpack is splitting the app and the third party modules into different files by default for a better performance.

Can I reduce it to 1 file only?

Yes, it is possible by adding the following option into your vue.config.js file:

module.exports = {
  configureWebpack: config => {
    config.optimization.splitChunks = false
  }
}
Enter fullscreen mode Exit fullscreen mode

This configuration will move the whole content of chunk-vendors file inside the app file (just like before webpack v4).
This option will have effect on the performance, so take it in count.

Vite

I've wanted to achieve the same thing with Vite, but because Vite's production build is based on rollup (which works different from webpack - you can learn more about it Here) I've created a plugin for the same issue:

vite-plugin-loading-script is a vite plugin for wrapping and loading the generated files/assets with a single script into the DOM instead of index.html.

You can learn about the plugin in the Docs Here.

The generated file will appear in the app's dist folder - app.[hash].js.

Conclution

It is pretty easy to include (or inject) a vue application into another web application.
But keep in mind that there might be some other problems that I didn't tackled in my case so it's not perfect, but still might be useful to someone else.

Hope it'll help you (at least partially) :)

Top comments (1)

Collapse
 
jasonhjohnson profile image
Jason

Thanks for this article! Am I able to see a complete example of the rollup solution?