Search code examples
laravelvue.jslaravel-mixlaravel-mix-vue3

Vue 3 Template Fragments creating errors


-- Update --

I forgot to mention for this issue that I am using Laravel Mix to bundle my code.

webpack.mix.js

const mix = require("laravel-mix");
mix
  .js("src/js/index.js", "dist/js")
  .vue()
  .version()
  .js("src/js/popup.js", "dist/js")
  .vue()
  .version()
  .js("src/js/background.js", "dist/js")
  .version()
  .sass("src/css/main.scss", "dist/css")
  .sass("src/css/popup.scss", "dist/css")
  .copy("src/assets", "dist/assets")
  .copy("src/html", "dist/html")
  .copy("src/manifest.json", "dist")
  .setPublicPath("./")
  .options({ processCssUrls: false });

When I have it set like this, webpack uses Vue 2 by default. To clarify, Vue 2 works perfectly fine for my project. I just want the additional functionality of Vue 3.

From the documentation that's listed on Laravel Mix, I should be doing this in order to specify Vue 3

mix.js('src/app.js', 'dist').vue({ version: 3 });

When I configure my webpack.mix.js like this, it ends up throwing the error Can't resolve 'vue' in path/to/file

-- Original --

Trying to use Fragments in Vue 3 but they are not working.

Here is my code

<template>
  <div class="container">
    <div v-if="tab === 'options'">
      <Options />
    </div>
    <div v-else-if="tab === 'updates'">
      <Updates />
    </div>
    <div v-else-if="tab === 'account'">
      <Account />
    </div>
  </div>
  <md-bottom-bar md-type="shift">
    <md-bottom-bar-item
      @click="($event) => changeTab($event, 'options')"
      id="bottom-bar-item-options"
      md-label="Options"
      md-icon="home"
    />
    <md-bottom-bar-item
      @click="($event) => changeTab($event, 'updates')"
      id="bottom-bar-item-updates"
      md-label="Updates"
      md-icon="pages"
    />
    <md-bottom-bar-item
      @click="($event) => changeTab($event, 'account')"
      id="bottom-bar-item-account"
      md-label="Account"
      md-icon="favorite"
    />
  </md-bottom-bar>
</template>

Here is the error:

Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.

After reading the documentation, it mentions that : In 3.x, components now can have multiple root nodes! However, this does require developers to explicitly define where attributes should be distributed.

I don't think I'm passing any attributes though. Without my knowledge, could I still be running Vue 2?


Solution

  • As far as I can see this code should work perfectly in vue3. So it actually might be a versioning issue.

    Check your package.json for "vue" the version should be 3.x.x. After changing it to 3.x.x you will need to run npm install or yarn install.

    And a little tip instead of multiple v-ifs you could use dynamic components:
    <component :is="tab"></component>

    See: https://vuejs.org/v3/guide/components-dynamic-async.html