Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev server does not transpile script in .vue files (but it works in .ts ones) #31

Closed
7 tasks done
p0358 opened this issue Dec 1, 2022 · 11 comments · May be fixed by #222
Closed
7 tasks done

Dev server does not transpile script in .vue files (but it works in .ts ones) #31

p0358 opened this issue Dec 1, 2022 · 11 comments · May be fixed by #222

Comments

@p0358
Copy link

p0358 commented Dec 1, 2022

Describe the bug

I set my build/esbuild target to something below ES2020 in order to support by target browser (~Safari 13, supports around ES2019, pre-ES2020). Then I can use newer syntax in .ts files just fine, but as soon as I use any new syntax in .vue SFC files (inside of <script lang="ts">, no matter if setup or not), I get errors, because it's not properly transpiled.

One example of such syntax is optional chaining operator, and as such adding a line like

test()?.value || 'bb'

will yield error like following:
image

Again, it works as expected if I use this inside of any .ts file, but fails inside of .vue.

Reproduction

https://github.com/p0358/vite-vue-transpilation-repro

Steps to reproduce

  1. Clone my repro repo (see commit to see what changes I had to made to default project, most importantly target)
  2. pnpm run dev
  3. Open in your latest browser, see all works
  4. Open in some older pre-ES2020 browser, see it fails and throws SyntaxError
  5. Change code in HelloWorld.vue to not include optional chaining anymore (change ?. to .)
  6. See that it now works in old browser too, and code from main.ts will print something into the console now, confirming the issue lies in improper transpilation of .vue files

Example old browser to test in: https://github.com/niutech/qt-ultralight-browser (note this one sadly has no dev tools, I can package a build based on the same browser with dev-tools if you want to test)

System Info

System:
    OS: Windows 10 10.0.19045
    CPU: (4) x64 Intel(R) Core(TM) i5-6400 CPU @ 2.70GHz
    Memory: 530.82 MB / 15.88 GB
  Binaries:
    Node: 19.1.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.19 - C:\Program Files\nodejs\yarn.CMD
    npm: 8.19.3 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Spartan (44.19041.1266.0)
    Internet Explorer: 11.0.19041.1566
  npmPackages:
    @vitejs/plugin-vue: ^3.2.0 => 3.2.0
    vite: ^3.2.3 => 3.2.4

Used Package Manager

pnpm

Logs

SyntaxError: Unexpected token '.' — HelloWorld.vue

Validations

@p0358
Copy link
Author

p0358 commented Dec 1, 2022

Can also be reproduced with this chromium version (has devtools; grab chrome-win.zip):
https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/683419/

image

@patak-dev patak-dev transferred this issue from vitejs/vite Dec 3, 2022
@p0358
Copy link
Author

p0358 commented Dec 4, 2022

It's worth noting that I was having issues with transpilation working in dev mode at all, for which I had to explicitly add esbuild.target option like so, in addition to existing build.target:

export default defineConfig({
    // [...]
    plugins: [vue()],
    build: {
        target: ["chrome102", "safari13"],
    },
    esbuild: {
        target: ["chrome102", "safari13"]
    },
    // [...]
});

Because of that I was not sure if issue belongs to vite or this plugin here. These issues might even potentially be unrelated, I mention the above thing just now, because I forgot at that time I even did this, assuming it just made things work.

@luo3house
Copy link

vite-plugin-vue always transpiles Vue code into esnext, not follows dev server config.

const { code, map } = await transformWithEsbuild(
resolvedCode,
filename,
{
loader: 'ts',
target: 'esnext',
sourcemap: options.sourceMap,
},
resolvedMap,
)

I think you should use the latest browser for developing,
But if there are special cases, this is also possible to be a bug.

@p0358
Copy link
Author

p0358 commented Dec 5, 2022

I think you should use the latest browser for developing,
But if there are special cases, this is also possible to be a bug.

My case is a little bit special, because I develop for an embedded browser for a video game, which is a product based on a fixed version of WebKit which they rebase on top of latest version with some considerate delay (current version is based on mid-2019 WebKit, they plan to update to newer one within a couple of months).

