Using custom script languages (such as coffeescript) no longer works since vue 3.3 (works in 3.2)
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:
-
@vitejs/plugin-vue - a custom plugin that compiles coffeescript in
.coffeefiles and in<script lang="coffee">in.vuefiles
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import CoffeeScript from "coffeescript"
// 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
> [email protected] 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 | </script>
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 | </script>
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
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
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?
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 [email protected]
npm run build
This is my build output after running the above commands in my example project
> [email protected] 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
@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?
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.
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
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.coffeeexport 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..
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.
Years go by ... 3.5.13 same issue