thunderbiscuit
thunderbiscuit

Reputation: 219

VuePress theme inheritance setup

I am attempting to modify the VuePress default theme navbar using theme inheritance. After reading the 1.x documentation, I believe I am applying exactly what is recommended, but the website does not build properly.

I have added extend = '@vuepress/theme-default' to my config.toml file, and created a directory called .vuepress/theme/components/ to which I have added the file Navbar.vue.

When generating the site, my terminal gives me the following warning:

warning [vuepress] Cannot resolve Layout.vue file in undefined, fallback to default layout: ...

The website does work, but the the default theme is not used, and the page is all off.

Upvotes: 2

Views: 2053

Answers (2)

leas
leas

Reputation: 379

How to extend the default theme in Vuepress

Step 1 : Create a folder named « theme » under ‘./vuepress'

In this folder create a file named « index.js » with the following lines :

module.exports = {
    extend: '@vuepress/theme-default'
}

By doing this you specified that you are extending the default theme.

Step 2 : Recreate the right folders hierarchy respecting the one under ‘@vuepress/theme-default’

For example, if you want to extend the theme of the sidebar, you will have to replicate its hierarchy as follows :

The default theme in the Vuepress module :

@vuepress
  |— theme-default
     |— components
        |— Sidebar.vue

The extension of the default theme in your own project :

./vuepress
    |— theme
       |— components
          |— Sidebar.vue

To learn more about the file-level conventions, check out the Vuepress documentation.

Step 3 : Add a layout, a component or a styling element

You can either create a new component or styling element from scratch or copy an existing one from Vuepress to modify it.

Place the file in the right folder, and conserve its original name if it’s an existing one.

Step 4 : Fix dependencies

If your file depends on other files that are in the Vuepress module, you will need to specify it using the '@parent-theme’ keyword.

For example :

import { endingSlashRE, outboundRE } from  ‘../util’

becomes

import { endingSlashRE, outboundRE } from '@parent-theme/util’

And

@require ‘../styles/wrapper.styl’

becomes

@require '~@parent-theme/styles/wrapper.styl’

You can consider that '@parent-theme' stands for ’node-module/@vuepress/theme-default’.

Step 5 : Change the theme as you’d like !

Upvotes: 11

JL Peyret
JL Peyret

Reputation: 12184

So much thanks to @leas on this. Since I managed to get it working with their help, I am going to share a concrete case of overriding a component, on something else than the default theme.

In this case, I want to override Header.vue on Theme @vuepress/theme-blog and I also needed to enhance the base theme configuration.

All I wanted to do was to add a logo to my navbar, which is supported by core vuepress but not @vuepress/theme-blog.

what I done beforehand to components/Header.vue

I had added an <img> tag by directly modifying it under node_modules and got it to display my logo successfully, but then I was looking for a way not to have to overwrite it after every npm install.

        <div class="header-wrapper">
          <div class="title">
+ 👉        <img v-if="$themeConfig.logo" :src="$themeConfig.logo" alt="logo">
            <NavLink link="/" class="home-link">{{ $site.title }} </NavLink>
          </div>
          <div class="header-right-wrap">

starting directory hierarchy under .vuepress

(minus the public and other stuff via tree -a -I 'public|about|_issues|_posts')

.
└── .vuepress
    └── config.js

final directory hierarchy, following leas's answer:

.
└── .vuepress
    ├── config.js
    └── theme
        ├── components
        │   └── Header.vue
        └── index.js

file contents and adjustments:

index.js:

module.exports = {
    extend: '@vuepress/theme-blog'
}

Header.vue, after adjusting for inheritance:

img remains the same, but note the @parent-theme and that I could not use ./Feed as a sibling, but had to refer to the components directory.

+           <img v-if="$themeConfig.logo" :src="$themeConfig.logo" alt="logo">
....
< import Feed from './Feed'
---
> import Feed from '@parent-theme/components/Feed' 👈

How did I know I had to do this? Well, the page didn't work and the console.log showed a compilation error around ./Feed. Had a look at the https://v1.vuepress.vuejs.org/theme/inheritance.html#inheritance-strategy as suggested.

config.js

This includes 2 things:

  • getting rid of the direct theme specification, since that is now handled by theme/index.js.

  • changing the theme config. You don't need to "override" the parent theme config as such, which people seem to want. Your config.js will be used by the base theme and plugin, you just need to use refer to your custom stuff correctly in your theme override.

  module.exports = {
    ...
!   // theme: '@vuepress/theme-blog',  👈 theme/index.js handles that.

    ...
    themeConfig: {

+     logo: "/selectobjects.png", 👈 and the modified Header.vue uses this.

Note: I will take a copy of the core Header.vue and save it. In the future, if @vuepress/theme-blog modifies theirs, I want to be able to see how my original customization here compared to their core component at the time.

FYI Versions used:

[email protected]
@vuepress/[email protected]
npm --version
6.14.5
node --version
v10.15.0

Upvotes: 5

Related Questions