TL;DR
A 5 minute read? Who has time for that amiright? You can create a microservice with Vue.js and dress it up like a WordPress plugin. Here's a working example of what I'm talking about - https://github.com/stevewhitmore/vue-wordpress-integration-starter
Background
I recently came across a situation where I had to add some fairly advanced frontend functionality to a WordPress website that I manage. I had a couple options that came to mind right away:
- Create a custom theme template and shoehorn some jQuery in there to get the job done.
- Find a plugin that does something similar and shoehorn some jQuery in there to get the job done.
- Do either option 1 or 2 but with vanilla JS because even though it's installed by default for WordPress you really don't need jQuery anymore.
In my experience choosing one of these three options is usually how custom functionality gets added to an otherwise established WordPress installation/theme.
Options 1 and 2 are out the window for me by default nowadays but unfortunately option 3 doesn't work so well when you have a custom business need and complicated logic that goes into the functionality. Applications written in vanilla JS don't scale super well which is why we have frameworks like Angular, React, and Vue among others.
Fortunately for us Vue plays very nicely with existing JavaScript code. I realized I could create a microservice in Vue and drop it into my WordPress installation as a plugin.
Surely someone else has had this same exact need as me, I thought. I'll find something on DEV.to or Medium or something where somebody figured this out already and I'll just piggyback off of that. Well past me soon found out how wrong he was. Yes there was some documentation out there but I couldn't find anything where somebody laid out everything for me step by step. Sometimes I like figuring things out. Sometimes I don't have the time, motivation, or energy for such tomfoolery. I'm lazy by nature and in most cases being lazy works to our advantage as developers.
I didn't have the luxury of being lazy in this scenario and I had to piece it together. That is why, dear reader, I extend to you this gift of not-having-to-because-the-answer-is-out-there-already. You're welcome.
Step 1: Make the Vue app
A good microservice is decoupled from the code it interacts with. Create a new Vue app outside of your WordPress codebase. I really like their CLI feature so I'd recommend getting that installed if you don't have it already.
npm i -g @vue/cli
Once that's successfully done you'll want to create the Vue project.
vue create my-awesome-new-app
Follow the prompts and get a basic placeholder app generated. This article isn't really about how to create a Vue app via their CLI but their docs are pretty helpful with this topic.
Now you can work on developing the application outside of WordPress and get it working independently. Once it's in a place where you want to start pulling it into your WordPress site you can move onto the next step.
Step 2: Do a Bit of Folder Restructuring
From the root of your newly created Vue project create another folder called app
. Put everything from the root of your project in that folder. Next make two new folders: plugin
and inside that whatever the name of your app is. In my case it's plugin/my-awesome-new-app
. It should look something like this:
Step 3: Modify the build script
We're making this app a WordPress plugin. That plugin needs to have a copy of the executables for this app so we'll update the build
script in our package.json
file to do the extra step of copying the dist folder to our new plugin folder.
"build": "vue-cli-service build",
becomes
"build": "vue-cli-service build && cp -r ./dist ../plugin/my-awesome-new-app",
Now when you run npm run build
you'll see something like the following:
So now you've got the following contents in your project:
|-- app
|-- [+] dist
|-- [+] node_modules
|-- [+] public
|-- [+] src
|-- .gitignore
|-- babel.config.js
|-- package-lock.json
|-- package.json
|-- README.md
|-- plugin
|-- my-awesome-new-app
|-- [+] dist
Step 4: Create the Plugin File
Now comes the part where we meld our shiny new Vue app into a WordPress plugin. Create a php file in your /plugin/my-aweseome-new-app
folder. You'll want the file name to be the same as the plugin. In this case it's my-awesome-new-app.php
. Here's a revised version of the folder structure table above:
|-- app
|-- [+] dist
|-- [+] node_modules
|-- [+] public
|-- [+] src
|-- .gitignore
|-- babel.config.js
|-- package-lock.json
|-- package.json
|-- README.md
|-- plugin
|-- my-awesome-new-app
|-- [+] dist
|-- my-awesome-new-app.php
Now you'll want to fill out the new php file with code that
- Provides metadata about the plugin through the comments at the top of the file
- Registers and enqueues the styles and minified javascript for the Vue app
- Creates a shortcode to insert into your WordPress site
It'll look something like this -
<?php
/**
* Plugin Name: My Awesome New App
* Plugin URI: https://yourdomain/wherever-you-keep-the-app-readme-file
* Description: Some great app that I made and it's so great it'll make your life great!
* Version: 1.0.0
* Author: Steve Whitmore
* Author URI: https://stevewhitmore.gitlab.io
*
* Be sure to rename the folder this file is in and this file to match what your plugin will be called. The names must be the same so WordPress knows where to look.
*/
function load_vuescripts() {
wp_enqueue_style( 'vue_wp_styles', plugin_dir_url( __FILE__ ) . 'dist/css/app.2cf79ad6.css' );
wp_register_script( 'vue_wp_compiled', plugin_dir_url( __FILE__ ) . 'dist/js/app.010d7631.js', true );
wp_register_script( 'vue_wp_dependencies', plugin_dir_url( __FILE__ ) . 'dist/js/chunk-vendors.1be0eeb0.js', true );
}
add_action( 'wp_enqueue_scripts', 'load_vuescripts' );
function attach_vue() {
wp_enqueue_script( 'vue_wp_compiled' );
wp_enqueue_script( 'vue_wp_dependencies' );
return "<div id='app'></div>";
}
add_shortcode( 'vue_wp', 'attach_vue' );
// Add the shortcode [vue_wp] to any page or post.
// The shorcode can be whatever. [vue_wp] is just an example.
?>
Note: Each time you make changes to your Vue app and build, the files will have newly hashed file names to help with caching issues. Be sure to update your php file with the new file names every time you build as needed to see your changes reflected.
Step 5: Upload and Activate
Upload the contents of /plugin/
to your WordPress installation's /wp-content/plugins
folder. Log into your WordPress admin panel and navigate to the Plugins section. You should see your new plugin waiting to be activated.
Step 6: Insert the Shortcode
Once activated you can either insert the shortcode through template code or by adding it to a page
<?php
/**
*
* Template name: Some Template
*
*/
get_header(); ?>
<section id="main">
<h2>Some Page About Something Or Other</h2>
<?php echo do_shortcode("[vue_wp]"); ?>
</section>
<?php get_footer(); ?>
or
Step 7: Rejoice
You did it!
That wasn't so bad was it? If it was please feel free to let me know how I can make this tutorial easier to follow and I'll get it updated. Otherwise please don't hesitate to ask me any questions!
Top comments (5)
Unfortunately, your solution doesn't work for me, because
npm run build
produces files with random names, so that also won't work:For example there is no
app.css
file onlyapp.dsf665lkfg.css
Thanks for pointing this out. I originally wrote this article a year and a half ago so it's possible that may not have been the case at the time. Or it was an oversight. Either way I've updated the article with a more accurate example and a note about the changing file names below it.
In history mode we need to modify .htaccess file so when you refresh it does not return a 404 error. v3.router.vuejs.org/guide/essentia...
What would be the rule in a plugin situation
Sorry I didn't see this until now. The intention here is to embed a micro-frontend into an existing WordPress page, so I don't think you'd have any need for using routes. What you're asking about may be more relevant for a full Vue SPA.
Hi Stephen,
I've been looking for that explanation like for more than 7 days.
It worked like a CLOCK!
Many many thanks for that!!!
For whoever might be reading this - DON'T SKIP THE DETAILS!