Plugins and the Vue app
Sometimes you want something in every component on the page: a global directive such as v-autofocus, a shared component, or an error reporter. In a plain Vue project you would set these up on the app returned by createApp(). Citry creates the Vue app for you, so there is no createApp() call to configure. Use a Vue plugin instead.
Add a Vue plugin
A Vue plugin is an object with an install(app) method. Register it with Citry.vue.use(plugin, ...options). Citry installs it on every Vue app it creates on the page, before the app mounts.
Here a plugin adds a v-autofocus directive:
// static/vue-plugins.js
Citry.vue.use({
install(app) {
app.directive("autofocus", {
mounted(el) {
el.focus();
},
});
},
});
Any template can then use it:
<input v-autofocus />
In install(app) you can:
- register directives with
app.directive()and components withapp.component(); - provide values with
app.provide(). A component reads a provided value withinjectin$component({...}); seeprovideandinject; - set
app.config.errorHandler; see Handle Vue errors; - add
app.config.globalProperties.
Load the plugin file
Load the file in the page's <head> with defer:
<script defer src="/static/vue-plugins.js"></script>
defer makes the file run after Citry's runtime loads and before Citry creates the first Vue app, which is the window in which Citry.vue.use() works.
To add the file to every page from Python, write an extension that adds it to ctx.early_scripts; see Add scripts and styles.
Handle Vue errors
To send errors to your own reporting tool, set app.config.errorHandler in the plugin's install:
Citry.vue.use({
install(app) {
app.config.errorHandler = (error, instance, info) => {
// With a handler set, Citry leaves logging to you.
console.error(error);
// sendToTracker stands for your reporting tool.
sendToTracker(error, info);
};
},
});
When a handler is set, Citry passes each error to it instead of the browser console, so log it there yourself. Errors from Citry's own browser code, such as a failed @c-poll refresh, reach the handler too, with an info text that starts with Citry, as in "Citry @c-poll".
With or without a handler, after an error Citry stops sending server updates to that Vue app. Reload the page to get them again.
Plugin limits
A plugin runs inside a Vue app that Citry has already set up, so a few things work differently from a plain Vue project.
Call use() early
Call Citry.vue.use() before Citry creates its first Vue app. A later call throws an Error, because that app would run without the plugin. The reference lists the other errors, such as passing a value that is not a plugin.
Components need render()
A component registered with app.component() can be used in any template by its name, such as <my-badge>. It needs a render() function written with Citry.vue.h. A template string does not compile in the browser:
Citry.vue.use({
install(app) {
app.component("my-badge", {
props: ["label"],
render() {
const h = Citry.vue.h;
return h("span", { class: "badge" }, this.label);
},
});
},
});
Keep $loading, $error
Citry adds $loading and $error to globalProperties. A plugin that sets either name replaces Citry's version, and $loading() and $error() stop working in every template. Give your properties other names.
One install per Vue app
A page can run several Vue apps, for example when HTML fragments add components to it. The plugin's install runs once for each app, and each app has its own app.provide() values. For one value that every app shares, create it outside install and provide that same object:
// One store for the whole page, created once.
const store = Citry.vue.reactive({ cartCount: 0 });
Citry.vue.use({
install(app) {
app.provide("store", store);
},
});
No mixins
A plugin cannot add a mixin to components, because $component({...}) rejects mixins and extends; see Unsupported options.
Ignored config options
app.config.compilerOptions has no effect, because Citry compiles templates on the server. app.config.warnHandler is never called, because the Vue build Citry loads leaves out Vue's warnings.
A failing install
If the plugin's install throws, that Vue app does not start, and the error shows as a page error.
See also
Citry.vue.usein the browser API reference.- Component options for what
$component({...})accepts. - Limits and errors for what Citry does not support.