// 用 @vue/compiler-sfc(与 @vitejs/plugin-vue 同一套编译器)校验 SFC 能否正常编译。
|
// 用途:校验尚未被任何页面引用的公共组件;已被引用的文件交给 npm run build:prod 兜底。
|
// 用法:node scripts/check-sfc.mjs <file...>
|
import { readFileSync } from 'node:fs'
|
import { parse, compileScript, compileTemplate } from '@vue/compiler-sfc'
|
|
const files = process.argv.slice(2)
|
if (!files.length) {
|
console.error('用法:node scripts/check-sfc.mjs <file...>')
|
process.exit(2)
|
}
|
|
let failed = 0
|
for (const file of files) {
|
const filename = file.replace(/\\/g, '/')
|
const errors = []
|
try {
|
const { descriptor, errors: parseErrors } = parse(readFileSync(file, 'utf8'), { filename })
|
errors.push(...parseErrors)
|
if (!errors.length) {
|
// 纯模板组件(如官方 ParentView)没有 script 块,compileScript 会直接报错,跳过
|
const hasScript = !!(descriptor.script || descriptor.scriptSetup)
|
const script = hasScript ? compileScript(descriptor, { id: filename }) : { bindings: {} }
|
if (descriptor.template) {
|
const { errors: templateErrors } = compileTemplate({
|
source: descriptor.template.content,
|
filename,
|
id: filename,
|
scoped: descriptor.styles.some(s => s.scoped),
|
compilerOptions: { bindingMetadata: script.bindings }
|
})
|
errors.push(...templateErrors)
|
}
|
}
|
} catch (e) {
|
errors.push(e)
|
}
|
|
if (errors.length) {
|
failed++
|
console.error(`✗ ${file}`)
|
errors.forEach(e => console.error(' ', e.message || e))
|
} else {
|
console.log(`✓ ${file}`)
|
}
|
}
|
|
process.exit(failed ? 1 : 0)
|