parcel: Cannot have Vue components in template with self-closing tags

🐛 bug report

When I use multiple Vue components in my Vue template, only the first child component of a parent component appears to be displayed after minification. This happens when building the code for production, and does not happen when building for development or when using the --no-minify parameter.

🎛 Configuration (.babelrc, package.json, cli command)

.babelrc: N/A

package.json:

{
  "name": "testapp",
  "version": "1.0.0",
  "description": "testapp",
  "private": true,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "parcel build src/index.html",
    "dev": "parcel src/index.html"
  },
  "author": "Steffen",
  "license": "ISC",
  "dependencies": {
    "vue": "^2.5.16"
  },
  "devDependencies": {
    "@vue/component-compiler-utils": "^1.2.1",
    "vue-template-compiler": "^2.5.16"
  }
}

cli command:

parcel build src/index.html

🤔 Expected Behavior

All of the components should be displayed.

In my example code, I expect A B C D to be displayed in the UI.

😯 Current Behavior

Only the first child component of a parent component appears to be displayed.

In my example code, A B is displayed in the UI. This means that component A did not display component B and C, and the App component did not display component D.

💁 Possible Solution

🔦 Context

I use multiple components to build my UI, so only some of the UI is displayed right now.

💻 Code Sample

Please see the example code here:

https://github.com/SteffenL/parcel-vue-bug-repro/tree/vue-components

Here is a smaller example template:

<template>
<div id="app">
    <A /> <!-- displayed -->
    <B /> <!-- not displayed -->
</div>
</template>

<script>
import A from './A.vue';
import B from './B.vue';

export default {
    components: {
        A,
        B
    }
};
</script>

Building the code:

npm install
npm run build

Serve the files located in the dist/ directory.

🌍 Your Environment

Software Version(s)
Parcel 1.8.1
Node 8.11.1
npm/Yarn 5.6.0
Operating System Windows 10

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 3
  • Comments: 29 (11 by maintainers)

Most upvoted comments

@oksurf add the following to your package.json:

"posthtml": {
  "recognizeSelfClosing": true
}

Thanks @evanleck. That works for me.

Another possibility is to add a .posthtmlrc file to the root of your project with this content:

{
  "recognizeSelfClosing": true
}

@houd1ni Thanks for letting me know!

@DeMoorJasper I have investigated further and found that the problem is with posthtml and its lack of support for self-closing custom tags.

const posthtml = require('posthtml');

const html = `
<span>A
    <ComponentB />
    <ComponentC />
</span>
`;

const result = posthtml()
  .process(html, { sync: true })
  .html;

console.log(result);

This code turns the template into the following:

<span>A
    <ComponentB>
    <ComponentC>
</ComponentC></ComponentB></span>

There is an open issue for this: https://github.com/posthtml/posthtml/issues/221

Based on comments, I added xmlMode: true:

const posthtml = require('posthtml');

const html = `
<span>A
    <ComponentB />
    <ComponentC />
</span>
`;

const result = posthtml()
  .process(html, {
    sync: true,
    xmlMode: true
  }).html;

console.log(result);

This results in the following template:

<span>A
    <ComponentB></ComponentB>
    <ComponentC></ComponentC>
</span>

This does not seem ideal to me, and it would be a breaking change that would require users to write templates with XML syntax.

Example:

<span>A
    <img>
    <ComponentB />
    <ComponentC />
</span>

Turns into:

<span>A
    <img></span>

Still seeing the same problem with the latest code.

Changing: <span>A <ComponentB /> <ComponentC /> </span> to: <span>A <ComponentB></ComponentB> <ComponentC></ComponentC> </span> seems to work but wish they would fix this…

Just wasted a whole day on this issue. I was looking for an easy way to get started with a vue-typescript project quickly and expected the parcel approach to be faster, but ended up debugging this one issue for the entire day.

@SteffenL nope. Haven’t noticed. Will do 👍

I’ve had the same issue today, and saw an issue from 2018 with a comment saying it’s been fixed in this and that version, and now I’m here seeing 2021 comments stating it’s still and issue - and I’m in 2024, still experiencing the issue. So I’ll just won’t use self-closing tags.

Thanks!

I really think this flag should be set by default in Parcel. This problem does not occur with other bundlers.

Just wasted half a day on this. So infuriating.

The issue title is a bit misleading. In my experience self-closing tags don’t work for html tags as well as vue components, so it’s not specific to just using multiple vue components

Thanks @evanleck. That works for me.

Another possibility is to add a .posthtmlrc file to the root of your project with this content:

{
  "recognizeSelfClosing": true
}

Are there any caveats settings this somehow as a default for vue projects?

@SteffenL

Good news: your problem is connected with mine one https://github.com/parcel-bundler/parcel/issues/1294

You may install the bundler locally, like I do with every project, then change that lines of code (see last messages there). You’ll have good minified vue project 😄

Then wait until the maintainers apply the fixes.