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
.coffee
files and in<script lang="coffee">
in.vue
files
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
> 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 | </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 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
@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.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..