Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[compiler-sfc] inconsistent behavior with vue2 when parsing empty blocks #2463

Closed
meteorlxy opened this issue Oct 22, 2020 · 1 comment
Closed

Comments

@meteorlxy
Copy link
Member

meteorlxy commented Oct 22, 2020

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

Explanation

It seems to be intended as the tests show:

https://github.com/vuejs/vue-next/blob/f4621ff5ee4abe924d985177956af3ddc9bb378f/packages/compiler-sfc/__tests__/parse.spec.ts#L114-L119

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 return null for empty <template>, it's difficult for vue-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:

https://github.com/vuejs/vue-next/blob/288c764e5279ccef63e0ef304d4250f5ad935a46/packages/runtime-core/src/component.ts#L711

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 and rollup-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

@sodatea
Copy link
Member

sodatea commented Nov 3, 2020

Another edge case as brought up by @znck: no <template>, no root level render, but the setup function returns a render function. In this case the omission of <template> is intentional.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants