Let’s say you have a well-developed app written in Vue. It’s pretty big and has multiple teams working in the code base for both maintenance and feature development. Now, let’s say you need to include that app in an Angular app and you want to avoid transposing the Vue app to Angular. This recently occurred on one of our projects. The task was to incorporate a Vue.js component into an existing Angular app. Several hang-ups eventually lead to rewriting the Angular piece in Vue. The following walkthrough is to create a proof of concept to demonstrate that adding a Vue component to an Angular app is possible
I’ll be using a premade Vue Calculator to add to an Angular Tour of Heroes app. These should serve well enough as stand–ins for the real-world problem. I’ll be using VSCode throughout, however, any text editor ought to do.
The first step is to take inventory of the apps we’ll be using. To do that I’ll pull the calculator repo down locally and install all dependencies.
Now that the app is local and dependencies installed, I’ll check it out by serving the Vue app.
Then navigate to http://localhost:8080 in the browser.
This step strictly speaking isn’t necessary, however, should something go wrong later on it’s good to know we at least started with functional components.
Now you can build this Vue app as a web component. To do this, I’ll be modifying the npm scripts located in package.json. Open package.json in VSCode and copy the build script. Paste it directly below the copied build script and change the name, I’ll be naming mine build-wc to signify that it builds a web component. Next, I’ll prepend some flags to the build-wc script.
I can now see a /dist directory with several files.
I’ll install and use the npm package to serve this up and view the web component in the browser.
Now I can open the browser and navigate to http://127.0.0.1:8080/demo.html.
Opening the developer tools in Chrome and viewing the Elements tab reveals the custom <my-vue-calc></my-vue-calc> mentioned earlier; I’ll include the web component the same way when I get to the integration. For now, you can once again see the calculator working as normal. You may notice that the calculator looks slightly different from the first time the app was served. This is due to the app having been built as a web component with Calculator.vue as the entry point. This demonstrates how styling works within Vue apps. In App.vue, the calculator I am using has a style block with several styles added to the #app selector. However, since I built only the Calculator component of the larger app, I don’t get the styles from App.vue. For demo purposes, I’ll ignore the text alignment and font colors of the number keys. There are several gotchas when dealing with web-components so check out the Vue CLI docs for additional info.
Now that I am satisfied with the results of building the Vue web component I’ll pull down the Angular app to which I’ll be adding the calculator.
And just like before, I’ll install dependencies.
I was having conflicts with the node-sass package and the version of node I had installed, v12.9.1. Using , I changed the current version of node to v11.15.0 which solved that problem. Once the app is cloned and dependencies are installed, I served the app, again, to ensure that it’s working prior to any changes I make. To accomplish this I ran the following in the root directory of the Tour of Heroes app.
Now that the app is working I added the custom web component html tag to index.html.
I’ve added the ‘TEST’ text as a sanity check. Since the web component isn’t defined yet, the tag defaults to the functionality of a <div>. Looking at the browser again there is now immediately following the <my-root></my-root>.
So far so good.
Having modified angular.json you will likely have to stop and restart the server for the changes to be picked up and compiled. With that, the angular app should rebuild itself and refresh the webpage and the calculator should appear at the bottom.
Well… sort of… this is a very simplistic example and implemented in the simplest way. What if I want the web component in one of the angular components? Doing this would break up the source code a bit more and perhaps allow for lazy loading of the components. I like the idea of having a calculator on the individual hero detail pages. To achieve this, I’ll remove the custom element tag from index.html and move it to the bottom of app/hero-details.component.html. Navigating to a hero details page, right away a console error appears.
The CUSTOM_ELEMENTS_SCHEMA tells angular that you will be using elements that are neither Angular components nor directives in the app, check out the Angular Docs for additional info. The ‘TEST’ text now appears on the hero details page.
And like magic once more!
In summary, the example in this walkthrough is absolutely contrived. I could have just as easily brought a native angular calculator app into the Tour of Heroes. However, there is no need for any calculator Vue or otherwise where I’ve added it. This walkthrough is to demonstrate the capability of adding a large well maintained Vue app to an Angular app while avoiding rewrite of the Vue app and the additional maintenance of a new code base. There may be caveats that make this solution unworkable for your application, so use your best judgment. The Angular and Vue docs are an excellent resource for additional information on these topics and many more check them out here and here.
Angular Docs. (2019, September 19). Retrieved from Angular.io: https://angular.io/docs
Butler, K. (2019, September 24). Vue Calculator. Retrieved from GitHub: https://github.com/kylbutlr/vue-calculator
Papa, J. (2019, September 24). Angular Tour of Heroes. Retrieved from GitHub: https://github.com/johnpapa/angular-tour-of-heroes
Vue CLI Docs. (2019, September 19). Retrieved from Vue CLI: https://cli.vuejs.org/guide/