The current Vue implementation does not allow building extensible CMS on it.
This plugin was created to solve this problem.
It parses modification files (.vuem
) in the specified directories and modifies the components at compile time.
Which means that components can be extended with countless add-ons without running code in production to modify it.
The plugin also supports Hot Update mode.
npm i vite-plugin-vue-component-modifications -D
// vite.config.js
import vue from '@vitejs/plugin-vue'
import vueComponentModifications from 'vite-plugin-vue-component-modifications'
import path from 'path'
export default {
plugins: [
// Must be placed before vue() plugin
vueComponentModifications({
dirs: [
path.resolve(__dirname, 'src/modifications'),
],
files: [
// path.resolve(__dirname, 'src/modifications/HelloWorld.vuem'),
],
skip: [
// Modificiations will not be applied to files with name config.js
// 'config.js',
// Modificiations will not be applied to files in dangerous directory
// /\/dangerous\//,
]
}),
vue(),
],
}
<!-- src/components/HelloWorld.vue -->
<script setup>
defineProps({
msg: {
type: String,
required: true
}
})
</script>
<template>
<div class="greetings">
<h1 class="green">{{ msg }}</h1>
<h3>
You’ve successfully created a project with
<a href="https://vitejs.dev/" target="_blank" rel="noopener">Vite</a> +
<a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>
</h3>
</div>
</template>
<style scoped>
h1 {
font-weight: 500;
font-size: 2.6rem;
position: relative;
top: -10px;
}
h3 {
font-size: 1.2rem;
}
.greetings h1,
.greetings h3 {
text-align: center;
}
@media (min-width: 1024px) {
.greetings h1,
.greetings h3 {
text-align: left;
}
}
</style>
<!-- src/modifications/HelloWorld.vuem -->
<!-- Add new link after Vue 3 -->
<template after="Vue 3<\/a>">
+ <a href="https://example.com" target="_blank" rel="noopener">New Link</a>
</template>
<!-- Extend props to add customMsg prop -->
<script before="msg: {">
customMsg: {
type: String,
default: ''
},
</script>
<!-- Add display of customMsg -->
<template find="{{ msg }}" replace="$S" trim>
{{ customMsg ? customMsg : msg }}
</template>
<!-- Append new css to the style tag -->
<style>
h1 {
font-size: 3rem;
}
</style>
Now the HelloWorld.vue
component will be compiled as follows:
<!-- src/components/HelloWorld.vue with applied modifications -->
<script setup>
defineProps({
customMsg: {
type: String,
default: ''
},
msg: {
type: String,
required: true
}
})
</script>
<template>
<div class="greetings">
<h1 class="green">{{ customMsg ? customMsg : msg }}</h1>
<h3>
You’ve successfully created a project with
<a href="https://vitejs.dev/" target="_blank" rel="noopener">Vite</a> +
<a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>
+ <a href="https://example.com" target="_blank" rel="noopener">New Link</a>
</h3>
</div>
</template>
<style scoped>
h1 {
font-weight: 500;
font-size: 2.6rem;
position: relative;
top: -10px;
}
h3 {
font-size: 1.2rem;
}
.greetings h1,
.greetings h3 {
text-align: center;
}
@media (min-width: 1024px) {
.greetings h1,
.greetings h3 {
text-align: left;
}
}
h1 {
font-size: 3rem;
}
</style>
Allow to specify the pattern for the names of the files to which the modification will be applied.
Default: [modification filename].vue
Under the hood, the plugin creates a regular expression filter from this pattern.
That is, the modification will be applied to all files that match this regular expression (except for files with the .vuem
extension).
Will be applied to files named HelloWorld.vue
:
<file>HelloWorld.vue</file>
Will be applied to files named HelloWorld.vue
in components
directory:
<file>components/HelloWorld.vue</file>
Will be applied to files named HelloWorld.vue
or GoodbyeWorld.vue
:
<file regex>(Hello|Goodbye)World\.vue</file>
Using these tags we can specify the place where the modification will be applied.
These tags have accept attributes:
before
– the tag content will be applied before the content matching the specified regular expression.
after
– the tag content will be applied after the content matching the specified regular expression.
find
– the tag content will be applied instead of the content matching the specified regular expression.
replace
– controls how the matching content will be replaced. The $S
keyword will be replaced with the tag contents.
trim
– if this attribute is present, the tag content will be trimmed before replace.
If the after
, before
and find
attributes are not specified, the tag content will be appended to the end of the corresponding component tags.
Look at the usage example above to see how these tags work.
<!-- src/main.js -->
import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
<!-- src/modifications/mainjs.vuem -->
<file>src/main.js</file>
<script after="mount\('\#app'\)" trim>
.use(SomePlugin);
console.log('Hello from modification!');
</script>
Result:
<!-- src/main.js -->
import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app').use(SomePlugin);
console.log('Hello from modification!');