
How to create a Universal Library for Vue 2 & 3
27 January, 2021
4
4
1
Contributors
branches
and tags
(main
for vue 2.x and next
for vue 3.x) or even having a separate repo to ensure better code isolation.The drawback of this is that you will need to maintain two codebases that double your workload. For small scale libraries or new libraries that want to support both versions, doing bugfix or feature supplements twice is just no ideal. I would not recommend using this approach at the very beginning of your projects.
Create base setup

β’
β’
β’
β’
β’
β’
App.vue
and main.ts
since we mainly are going to work with an index.ts
file.Find a purpose


Hands dirty
counter-number
component under src/components/CounterNumber.ts
using defineComponent
.setup
function returns a render function with a <span>
element holding the counter value. That's intended and will be explained in the Caveates section of the post.main.ts
and the App.vue
to test the new component using npm serve
.Plugin installation
src/index.ts
:createVueCounterPlugin
will allow you to install the plugin via the install
method when using createApp.use()
in your app.app
instance all the components, properties of your library like you see above with app.component('vue-counter', CounterNumber);
options
or utilities
we create a Plugin Symbol to be used along with app.provide
in the install
method where we pass the createVueCounterPlugin itself as a parameter. This might look complicated at the moment, but it's the standard way:src/main.ts
:app.provide
in the plugin install method is that we can inject the plugin options as a dependency later.CounterNumber
component into the src/App.vue
.devDependencies
to your package.json
or they will be included in your library bundle.npm run serve

Animation and composition
CounterNumber
component, but since we talked before about Composition API let's use it for this purpose.useCounter.ts
file under src/composables
and export a function called useCounter
like this:ref
with the value to be animated).anime()
function accepts a lot of parameters to customize the behavior of the animation such as duration, delay, easing, and callbacks like an update that triggers every time the animation updates the target object. The interesting thing is that you can pass as property the same property you want to animate, in this case value
, in the example above will go from 0 to 640. For more info about the animejs API check the docsCounterNumber.ts
component and get the use the count.value
inside the span
like this:Make it customizable
useCounter(props)
function;App.vue
and create some variables to pass to the component as props:useCounter.ts
and pass the props to the anime
instance
Make it universal
vue-demi
comes to the rescue.vue
and @vue/composition-api
to your plugin's peer dependencies to specify what versions you support.vue
to vue-demi
, like so:vue@2
+ @vue/composition-api
or vue@3
based on users' environments.Build config
vue-demi
instead of vue
and set it as a global at the build moment. Because the rollup.config.js
is quite large, here is the link to it at the example repo.createConfig
make sure you have vue-demi
set in the property globals like this:script
in the package.json
and the paths for the package builds:Caveats
vue-demi
is rather for vue plugins that don't rely too much on rendering components because Vue 2 and Vue 3 render functions are quite different and the breaking changes between both, i.e. v-model
on a component expecting differently named events in Vue 2 vs 3 (Γ¬nput vs update:modelValue
)..ts
file instead of a .vue
file. For this example library, it will not affect the end result but it's something you need to take into consideration.Vue Demi
to help distinguishing users' environments and to do some version-specific logic.isVue2
isVue3
