vue-demi
vue-demi copied to clipboard
it's hard for developer to write a common component with vue-demi
【description】:
I want to try create the same component for Vue2 & Vue3 in the same source code, so I find vue-demi. But.. I have seen some projects likes json-editor-vue. For compact Vue2 & Vue3, I found its source code write render
options for 2 & 3. But i think it's hard for developer to code.
I prefer to code in template
in a sfc file. So i have some idea(We can smooth the difference with Vue2
& Vue3
when we compile components). Can we write a component with setup
& composition-api
in a sfc
. And then when we compile the component, we can use a series of plugins for Vue2
: unplugin-auto-import
, unplugin-vue2-script-setup
, vite-plugin-vue2
, [email protected]
, and plugins for Vue3
: @vitejs/plugin-vue
.
@antfu Maybe u have thought some idea before create this repo. So can u give me some advice or info?
I would suggest directly shipping SFC to npm and let userland plugin to compile it.
I would suggest directly shipping SFC to npm and let userland plugin to compile it.
Thanks for ur reply.
This is also a way to resolve. I think i may find a way to implement .
How about create a monorepo, one package to create SFC, and a package to compile it for Vue2
, a package to compile it for Vue3
. :bowtie:
Use unbuild for shipping the component directly
Thanks! I will use it for my project.
I have the same problem, I prefer to code in SFC syntax too
I'm using v-once
( head to JS tab on sfc playground ) directive on SFC component ( for example Vue component for datatables.net )
I would suggest directly shipping SFC to npm and let userland plugin to compile it.
-
requires to add
"type": "module"
in package.json -
Component must be defined separate
exports
field in package.json ( separate from other compiled files, if component use hook or composable )
Compiled component.vue
vue 2.6 vite-plugin-vue2:
vue 2.7 @vitejs/plugin-vue2 :
vue 3 @vitejs/plugin-vue:
Use unbuild for shipping the component directly
unbuild is good with .ts
defineComponent and composable
, at this time it's not compatible with .vue
files
https://github.com/unjs/unbuild/issues/80
have u find the way use monorepo
to adapt to use vue-demi
for SFC
?
i try to this but when i use vite-plugin-dts
generate d.ts
there still have many compatibility issues.
have u find the way use
monorepo
to adapt to usevue-demi
forSFC
? i try to this but when i usevite-plugin-dts
generated.ts
there still have many compatibility issues.
Hi,
Unfortunately no, I end up using defineComponent
(.ts) way instead of SFC
(.vue) files
for monorepo answer can be yes, but it questions the duty of vue-demi
- packages/
-- vue3
-- vue2
have u find the way use
monorepo
to adapt to usevue-demi
forSFC
? i try to this but when i usevite-plugin-dts
generated.ts
there still have many compatibility issues.Hi,
Unfortunately no, I end up using
defineComponent
(.ts) way instead ofSFC
(.vue) filesfor monorepo answer can be yes, but it questions the duty of vue-demi
- packages/ -- vue3 -- vue2
Yeah, still I am same problem with the questioner, use TS
render way it's hard to my team, we perfer to SFC
more, then will use antfu
says that publish components, use different project v2
, v2.7
, v3
to build it, use git branch to manage it.
this issue also related to this pull-request
https://github.com/vueuse/vue-demi/pull/154
@Hisioni can you share your vue-demi
repo? If it possible
@Hisioni can you share your
vue-demi
repo? If it possible
Of course, in this repository, still have question, i don't know how to config to generate d.ts on every vue version
have u find the way use
monorepo
to adapt to usevue-demi
forSFC
? i try to this but when i usevite-plugin-dts
generated.ts
there still have many compatibility issues.
@Hisioni I have same issue too, I thought generating types only required once with Vue3 as main version in package.json
the error I got when installing vue-demi lib on vue2.7 project I think it was editor problem
Generic type 'DefineComponent' requires between 0 and 11 type arguments.
However, autocomplete props on component only pops up on Vue3 (using Volar)
Found an example for handling type definitions separately :fearful: also installed this package on Vue2 app autocomplete props are not showing only showed up on Vue3 https://github.com/alibaba/formily/tree/formily_next/packages/vue
an example that autocompletes props are showing up ctrl + space on Vue2.6 https://github.com/DanSnow/vue-recaptcha
https://discord.com/channels/793943652350427136/1052340776186695751
You can refer to my project, I believe I have explored a relatively elegant solution. It allows you to use the script setup
syntax and other latest Vue3 syntax to develop a universal component library. The idea is to package different versions together and use the postinstall script to distinguish the user's Vue version and release the corresponding build files.
https://github.com/Shimada666/vue-demi-sfc-component-template
For vue-demi
components, it's better to use local registration over global registration, because of this 👇
// global.d.ts or volar.d.ts
declare module '@vue/runtime-core' { // Vue 3
// declare module 'vue' { // Vue 2.7
// declare module '@vue/runtime-dom' { // Vue <= 2.6.14
export interface GlobalComponents {
GlobalComponent: typeof import('***')['GlobalComponent']
}
}
export {}
or you can define preset/resolver for unplugin-vue-components in your package
-
For showing autocomplete props on Vue3 and Vue2.7 component check vue-bridge ( how to generate d.ts files )
-
Also check this one https://www.npmjs.com/package/@smooth-scrollbar-contrib/vue-test?activeTab=explore based on
vue-bridge
ideaunbuild config
import { promises as fsp } from 'fs' import { join, resolve } from 'pathe' import { definePreset } from 'unbuild' const clientPreset = definePreset({ clean: true, externals: [ 'vue', 'vue-demi', 'smooth-scrollbar', '@vueuse/core', '@vueuse/shared', ], rollup: { emitCJS: true, }, failOnWarn: false, }) const versions = ['v2.6', 'v2.7', 'v3'] async function buildVue() { const { build } = await import('unbuild') for (const version of versions) { await build('.', false, { entries: ['src/index'], outDir: `dist/${version}`, preset: clientPreset, declaration: version === 'v3', hooks: { 'build:prepare': async (ctx) => { const indexFile = resolve(join(ctx.options.rootDir, 'src/component/index.ts')) const versionContent = await fsp.readFile(resolve(join(ctx.options.rootDir, `src/component/${version}.ts`)), 'utf8') await fsp.writeFile(indexFile, versionContent, 'utf8') }, 'build:done': async (ctx) => { if (version === 'v2.6' || version === 'v2.7') { const dtsFilePath = resolve(join(ctx.options.rootDir, `dist/${version}`, 'index')) await fsp.writeFile(`${dtsFilePath}.d.ts`, ["export * from '../src/index'"].join('\n')) } }, }, }) } } buildVue().catch((err) => { console.error(err) process.exit(1) })
Vue3
:
// declaration: true
// dist/index.d.ts
import * as vue_demi from 'vue-demi';
declare const Component: vue_demi.DefineComponent<{...}>;
Vue2.7
:
// custom index.d.ts
// dist/index.d.ts
// link to source file instead of generating d.ts file
export * from '../src/index'
Warn the user to not use __VUE_OPTIONS_API__: false
in their bundler option, since vue-demi
package is mixed with Option APIs and Composition APIs
I've been trying to make universal components with Vue and using the hints from here I could make it work. The nice thing is that we don't need to write our template by manually calling the h
function, which is ugly and hard to maintain, you can use JSX which will compile to the h-demi
function that @dnldsht created. There are a lot of little details and they are all described on the README of the repo below, so feel free to read and test it for yourself:
https://github.com/andresilva-cc/poc-vue-universal-component
It is not fully polished, it probably lacks some features, but it's working.