vuejs / core

πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
https://vuejs.org/
MIT License
47.62k stars 8.33k forks source link

Using custom script languages (such as coffeescript) no longer works since vue 3.3 (works in 3.2) #8368

Open Boux opened 1 year ago

Boux commented 1 year ago

Vue version

3.3.4

Link to minimal reproduction

https://github.com/Boux/vite-coffee-bug

Steps to reproduce

clone my example repo by running

git clone https://github.com/Boux/vite-coffee-bug.git
cd vite-coffee-bug
npm install
npm run build

This is a simple vue project that uses vite to compile everything, it uses 2 plugins in the vite.config.js:

// https://vitejs.dev/config/ export default defineConfig({ plugins: [ vue(), { name: 'coffee_compile', transform: function(src, id) {

    // compile coffee files to js
    if (/\.coffee$/.test(id)) {
      var {js, sourceMap} = CoffeeScript.compile(src, { sourceMap: true })
      return { code: js, map: sourceMap }
    }

  }
}

], })


### What is expected?

The sfc compiler called from the `@vitejs/plugin-vue` plugin should output something like this:

import _sfc_main from "/Users/boux/repo/vite_coffee_bug/src/App.vue?vue&type=script&lang.coffee" export * from "/Users/boux/repo/vite_coffee_bug/src/App.vue?vue&type=script&lang.coffee" import { toDisplayString as _toDisplayString, createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"

function _sfc_render(_ctx, _cache) { return (_openBlock(), _createElementBlock("div", null, [ _createElementVNode("button", { type: "button", onClick: _cache[0] || (_cache[0] = $event => (_ctx.count++)) }, "count is " + _toDisplayString(_ctx.count), 1) ])) }

import _export_sfc from 'plugin-vue:export-helper' export default /#PURE/_export_sfc(_sfc_main, [['render',_sfc_render]])


which I can then use in the `coffee_compile` plugin to compile the contents of `import _sfc_main from "/Users/boux/repo/vite_coffee_bug/src/App.vue?vue&type=script&lang.coffee"` from coffeescript to javascript

### What is actually happening?

The src compiler crashes with syntax errors as if it's trying to parse the code as typescript

npm run build

vite-coffee-bug@0.0.0 build vite build

vite v4.3.8 building for production... βœ“ 3 modules transformed. βœ“ built in 79ms [vite:vue] [vue/compiler-sfc] Missing semicolon. (5:6)

/Users/boux/repo/vite-coffee-bug/src/App.vue 3 |
4 | export default 5 | data: -> { count: ref(0) } | ^ 6 | 7 |
file: /Users/boux/repo/vite-coffee-bug/src/App.vue:5:6 error during build: SyntaxError: [vue/compiler-sfc] Missing semicolon. (5:6)

/Users/boux/repo/vite-coffee-bug/src/App.vue 3 |
4 | export default 5 | data: -> { count: ref(0) } | ^ 6 | 7 |
at instantiate (/Users/boux/repo/vite-coffee-bug/node_modules/@babel/parser/lib/index.js:653:32) at constructor (/Users/boux/repo/vite-coffee-bug/node_modules/@babel/parser/lib/index.js:946:12) at Parser.raise (/Users/boux/repo/vite-coffee-bug/node_modules/@babel/parser/lib/index.js:3270:19) at Parser.semicolon (/Users/boux/repo/vite-coffee-bug/node_modules/@babel/parser/lib/index.js:3637:10) at Parser.parseExportDefaultExpression (/Users/boux/repo/vite-coffee-bug/node_modules/@babel/parser/lib/index.js:13759:10) at Parser.parseExport (/Users/boux/repo/vite-coffee-bug/node_modules/@babel/parser/lib/index.js:13663:25) at Parser.parseStatementContent (/Users/boux/repo/vite-coffee-bug/node_modules/@babel/parser/lib/index.js:12661:27) at Parser.parseStatementLike (/Users/boux/repo/vite-coffee-bug/node_modules/@babel/parser/lib/index.js:12549:17) at Parser.parseModuleItem (/Users/boux/repo/vite-coffee-bug/node_modules/@babel/parser/lib/index.js:12526:17) at Parser.parseBlockOrModuleBlockBody (/Users/boux/repo/vite-coffee-bug/node_modules/@babel/parser/lib/index.js:13121:36) at Parser.parseBlockBody (/Users/boux/repo/vite-coffee-bug/node_modules/@babel/parser/lib/index.js:13114:10) at Parser.parseProgram (/Users/boux/repo/vite-coffee-bug/node_modules/@babel/parser/lib/index.js:12437:10) at Parser.parseTopLevel (/Users/boux/repo/vite-coffee-bug/node_modules/@babel/parser/lib/index.js:12427:25) at Parser.parse (/Users/boux/repo/vite-coffee-bug/node_modules/@babel/parser/lib/index.js:14245:10) at Object.parse (/Users/boux/repo/vite-coffee-bug/node_modules/@babel/parser/lib/index.js:14286:38) at parse (/Users/boux/repo/vite-coffee-bug/node_modules/@vue/compiler-sfc/dist/compiler-sfc.cjs.js:15812:25) at new ScriptCompileContext (/Users/boux/repo/vite-coffee-bug/node_modules/@vue/compiler-sfc/dist/compiler-sfc.cjs.js:15828:43) at Object.compileScript (/Users/boux/repo/vite-coffee-bug/node_modules/@vue/compiler-sfc/dist/compiler-sfc.cjs.js:19817:15) at resolveScript (file:///Users/boux/repo/vite-coffee-bug/node_modules/@vitejs/plugin-vue/dist/index.mjs:283:31) at genScriptCode (file:///Users/boux/repo/vite-coffee-bug/node_modules/@vitejs/plugin-vue/dist/index.mjs:2469:18) at transformMain (file:///Users/boux/repo/vite-coffee-bug/node_modules/@vitejs/plugin-vue/dist/index.mjs:2282:54) at Object.transform (file:///Users/boux/repo/vite-coffee-bug/node_modules/@vitejs/plugin-vue/dist/index.mjs:2794:16) at file:///Users/boux/repo/vite-coffee-bug/node_modules/rollup/dist/es/shared/node-entry.js:24592:40


### System Info

```shell
Tested on both `Mac OS 13.3.1` and up-to-date `Arch Linux`

Both on `node v16.16.0 (npm v8.11.0)` and `node v20.2.0 (npm v9.6.6)`

  System:
    OS: macOS 13.3.1
    CPU: (8) arm64 Apple M1
    Memory: 62.44 MB / 8.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 16.16.0 - ~/.nvm/versions/node/v16.16.0/bin/node
    Yarn: 1.22.19 - ~/.nvm/versions/node/v16.16.0/bin/yarn
    npm: 8.11.0 - ~/.nvm/versions/node/v16.16.0/bin/npm
  Browsers:
    Brave Browser: 113.1.51.110
    Chrome: 113.0.5672.92
    Firefox: 112.0.2
    Safari: 16.4
  npmPackages:
    vue: 3.3 => 3.3.4 

Any additional comments?

I am not sure if something has to be changed in @vitejs/plugin-vue when it calls the compiler, or if the compiler itself has a bug, or if this intended. It doesn't seem intended after reading the vue 3.3 blog post: https://blog.vuejs.org/posts/vue-3-3#script-setup-typescript-dx-improvements. They talk about fixes in their compiler for typescript when the code is in a <script setup>, but I'm not using a <script setup> and much less typescript. Nothing about restricting custom script languages

yyx990803 commented 1 year ago

This doesn't seem to be related to anything in Vue core - the error comes from the Vite scanning phase, so it's more of a Vite issue.

However, I'm not able to get your repro to work in any recent versions of Vite, so I'm not even sure if this is a regression. What is the version of Vue / Vite / @vitejs/plugin-vue in your previous working setup?

Boux commented 1 year ago

I understand, I will try posting this in the @vitejs/plugin-vue issues page EDIT: I posted it here: https://github.com/vitejs/vite-plugin-vue/issues/178

Here's the version numbers just in case @vitejs/plugin-vue: 4.2.3 (works with vue 3.2, but not 3.3) vite: 4.3.8 (works with vue 3.2, but not 3.3)

vue: 3.3.4 (doesnt work) vue: 3.2.47 (works)

if you downgrade the vue version to 3.2, are you still not able to get it to work?

npm install vue@3.2
npm run build

This is my build output after running the above commands in my example project

> vite-coffee-bug@0.0.0 build
> vite build

vite v4.3.8 building for production...
βœ“ 12 modules transformed.
dist/index.html                  0.45 kB β”‚ gzip:  0.30 kB
dist/assets/index-78058d01.css   1.03 kB β”‚ gzip:  0.56 kB
dist/assets/index-0fe7b7d9.js   53.24 kB β”‚ gzip: 21.45 kB
βœ“ built in 492ms
Boux commented 1 year ago

@yyx990803 I did a little digging, comparing both vue 3.2 and 3.3's compileScript function. Both of them tries to parse the script's content with babel's parser, with a try/catch around it, but in 3.2, the catch simply fails silently and returns the script, and in 3.3 it throws the error

version 3.2 https://github.com/vuejs/core/blob/3.2/packages/compiler-sfc/src/compileScript.ts line: 202

    } catch (e) {
      // silently fallback if parse fails since user may be using custom
      // babel syntax
      return script
    }

version 3.3 https://github.com/vuejs/core/blob/main/packages/compiler-sfc/src/script/context.ts in ScriptCompileContext's constructor, line: 103

    function parse(input: string, offset: number): Program {
      try {
        return babelParse(input, {
          plugins,
          sourceType: 'module'
        }).program
      } catch (e: any) {
        e.message = `[vue/compiler-sfc] ${e.message}\n\n${
          descriptor.filename
        }\n${generateCodeFrame(
          descriptor.source,
          e.pos + offset,
          e.pos + offset + 1
        )}`
        throw e
      }
    }

    this.scriptAst =
      descriptor.script &&
      parse(descriptor.script.content, descriptor.script.loc.start.offset)

I've never used babel before, I don't really know what it does, but if I comment out the line:

    this.scriptAst =
      descriptor.script &&
      parse(descriptor.script.content, descriptor.script.loc.start.offset)

in the node_modules/@vue/compiler-sfc/dist/compiler-sfc.cjs.js and I call npm run build again, everything works in vue 3.3

Is there a way to make it fail silently like it did in 3.2?

Kiruse commented 1 year ago

I can confirm that this issue is affecting my webpack setup as well. vue on version 3.3.4 fails as though pre-processing is never run, whereas vue v3.2.47 works perfectly.

Here are the errors I receive when trying to build with v3.3:

ERROR in ./views/home.vue?vue&type=script&lang=coffee (./node_modules/coffee-loader/dist/cjs.js!./node_modules/vue-loader/dist/index.js??ruleSet[1].rules[9].use[0]!./views/home.vue?vue&type=script&lang=coffee)
Module Error (from ./node_modules/vue-loader/dist/index.js):
[vue/compiler-sfc] Missing semicolon. (5:12)

/path/to/project/views/home.vue
47 |  
48 |  export default
49 |    components: {
   |              ^
50 |      MyComponent,
51 |    }
 @ ./views/home.vue?vue&type=script&lang=coffee 1:0-178 1:0-178 1:179-346 1:179-346
 @ ./views/home.vue 2:0-59 3:0-54 3:0-54 8:49-55

ERROR in ./views/home.vue?vue&type=script&lang=coffee (./node_modules/coffee-loader/dist/cjs.js!./node_modules/vue-loader/dist/index.js??ruleSet[1].rules[9].use[0]!./views/home.vue?vue&type=script&lang=coffee)
Module build failed (from ./node_modules/vue-loader/dist/index.js):
TypeError: Cannot read properties of null (reading 'content')
    at selectBlock (/path/to/project/node_modules/vue-loader/dist/select.js:23:45)
    at Object.loader (/path/to/project/node_modules/vue-loader/dist/index.js:92:41)
 @ ./views/home.vue?vue&type=script&lang=coffee 1:0-178 1:0-178 1:179-346 1:179-346
 @ ./views/home.vue 2:0-59 3:0-54 3:0-54 8:49-55

ERROR in ./views/home.vue?vue&type=template&id=36e0b024&scoped=true&lang=pug (./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[1]!./node_modules/vue-pug-loader/index.js!./node_modules/vue-loader/dist/index.js??ruleSet[1].rules[9].use[0]!./views/home.vue?vue&type=template&id=36e0b024&scoped=true&lang=pug)
Module Error (from ./node_modules/vue-loader/dist/templateLoader.js):
[vue/compiler-sfc] Missing semicolon. (5:12)

/path/to/project/views/home.vue
47 |  
48 |  export default
49 |    components: {
   |              ^
50 |      MyComponent,
51 |    }
 @ ./views/home.vue?vue&type=template&id=36e0b024&scoped=true&lang=pug 1:0-259 1:0-259
 @ ./views/home.vue 1:0-86 8:68-74

2 errors have detailed information that is not shown.
Use 'stats.errorDetails: true' resp. '--stats-error-details' to show it.

webpack 5.88.2 compiled with 3 errors in 1023 ms
error Command failed with exit code 1.
Boux commented 1 year ago

I currently have a (bad) workaround for this. I simply split up my script from my vue file and just import it in the vue file, for example:

MyComponent.vue

<script>
import MyComponent from "./MyComponent.coffee"
export default MyComponent
</script>

<template>
<p @click='onClick'>{{thing}}</p>
</template>

MyComponent.coffee

export default
  data: -> thing: 123
  methods:
    onClick: -> console.log "hello"

I ported one of my small projects over to vue 3.3 with this method, but I just gave up on coffeescript for my new projects

raizdev commented 1 year ago

I currently have a (bad) workaround for this. I simply split up my script from my vue file and just import it in the vue file, for example:

MyComponent.vue

<script>
import MyComponent from "./MyComponent.coffee"
export default MyComponent
</script>

<template>
<p @click='onClick'>{{thing}}</p>
</template>

MyComponent.coffee

export default
  data: -> thing: 123
  methods:
    onClick: -> console.log "hello"

I ported one of my small projects over to vue 3.3 with this method, but I just gave up on coffeescript for my new projects

Yeah, I'm spending almost few days to make it works unfortunately.. hope there will be a better workaround available..

nbennke commented 5 months ago

Is there any update in progress, solving this issue? We're also faced with this error preventing us to upgrade vue beyond v3.2.47 in our project using vue and coffeescript together.