Split Vue.js components into multiple files

  • img
    Ashish Kurian Thomas
  • April 29,2019

One of the most common things, people coming from Angular find annoying about Vue.js is that a component is one .vue file. In this short article we'll take the template and style parts from the .vue file and move it to .html and .css files respectively.

Let's start

Install the vue cli with $ sudo npm i -g @vue/cli, if you don't have vue installed locally. Now create a project with $ vue create my-awesome-app. Wait for a few seconds to let the cli do its thing.

Let's examine the project directory

my-awesome-app
├── babel.config.js
├── node_modules/
├── package.json
├── package-lock.json
├── public/
├── README.md
└── src/
    ├── App.vue
    ├── assets/
    ├── components/
    │   └── HelloWorld.vue
    └── main.js

In the src/components folder, we see our one component HelloWorld.vue. Run the app with $ npm run serve and our app's dev server is live on http://localhost:8080.

Restructuring

  1. Let's create a folder in the components directory
$ mkdir src/components/HelloWorld
  1. Create the style and script files
$ touch src/components/HelloWorld/HelloWorld.html
$ touch src/components/HelloWorld/HelloWorld.css
  1. Move over the HelloWorld.vue to the HelloWorld component folder. We'll see that the app breaks as it can't find HelloWorld.vue.
$ mv src/components/HelloWorld.vue src/components/HelloWorld/HelloWorld.vue
  1. Open up App.vue and change the import statement
import HelloWorld from './components/HelloWorld/HelloWorld.vue'
  1. Open up the HelloWorld.vue file. There are 3 parts to a .vue file, which are
    <template>, <script> and <style> sections.

  2. Move the content of the style section to the HelloWorld.css file.

$ cat src/components/HelloWorld/HelloWorld.css

h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
  1. Add an src attribute to the <style> tag, to link to the new .css file.
$ cat src/components/HelloWorld/HelloWorld.vue

. . .

<style scoped src="./HelloWorld.css">
</style>

  1. Lets do the same for the .html file. Move the content with in the <template> tag into the HelloWorld.html file.
$ cat src/components/HelloWorld/HelloWorld.html

<div class="hello">
. . .
</div>
  1. Add an src attribute to the <template> tag, to link it to the new .html file.
$ cat src/components/HelloWorld/HelloWorld.vue

<template src='./HelloWorld.html'>
</template>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped src="./HelloWorld.css">
</style>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
};
</script>
  1. Our app should be working fine now. However, the import statement in App.vue could be better. Change that to
import HelloWorld from './components/HelloWorld'
  1. Make an index.js file in the component's folder.
$ touch src/components/HelloWorld/index.js
  1. Add the following into index.js
import HelloWorld from './HelloWorld.vue';

export default HelloWorld;

The app will be working as it should now. Our updated project
structure is now

my-awesome-app
├── babel.config.js
├── node_modules/
├── package.json
├── package-lock.json
├── public/
├── README.md
└── src/
    ├── App.vue
    ├── assets/
    ├── components/
    │    └── HelloWorld/
    │        ├── HelloWorld.html
    │        ├── HelloWorld.vue
    │        ├── HelloWorld.css
    │        └── index.js
    └── main.js

With that we have split our Vue components into different files.

~Happy Hacking

Subscribe to newsletter
Need more tech news? Tune in to our weekly newsletter to get the latest updates