[compiler-sfc] inconsistent behavior with vue2 when parsing empty blocks
Version
3.0.2
Reproduction link
https://codesandbox.io/s/autumn-wildflower-cqpew?file=/src/index.ts
Steps to reproduce
import { parse } from "@vue/compiler-sfc";
import { parse as parse2 } from "@vue/component-compiler-utils";
const source = `\
<template></template>
<script></script>
<style></style>
`;
const vue3 = parse(source);
console.log("vue3", vue3.descriptor);
// template: null
// script: null
// style: []
const vue2 = parse2({
source,
compiler: require("vue-template-compiler")
});
console.log("vue2", vue2);
// template: { ... }
// script: { ... }
// style: [{ ... }]
What is expected?
Consistent with vue2, get the descriptor of empty block.
What is actually happening?
The descriptor of empty block is null
.
Related issues
- #464
Explanation
It seems to be intended as the tests show:
However, it may cause some breakings in SFC:
- An empty
<template>
block means it should render empty string, which is different from no<template>
block. - If
@vue/compiler-sfc
returnnull
for empty<template>
, it's difficult forvue-loader
/rollup-plugin-vue
to determine if the SFC has<template>
block or not.
In fact, the only difference is a runtime warning during development:
IMO:
- An empty
<template>
block is intended by user, which should not be warned. - No
<template>
block might be a fault, which should be warned.
Questions / Discussion
As we do not have a full specification for vue SFC, some edge cases are not so specific, and the behavior of vue-loader
/ rollup-plugin-vue
/ other implementations can be inconsistent.
Here are some edge cases that might need to be determined:
Case A: SFC has both <template>
and script.render
:
<template>
<div></div>
</template>
<script>
export default {
render() {}
}
</script>
Which is expected?
- replace
script.render
with<template>
- use
script.render
Current behavior of
vue-loader
androllup-plugin-vue
is the first one.
Case B: SFC has empty <template>
and script.render
:
<template></template>
<script>
export default {
render() {}
}
</script>
Which is expected?
- replace
script.render
with empty<template>
- use
script.render
This is affected by this issue.
Case C: SFC has empty <template>
, but does not have script.render
:
<template></template>
<script>
export default {
// no render()
}
</script>
Which is expected?
- replace
script.render
with empty<template>
- replace
script.render
with a NOOP as default render - keep it
undefined
(will print a runtime warning)
This is affected by this issue.
Case D: SFC does not have <template>
nor script.render
:
<script>
export default {
// no render()
}
</script>
Which is expected?
- replace
script.render
with a NOOP as default render - keep it
undefined
(will print a runtime warning)
@yyx990803 @sodatea @znck