With that + the fact this kind of browser has custom JavaScript bindings for communication with the game engine, it'd be hard to test with an outside browser, as even developing mocks would not give the exact same experience behavior. And the thing is, it basically fully works, until it encounters some ES2020+ syntax like here.

vite-plugin-vue always transpiles Vue code into esnext, not follows dev server config.

I see, would it be possible to consider changing it? I'm not exactly sure what's the relationship here between the Vue plugin and Vite, but I know setting esbuild.target in Vite config causes it to transpile .ts files in dev server mode, and that seems to work 100% fine. After all ESBuild is pretty fast, and theoretically matching the target option as long as it's post-ES6 shouldn't really have any side effects, right? Maybe the plugin could try to inherit that target option or at least make it manually configurable for the user?

Or perhaps it's a Vite bug that it transpiles .ts files directly there, but not output of plugins?

@luo3house
Copy link

Vite transpiles .ts code to esbuild.target, but Vue Plugin does not.

Assume esbuild target is es6, when dev for IE11 (only ES6).

Then the code ({ n: 1 })?.n.

  • runs at main.ts, it is transpiled to es6 by Vite.

  • error occurs at HelloWorld.vue, it is also transpiled, but to esnext by Vue Plugin.


If this is seem like a bug. Vue Plugin should follow Vite config.

Vue Plugin use import.meta for HMR. That feature is available >= ES2020.

If retrieved esbuild target from Vite is < ES2020. Plugin should show warning even error message.


I can't provide any approach for your case excepting take patch. It is hard-coded.

@sapphi-red Sorry for pinging. Would you see it as a bug?

@sapphi-red
Copy link
Member

When esbuild.target is ES2020+, I think this is a "p3-minor-bug" and "regression". I think we should use esbuild.target if it's defined.

But when esbuild.target is ES2020<, it's not a "regression" because it didn't work in past. IMO it's a "won't fix". Vite heavily relies on import.meta and won't work without that. Maybe you could workaround with a custom plugin.

FYI this part was set by vitejs/vite#10207 to avoid transpiling import.meta into import_meta that breaks HMR.

@p0358
Copy link
Author

p0358 commented Dec 6, 2022

In my case it seems the browser turns out to not be actually ES2020< (Safari 13), as import.meta is supported (since Safari 11.1), thankfully.

I can confirm that manually editing vue plugin's .js file under node_modules to change esnext to safari13 fixes my issue and everything works 100% properly then.

In such case I think it would be reasonable to just use the esbuild.target setting directly if it's defined. If too old of a target there would break Vite's dev server itself due to lack of import.meta support, then I think it's not a concern of this plugin itself, as the whole HMR system would already be broken in the first place, so nothing would work. So perhaps Vite should have some warning for too old setting there, but the possibility to transpile between that minimum HMR target and latest proved very useful to me, so it would be cool to keep it there, given it works just fine and is optional (as in my use-case I can't really use any other browser than my exact frozen target version).

@uuau99999
Copy link

@p0358 same issue and modify target inside node_modules/vite-plugin-vue fix my problem too. I also agree that specifying a too low target which breaks the bundle is not the concern of this lib. It is user's concern specifying target in the config.esbuild. vite-plugin-vue should respect the target in esbuild regradless of the risk that may break the bundling.
image

As seen above, browser starting from 2018 already support import.meta, which is much earlier than the release of es2020.

@alamhubb
Copy link

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 #444

@alamhubb
Copy link

#444 This fix allows overwrite esbuild config, so it fixes #278 , and #31 is repeated with 278. Can #31 be closed?

#278 , in dev mode, whether the configuration when calling esbuild build can be read synchronously from vite.config.js or support parameter passing duplication,

@sxzz sxzz closed this as completed Sep 16, 2024
@aweikalee
Copy link

#444此修复允许覆盖 esbuild 配置,因此它修复了#278,并且#31与 278 重复。#31可以关闭吗?

#278,dev 模式下,调用 esbuild build 时的配置是否可以从 vite.config.js 中同步读取或者支持参数传递重复,

The problem is not completely solved.

#444 only fixed lang="ts", the problem still exists with lang="js".

I think #222 is a more thorough fix.

@github-actions github-actions bot locked and limited conversation to collaborators Oct 3, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants