Skip to content

Proposal: Template inheritance using the slots mechanism #6811

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

Closed
xlotlu opened this issue Oct 13, 2017 · 41 comments
Closed

Proposal: Template inheritance using the slots mechanism #6811

xlotlu opened this issue Oct 13, 2017 · 41 comments

Comments

@xlotlu
Copy link

xlotlu commented Oct 13, 2017

What problem does this feature solve?

Within a large application that makes heavy use of inheritance and mixins, the lack of template inheritance causes much jumping through hoops. The rationale under #5401 is eloquently written and captures the gist of it, so I won't repeat it here.

What does the proposed API look like?

My proposal for solving this issue is to simply extend upon the existing slots mechanism. That is (shamelessly copy/pasting from @simplesmiler's example under the issue above):

<!-- parent.vue -->
<template>
  <div>
    <slot name="header">
      <h3>Default header</h3>
    </slot>
    
    <slot><!-- yup, default --></slot>
    
    <slot name="body">
      <p>Default body</p>
    </slot>
    
    <slot name="footer">
      <!-- no footer by default -->
    </slot>
    
  </div>
</template>
<!-- child.vue -->
<template extends> <!-- here be magic -->
  This stuff
  <h2 slot="header">More pronounced header</h2>
  goes into
  <p slot="footer">Footer added by the child</p>
  the default slot.
</template>

Thus the existing composition rules are preserved, while it feels natural to both Vue developers and people used to templates with block-based inheritance (like Django, Pug etc.)

The only rules are that

  • an empty extends attribute can be used only with single-file components,
  • or it must be given a value when extending a DOM element:extends="#template-element",
  • and of course, that <template extends> can allow multiple root elements.
@yyx990803
Copy link
Member

Sorry but I really don't see what this provides over just:

<!-- child.vue -->
<template>
  <parent>
    your stuff
  </parent>
</template>

@xlotlu
Copy link
Author

xlotlu commented Oct 13, 2017

@yyx990803 the names "Parent" / "Child" in the original example meant class-like inheritance, not a tree of components. I updated the example to make things more clear.

The point here (as in #5401, and #6536, and in many places on the internet) is being able to extend a complex component for overriding something at script-level, while also doing small overrides at the template level. The simplest way to achieve this as per your example would be:

<template>
  <base>
    ..stuff
  </base>
</template>

<script>
import Base from './Base'

export default {
  extends: Base,
  components: {
    base: Base,
  }
}
</script>

... which is a big bug waiting to happen.

The non-simple but safe ways are:

  • proxying props, methods, slots and events around, and/or
  • lots of custom {{ vars }} sprinkled all over the template.

This, as the author put it in #5401, is very cumbersome and fragile. I love Vue precisely because it allows doing OOP-like multiple inheritance with extends and mixins, but the fact that templates are not extendable in the same manner ruins the fun pretty quick. In our case it makes development unnecessarily difficult and code hard to understand for newcomers to the project. If my highly simplified example is still not convincing enough I can provide real-life code that had to become unnecessarily complex due to the lack of template inheritance.

But this has been extensively discussed under #5401, where you seemed to agree there's an issue (although you obviously didn't agree with its severity as perceived by us). However you rejected the proposed solution because "having an extra composition model greatly muddles the structure of the program", which is a reasonable argument.

So there, this proposal solves the issue and preserves the composition model while looking natural and clean.

@MannikJ
Copy link

MannikJ commented Jan 8, 2018

@yyx990803 @xlotlu
I really like the approach of making use of the existing slot mechanism for component extension. Not sure whether the proposed syntax is the best, but it is at least a good starting point for discussion.

I finally decided to add my two cents here because I am still a bit surprised and frustrated.
After hours of research, thinking and tinkering I stumbled upon this article which helped me not to feel completely dumb for being unable to figure out how to solve my problem with the existing means.
As someone else already said, the fact that people use templating libraries like pug for component inheritance, should be proof enough that this demand should not be completely ignored.

The problem with the approaches I can think of using the existing mechanisms like mixins and slots is, if you want to change the Javascript AND the Markup, you always end up implementing the composition of elements at least two times.
This is because the slot mechanism expects data passed in from the parent to the child, so the parent template resides in the child actually, whereas class inheritance within Javascript works the opposite way. Something that couples both together would be very useful.

I don't think using scopes to define how a potential child component is able to merge additional content in to the parent's template, is bad at all. As the OP points out, I don't see how this feature would collide with the conventional scopes. This feature request is just about defining rules how the existing scopes could be used the other way round from within the child component to enable semantically correct component inheritance.

It should be said that I am neither Vue nor Javascript expert and therefore I have certainly overlooked important points that speak against such a feature.
Also, if anyone can think of an elegant way to implement component inheritance like described in the linked article with pure Vue, please share your thoughts.

@MannikJ
Copy link

MannikJ commented Jan 8, 2018

@yyx990803 @xlotlu

Sorry but I really don't see what this provides over just:

 <!-- child.vue -->
 <template>
 <parent>
     your stuff
 </parent>
 </template>

If get it right, in your example a whole new instance of the parent component is created. In the proposed approach, the child component IS A parent actually and it is the only instance created in this situation. The parent either serves as a prototype for the child or is directly used at the same level of the markup tree, because they are equivalent and independent instances.
The possibility to inherit and extend the parent from within the child template, makes it possible to couple it with the class extension at script level and would therefor enable full component inheritance.
IMHO this template inheritance only makes sense in conjunction with component class extension.
Also, to understand what we are aiming for, it does not help to look at content distribution in templates and component class extension separately. The claimed mechanism should bring those two together and therefor provide an API for content manipulation from child to parent while not destroying the original semantics of the slots system.

Here you can see, what I want to do:
https://codesandbox.io/s/jz8zzl7v3

@ThaDaVos
Copy link

Shameless copy-paste of my comment on the issue mentioned above #5401

Currently I'm running in the same kind of issue.
I'm extending a component which only purpose is to render something to a HTML5 Canvas (Parent of this component) - this component is called CanvasBox - now I want to extend this component to add separate logic for a specific use case - for this use case I also need to add a few elements to the CanvasBox's slots - so extending on the template - or at least filling in the slots without proxying all the props, events etc.

Like Justineo (in #5401) said, introducing another language, like pug, only to be able to do this looks overkill for me. So introducing a native VueJs way of just filling in the slots would be amazing.

btw, I can't include the CanvasBox as a component in the new component's template because there's logic in the CanvasBox's created hook for rendering to the HTML5 Canvas and using CanvasBox as component in the template would cause it to run this logic twice.

So last but not least, I would also love a easy way of extending the template or at least filling in the slots of the component which is extended.

@ThaDaVos
Copy link

I also want to make a proposal for in my eyes, a better syntax. It is as follows:

<!-- Base.vue -->
<template>
  <div>
    <slot name="header">
      <h3>Default header</h3>
    </slot>
    
    <slot><!-- yup, default --></slot>
    
    <slot name="body">
      <p>Default body</p>
    </slot>
    
    <slot name="footer">
      <!-- no footer by default -->
    </slot>
    
  </div>
</template>
<!-- SomeComponent.vue -->
<template slot="header">
<!-- Headery stuff -->
</template>

<template slot="body">
<!-- Body Stuff -->
</template>

<template slot="footer">
<!-- footer stuff -->
</template>

<script>
import Base from 'Base.vue';

export default {
    name: 'SomeComponent',
    extends: Base,
}

</script>

@xlotlu
Copy link
Author

xlotlu commented Jun 28, 2018

<template slot="header">
<!-- Headery stuff -->
</template>

@dvdbot this is so straightforward and obvious. There remains the problem of the default slot though, and the fact that currently multiple template blocks don't make sense to vue.

(on a related note, that is a feature I wanted so I could define subcomponents locally, e.g.:

<template>
   <!-- main thing stuff ... -->
</template>

<template id="subthing-tpl">
   <!-- sub thing stuff ... -->
</template>

<script>
import Thing from 'Thing'
import SubThing from 'SubThing'

export default Thing.extend({
  components: {
    subthing: SubThing.extend({
      template: "#subthing-tpl",
    })
  }
})
</script>

... :) )

Currently I'm running in the same kind of issue.
I'm extending a component which only purpose is to render something to a HTML5 Canvas

Incidentally, I encountered this in a similar scenario: I was using d3 to do the rendering, and vue as the data-handling backbone.

@ThaDaVos
Copy link

why not default slot =>

<template slot="">

@ThaDaVos
Copy link

Currently using a cheaty workaround :P - which works :P

@bbugh
Copy link

bbugh commented Jun 28, 2018

I understand the arguments for having an actual "extend template" built into the language - using the parent version in the template initializes another extra "unnecessary" component, which isn't optimal for performance. I agree that it is weird that this isn't built into the language, both to avoid the extra component and to simplify props passing.

However, the pattern for using the parent element as a slot is quite easy, and since this is one of the first Google results for the topic, here's a clean solution that has worked well for us:

// Base Component
<template>
  <div class="base-thing special-class">
    <p>Special {{label}}</p>
    <slot/>
  </div>
</template>

<script>
export default {
  name: "BaseComponent",
  props: {
    label: {
      type: String,
      required: true
    },
  }
}
</script>
// Inheriting Component
<template>
  <!-- $props passes all of the props on to the "parent" component -->
  <base-component v-bind="$props">
    <p>this is the extraProp: {{ extraProp }}</p>
    <!-- $attrs and $listeners respectively passes any additional non-prop 
         attributes and any event listeners on to the child -->
    <input v-model="someModel" v-bind="$attrs" v-on="$listeners">
  </base-component>
</template>

<script>
import BaseComponent from './BaseComponent'

export default {
  name: 'InheritingComponent',
  components: {
    BaseComponent
  },
  extends: BaseComponent,
  inheritAttrs: false,
  props: {
    extraProp: {
      type: String,
      default: "Goodbye"
    },
  },
  data() {
    return {
      someModel: 'test'
    }
  }
} 
</script>

Usage:

<inheriting-component label="Hello, World!" extraProp="Nevermind" />

Output:

<div class="base-thing special-class">
  <p>Special Hello, World!</p>
  <p>this is the extraProp: Nevermind</p>
  <input type="text" value="test">
</div>

@ThaDaVos
Copy link

The problem I'm running into when using your example @bbugh is that I've got logic in the created hook which draws something to the HTML5 Canvas - when using your example, the created hook is called on the base and the extending component, this is not what I want because the drawing is done twice - also I can't override the created hook without adding custom merge logic, but adding custom merge logic is global and not local for this component only, as far as I know and adding such custom merge logic may cause unfurseen side effects

@ThaDaVos
Copy link

For now I cheated the props part by using the following:

props: {
    ...BaseComponent.props
}

And then using the v-bind="$props"

@ThaDaVos
Copy link

Also not extending the BaseComponent

@xlotlu
Copy link
Author

xlotlu commented Jun 28, 2018

@bbugh I covered this approach in my initial rebuttal of @yyx990803 's rejection: #6811 (comment). I called it "a big bug waiting to happen" for the same reason as @dvdbot: hooks and watchers.

I wasn't aware of inheritAttrs, but it still doesn't solve the problem.

@anthonygore
Copy link

@xlotlu @dvdbot could I get your thoughts on this as a possible solution? anthonygore/vue-template-extension-loader#1

@dmitry-ivanov
Copy link

+1

IMHO, it would be great to have "template inheritance" as a part of a Vue core.
When you have components inheritance (I mean JS part) and don't have template inheritance (just child vs parent template) - it shortly becomes a pain.

In my case, I've extracted a few base components, for example, EditForm. Each child has its own fields, but they have the same buttons (Save, Save & Continue, Cancel). I have to copy-paste the same HTML code over and over now.

Suggestion to use the parent as a separate component inside the child template - also doesn't work for me, and I don't like it. I want to have one child component on all levels - script and template, both.

@nervgh
Copy link

nervgh commented Oct 30, 2018

+1 for the "template inheritance".

I use Nunjucks template engine which has this feature out-of-box. That's really convenient and powerful.

In general there are two ways of reusing the code: the inheritance and the composition. Last week React announced React-hooks which are focused on the composition. Why doesn't Vue want to implement the first one? I have no idea...)

@nervgh
Copy link

nervgh commented Oct 30, 2018

@yyx990803 please, read my comment above and share your thoughts about it : )

Your comment here is just about composition but not inheritance (of templates). There is a difference.

P.S: In my opinion "template inheritance" could be the new benefit of Vue.

@adamreisnz
Copy link

@yyx990803 why was this closed without further consideration? There's a lot of good comments and discussion about this topic, not just in here, but also in the referenced issues. Clearly this is something the community is very interested in, and it is not currently provided by vue. Component inheritance is not the same as nested parent/child components.

@miser
Copy link

miser commented Nov 20, 2018

Hi guys,
whether we can use component replacement instead of slot ?

If you know Chinses, please look it Vue Component 继承与复用

// Base Component
<template>
  <div class="base-thing special-class">
    <Button />
  </div>
</template>

<script>
import Button from './ButtonClick'
export default {
  components: { Button }
}
</script>

// Inheriting Component
<script>
import BaseComponent from './BaseComponent'
import Button from './OtherButton'

export default {
  extends: BaseComponent
  components: {
    Button
  }
} 
</script>

The Button of Child Component will be replaced OtherButton. We can do something in the OtherButton

@mrodal
Copy link

mrodal commented Jan 1, 2019

I also would like this to move forward, I have a base component that calls methods that are overriden by the child components, and this is not working now

@JamesB797
Copy link

Coming from mostly using html templating languages like twig with minimal js, not being able to extend the parent component's template and override small portions in the child component feels really weird and awkward.

The way it is right now if you want to change the js and template of a component directly, you need to first extend it to change the js, then wrap it to change the template. On the other hand if any of the solutions in this issue are implemented, you can get rid of the wrapper file completely, which is much cleaner.

I get that it might not be that easy given how component extension is sort of buried in the js, but I think it's a necessary feature for ease-of-use in the long run.

@SasanFarrokh
Copy link

Sorry but I really don't see what this provides over just:

<!-- child.vue -->
<template>
  <parent>
    your stuff
  </parent>
</template>

How to force the parent element to call child methods and use child data, props and ...?

@mrodal
Copy link

mrodal commented Jan 26, 2019

I ended up making a loader: https://github.com/mrodal/vue-inheritance-loader
Try it out if you want and let me know what you think and any improvements that could be done!

@Flipecs
Copy link

Flipecs commented May 24, 2019

This should be simple and useful, something along the lines.

<!-- child.vue -->
<template>
  <!-- could get the imported vue template from extends, mixins and components -->
  <insert extends:parent> 

    <!-- only markup linked to slots accepted -->
    <template v-slot:someparentslot>
      <!-- define the slot -->
    </template>

  </insert>
</template>

<script>
import parent from './parent'
export default {
  extends: parent
}
</script>

And at the end of the day if you wanna extend some templates you could put things behind or in front of it, if you wanna put something in between elements on the template it needs to contain a slot.
If you try to put something inside the insert markup without linking it to an slot you'll get an error.

@baptistebriel
Copy link

Hi! What's the current way of extending a template? When extending a class, my child component just doesn't have any template at all... I might be missing something, but this is the closest issue I could find. Thanks!

@okool
Copy link

okool commented Aug 1, 2019

Hi guys,
whether we can use component replacement instead of slot ?

If you know Chinses, please look it Vue Component 继承与复用

// Base Component
<template>
  <div class="base-thing special-class">
    <Button />
  </div>
</template>

<script>
import Button from './ButtonClick'
export default {
  components: { Button }
}
</script>

// Inheriting Component
<script>
import BaseComponent from './BaseComponent'
import Button from './OtherButton'

export default {
  extends: BaseComponent
  components: {
    Button
  }
} 
</script>

The Button of Child Component will be replaced OtherButton. We can do something in the OtherButton

这种替换方法,使得组件数量增加,达不到扩展的目的.既然替换不如直接拆分,使用props传值
<header /><table actions={...} columns={...} /><footer>

@MannikJ
Copy link

MannikJ commented Aug 1, 2019

Although I still think having template inheritance in the tool box would not really do any harm, I must meanwhile also assist the ones saying you have probably not internalized the concept of composition if you're asking for this feature. That's at least what I found while becoming a more advanced vue developer during the last months.
Once you get used to dividing your app into a ton of very small reusable components you will realize there is hardly any need for inheritance. Besides you will also notice very quickly how fast development gets when there many generic components already available.
To really make that work well it is essential to learn how to really implement your components in a way that they are flexible so they can be customized for any context inside your app. Slots and (computed) props are obviously the key techniques to make that happen.
In this context it is also very important to decide very carefully whether a you're dealing with a real data attribute, a property that comes from the outside of your component or a computed property that's only derived from the others. As a rule of thumb one can say almost ever there should be more props and computed props then data attributes. Data should be the single point of truth, so think twice what you put in there.
As developer who started with Java I found it really hard to accustom the fact that you are compelled to also implement relationships which are more like IS-A with composition instead of inheritance. But it's just the way to go - and it works :)

@xlotlu
Copy link
Author

xlotlu commented Aug 1, 2019

Although I still think having template inheritance in the tool box would not really do any harm, I must meanwhile also assist the ones saying you have probably not internalized the concept of composition if you're asking for this feature.

If I may say so, the corollary to this statement is that if one makes the case that template inheritance is useless because composition fits all scenarios, one probably has not internalized the concept of inheritance. Ten minutes spent within a good django or pug-based project might turn into an eye opener.

The project that prompted this issue at the time ended up filled with idiosyncrasies and code that is hard to follow due to this glaring omission, forcing us indeed to use composition when inheritance would have simply been straightforward, clean, and avoided useless repetition.

Such an example is MapBase.vue as it's used under BaseMap.vue, which in turn gets inherited by all the other '*Map.vue' files in the repository. And that's only one example.

Yes, composition is great and useful and any developer worth their salt will be using it. That's why people invented functions. But inheritance and composition are complementary. That's why people invented classes.

The funny thing is Vue does have inheritance, and that's precisely what makes it great. But frankly, sporting inheritance at the code level while making the case that it's useless at the template level is mind-boggling.

@MannikJ
Copy link

MannikJ commented Aug 1, 2019

I did not want and will not argue against the value of this feature in general and that it would make sense for certain cases to have the option to use full-component inheritance over composition. And I don't want to criticize anyone who has gone a long way of thought and come up with valid reasons to ask for such a feature. So please don't feel offended.

I just wanted to remind people to always keep questioning themselves. Most developers (me included obviously) overrate themselves and are quite stuck in their methodologies. It's actually very hard to understand and accept a new philosophy that is fundamentally different from what you are used to. And that's what happened to me when I started with VueJs, even so I wouldn't say I was generally a bad developer. I was in fact a bad VueJs developer. ;)
I just hope these insights would help others to avoid some of the wrong paths I have taken.

The funny thing is Vue does have inheritance, and that's precisely what makes it great. But frankly, sporting inheritance at the code level while making the case that it's useless at the template level is mind-boggling.

That's what brought me to this topic and I have posted my thoughts on this before.
I agree that it just feels very inconsequential.
Although I must say once again that the cases that would really benefit from inheritance over composition are very rare as long as you use the framework how it's meant to be used. Exceptions prove the rule.

@kinch-tech
Copy link

i don't think he knows what inheritance really is...

@MannikJ
Copy link

MannikJ commented Oct 30, 2019

i don't think he knows what inheritance really is...

What does that refer to?

@bportesio
Copy link

You can do it with pug https://pugjs.org/language/inheritance.html

@xlotlu
Copy link
Author

xlotlu commented Jan 28, 2020

You can do it with pug https://pugjs.org/language/inheritance.html

Well, yes, because the Pug designers get how essential it is in any large-scale project worth its salt. But you can't use use Pug's inheritance with single-file components.

@Padam87
Copy link

Padam87 commented Feb 14, 2020

@yyx990803 I think this is a valid use-case:

<template>
    <div class="modal fade" tabindex="-1" role="dialog" data-keyboard="false" data-backdrop="static">
        <div class="modal-dialog modal-dialog-centered" :class="[size]" role="document">
            <div class="modal-content">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <i class="fa fa-times"></i>
                </button>
                <slot name="content">
                    <div class="modal-header">
                        <slot name="header">
                            <h5 class="modal-title">Modal</h5>
                        </slot>
                    </div>
                    <div class="modal-body">
                        <slot name="body"></slot>
                    </div>
                    <div class="modal-footer">
                        <slot name="footer">
                            <button type="button" class="btn btn-primary" @click.prevent="submit">Save</button>
                        </slot>
                    </div>
                </slot>
            </div>
        </div>
    </div>
</template>

<script>
    module.exports = {
        props: {
            size: {
                'default': 'modal-md'
            }
        },
        data: function() {
            return {
                shown: false
            }
        },
        methods: {
            show: function () {
                $(this.$el).modal('show');
            },
            hide: function () {
                $(this.$el).modal('hide');
            },
            submit: function () {
                console.log('SUBMITTED MODAL');

                this.hide();
            }
        }
    };
</script>
  • If I extend this I have to override the whole template.
  • If I create a new component and use this as a sub component I lose the show / hide functions, which will have to be re implemented on the parent.
  • If I do both (besides the general ugliness of it) It still won't work properly:
<template>
    <parent>
        <div slot="body">
...
        </div>
    </parent>
</template>

<script>
    const Modal = require('./modal').default;

    module.exports = {
        name: 'ExtendedModal',
        extends: Modal,
        components: {
            parent: Modal,
        },
        methods: {
            submit: function () {
                console.log('OVERRIDE IS WORKING');
            }
        },
    };
</script>

The OVERRIDE IS WORKING message never appears, as the submit button triggers the original sub component's method.
I would have to override that slot too, and then extenting it would be pointless.

@SasanFarrokh
Copy link

Checkout this loader, It only uses slot mechanism and you can override slots in child component

https://www.npmjs.com/package/vue-slot-loader

@chumager
Copy link

Hi @SasanFarrokh, have you tested it? that module could save me lots of work, but neither the most simple attempt worked out.

At first I thought I've a weird configuration that doesn't allow the loader to work, then tested it with the test inside the module and it worked, finally use vue create to create a simple project, add the conf in vue.config.js but it never worked.

Anyone has had any luck with this module?

It's like the rule never catch the slot section in SFC.

@SasanFarrokh
Copy link

Hi @SasanFarrokh, have you tested it? that module could save me lots of work, but neither the most simple attempt worked out.

At first I thought I've a weird configuration that doesn't allow the loader to work, then tested it with the test inside the module and it worked, finally use vue create to create a simple project, add the conf in vue.config.js but it never worked.

Anyone has had any luck with this module?

It's like the rule never catch the slot section in SFC.

@chumager Did you config the loader correctly? Use the sample on the document, if still there is problems open an issue on the repository:
https://github.com/sasanfarrokh/vue-slot-loader

@chumager
Copy link

@SasanFarrokh, It doesn't work for me, I've made some changes to avoid overload slots, it works fine except when there is async vNodes inside (the root or children), in that case it doesn't render, I've been reading to found the way to render vNodes with asyncFactory but I haven't found anything about it...

Do you know how to do it?

I've changed everything in my framework to work with this approach and now I NEED to accomplish this change.

BTW your idea was AWESOME...

@mittaus
Copy link

mittaus commented Feb 13, 2021

Template inheritance I solved it as follows using vue-router.

-- public/index.html

<!DOCTYPE html>
<html lang="">
  <head>
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <!-- Title -->
    <title><%= htmlWebpackPlugin.options.title %> - Event</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

-- src/App.vue

<template>
  <div id="myapp">
    <router-view />
  </div>
</template>

-- src/views/_layouts/master.vue

<template>
  <div>Master page content</div>
  <router-view></router-view>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  name: "master",
});
</script>

-- src/views/home/Home.vue

<template>
  <div>Page content</div>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  name: "Home",
});
</script>

-- src/router/index.ts

import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
import Master from "../views/_layout/master.vue";

const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    name: "Home",
    component: Master,
    children: [
      {
        path: "/",
        name: "xyz",
        component: () => import("../views/home/Home.vue"),
      },
    ],
  },
  {
    path: "/about",
    name: "About",
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () =>
      import(/* webpackChunkName: "about" */ "../views/About.vue"),
  },
];

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes,
});

export default router;

And then execute npm run server and show

2021-02-13_13h04_53

@semiaddict
Copy link

Checkout this loader, It only uses slot mechanism and you can override slots in child component

https://www.npmjs.com/package/vue-slot-loader

@SasanFarrokh, this seems very promising!
Would love to see a version compatible with Vue 3.

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

No branches or pull requests