Vue In-Browser Compiler
The `vue-inbrowser-compiler` package allows for the compilation of Vue Single File Components (SFCs), pseudo-JSX, and plain Vue app definitions directly within the browser environment. It is primarily designed for applications requiring dynamic, user-editable Vue components, such as live code editors, interactive documentation (e.g., Vue Styleguidist), or component playgrounds, eliminating the need for server-side compilation. The current stable version is 4.72.4. Based on its frequent patch and minor updates within the `vue-styleguidist` monorepo, it maintains an active development and release cadence. Its key differentiator is the ability to perform full Vue component compilation dynamically on the client-side, integrating with tools like Buble for JavaScript transpilation, providing a flexible and immediate feedback loop for component development.
Common errors
-
TypeError: h is not a function
cause This error typically occurs when attempting to compile or render JSX without correctly configuring the JSX pragma or providing the Vue-specific `h` (createElement) function.fixEnsure that your `compile` call's Buble configuration includes `{ jsx: '__pragma__(h)' }` and that the `new Function()` call for the compiled script is invoked with `func(adaptCreateElement)`. -
Vue template compilation error: Property or method "myVariable" is not defined on the instance but referenced during render.
cause When using pseudo-JSX (HTML-like syntax at the top level of the code string), variables declared outside the template are not automatically injected into the component's `data` option.fixManually move variables intended for reactive use within the component's template into the `data` property of the returned component object. For more complex scenarios, consider using the `new Vue({...})` or full Single File Component syntax. -
Uncaught SyntaxError: Unexpected token '<' (at line X, column Y)
cause This error arises when you try to execute a raw Vue template string or an uncompiled Single File Component string directly via `new Function()`. JavaScript's `new Function()` expects valid JavaScript code, not HTML-like templates.fixAlways pass your raw Vue component code through the `compile(code, config)` function first. The `compile` function will return an object containing `script` and `style` strings, where `script` is the valid JavaScript string ready for `new Function()`.
Warnings
- gotcha The package uses Buble for JavaScript transpilation, not Babel. Buble's configuration (`BubleConfig`) is less feature-rich than Babel's and may not support the very latest ECMAScript proposals. Users familiar with Babel should note this distinction.
- breaking Earlier versions of `vue-inbrowser-compiler` (prior to 4.72.4) had compatibility issues with Vue 3.3.2 and potentially newer Vue 3 features, especially regarding `defineEmits` syntax. This could lead to parsing errors or incorrect component behavior.
- gotcha When using JSX syntax within the compiler, explicit configuration is required. The `jsx` option in `BubleConfig` must be set, and the `adaptCreateElement` helper must be passed to the compiled function.
- gotcha Styles within a compiled Single File Component (SFC) that use the `scoped` attribute are transformed during compilation. However, if you add raw CSS or need custom scoping, you might need to use `addScopedStyle` manually to inject them into the DOM.
Install
-
npm install vue-inbrowser-compiler -
yarn add vue-inbrowser-compiler -
pnpm add vue-inbrowser-compiler
Imports
- compile
const { compile } = require('vue-inbrowser-compiler')import { compile } from 'vue-inbrowser-compiler' - isCodeVueSfc
const isCodeVueSfc = require('vue-inbrowser-compiler').isCodeVueSfcimport { isCodeVueSfc } from 'vue-inbrowser-compiler' - adaptCreateElement
import adaptCreateElement from 'vue-inbrowser-compiler/adaptCreateElement'
import { adaptCreateElement } from 'vue-inbrowser-compiler' - addScopedStyle
const { addScopedStyle } = require('vue-inbrowser-compiler')import { addScopedStyle } from 'vue-inbrowser-compiler'
Quickstart
import { compile, addScopedStyle } from 'vue-inbrowser-compiler';
import { createApp } from 'vue'; // Assuming Vue 3 for a modern example
const sfcCode = `
<template>
<div class="hello" :style="{ color: dynamicColor }">
<h1>Compiled Vue Component</h1>
<button @click="changeColor">{{ msg }}</button>
</div>
</template>
<script>
export default {
data() {
return {
msg: 'Click Me!',
dynamicColor: '#900'
}
},
methods: {
changeColor() {
this.dynamicColor = this.dynamicColor === '#900' ? '#009' : '#900';
}
}
}
</script>
<style scoped>
.hello {
text-align: center;
font-family: sans-serif;
}
button {
padding: 10px 20px;
border: none;
border-radius: 5px;
background-color: #4CAF50;
color: white;
cursor: pointer;
margin-top: 15px;
}
</style>
`;
function getRunnableComponent(code) {
const compiled = compile(code, {
target: { ie: 11 } // Buble configuration for transpilation
});
// Add compiled styles to the document with a unique scope
// The 'scoped' attribute in the SFC is handled by vue-inbrowser-compiler itself.
// addScopedStyle is for when you manually scope or have global styles to add.
// For SFCs, compiled.style already contains scoped styles.
const styleTag = document.createElement('style');
styleTag.textContent = compiled.style;
document.head.appendChild(styleTag);
// Execute the script and return the component definition
const func = new Function(compiled.script);
return func();
}
// Mount the compiled component
const appDiv = document.createElement('div');
appDiv.id = 'app';
document.body.appendChild(appDiv);
const componentDefinition = getRunnableComponent(sfcCode);
const app = createApp(componentDefinition);
app.mount('#app');
console.log('Vue component compiled and mounted to #app');