vitejs / vite-plugin-vue

Vite Vue Plugins
MIT License
501 stars 154 forks source link

Support decorators in `.vue` file. #430

Closed ruojianll closed 2 months ago

ruojianll commented 4 months ago

Related plugins

Description

In newest npm create vue@latest project, we could use decorators after set "experimentalDecorators": true in standalone .ts files. But it couldn't be transformed in .vue files in <script lang="ts"></script>.

I advice to support decorators in .vue files directly or with "experimentalDecorators": true.

Suggested solution

Support decorators in .vue files.

Alternative

No response

Additional context

No response

Validations

sxzz commented 4 months ago

Considering it as a bug. Please provide a minimal reproduction to continue the issue. Thanks.

Why reproduction is required

ruojianll commented 4 months ago
  1. npm create vue@latest
  2. cd your-project
  3. npm install
  4. Set "experimentalDecorators": true in tsconfig.app.json
  5. npm run dev
  6. Change src/HomeView.vue's script block.
    
    <script setup lang="ts">
    import TheWelcome from '../components/TheWelcome.vue'

function deco(){ console.log('deco works') } @deco class MyClass{}



There is an error in browser console `Uncaught SyntaxError: Invalid or unexpected token`.
It should show `deco works`.
sxzz commented 4 months ago

It could be related to Vite dev server, since it works on build mode vite build.

sxzz commented 4 months ago

This is because Vite's esbuild syntax transformation occurs before the Vue plugin, and esbuild does not recognize Vue SFC, so it is ignored.

ruojianll commented 2 months ago

How about this going?

alamhubb commented 2 months ago

When I used the decorator function of ts, I also encountered a problem

When I used the decorator in the dev environment of vite, an exception occurred, but it was normal in the build environment

So I checked the differences between the dev and build environments

I found that in the build environment, the target of esbuild can be replaced by esbuild:{target}, esbuildTransformOptions in vite.config.ts, while in the dev environment, it is hard-coded, target:esnext, and esbuildTransformOptions does not replace target:esnext

Logic executed when vite:esbuild builds

https://github.com/vitejs/vite/blob/main/packages/vite/src/node/plugins/esbuild.ts (238)

image

vite-plugin-vue Logic executed in dev environment

https://github.com/vitejs/vite-plugin-vue/blob/main/packages/plugin-vue/src/main.ts (253)

image

This leads to inconsistency between dev environment and build environment, which I find strange

vite is the basic component of vite-plugin-vue.

In the vite project, when vite-plugin-vue calls the transformWithEsbuild function provided by vite:esbuild, the parameters passed in should be consistent with the parameters of transformWithEsbuild called by vite:esbuild itself when building.

That is, esbuildTransformOptions should be used to replace and merge target:esnext

And this code will only be triggered in the development environment, so options.devServer?.config.esbuild can be used

This way, the results of dev environment and build environment can be consistent

So I submitted a PR https://github.com/vitejs/vite-plugin-vue/pull/444

alamhubb commented 2 months ago

relate pr https://github.com/vitejs/vite-plugin-vue/pull/222

sxzz commented 2 months ago

Fixed via #444

sxzz commented 2 months ago

It will automatically read tsconfig.json and transform decorators. In the default vue template, Vite cannot find the correct tsconfig.json via App.vue.

Try copying the content from tsconfig.app.json to your main tsconfig.json.