1
votes

I'm using BootstrapVue and have set it up as per the docs. What I'm seeing though is that for every component in my Vue app that uses a BootstrapVue component, I'm getting the Bootstrap embedded in my rendered HTML. In this case, I have 27 instances of the same stylesheet being added.

I can't see where the issue is.

Here's my main.js file

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import { BRow, BCol, BContainer  } from 'bootstrap-vue'
import {InlineSvgPlugin} from "vue-inline-svg/dist/vue-inline-svg";
import VueSvgIconPolyFill from "@yzfe/vue-svgicon-polyfill";

Vue.config.productionTip = false

Vue.use(VueSvgIconPolyFill);
Vue.use(BCol, BRow, BContainer)
Vue.use(require('vue-moment'))
Vue.use(InlineSvgPlugin)

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

And here's an example of a Vue component using BootstrapVue

<template>
    <section class="latest-news">
        <b-container>
            <b-row class="latest-news__title-bar">
                <b-col class="d-flex align-items-center" :sm="12" :md="10">
                    <h2>
                        {{blockTitle}}
                        <a
                                href="#"
                                title="Collapse this section"
                                :class="`collapse-control ` + (isCollapsed ? 'collapse-control--collapsed' : '')"
                                @click.prevent="isCollapsed = !isCollapsed"
                                v-html="(isCollapsed) ? 'Show' : 'Hide'"
                        ></a>
                    </h2>
                </b-col>
                <b-col class="d-flex justify-space-around" v-if="showSearchBar">
                    <ContentSearchBar title="Search news"/>
                </b-col>
                <b-col class="d-flex justify-content-end">
                    <Toolbar controls="news" :display-sorter="false" v-if="!isCollapsed && news.length"/>
                </b-col>
            </b-row>
            <b-row v-if="!isCollapsed">
                <b-col
                        cols="12"
                        :sm="smCols"
                        :md="mdCols"
                        v-for="(item, index) in news"
                        :key="`news` + index"
                       :class="((index < numberNewsItems) || !numberNewsItems) ? `latest-news__col` : ``"
                >
                    <NewsItem
                            v-if="(index < numberNewsItems) || numberNewsItems === null"
                            :show-excerpt="showExcerpt"
                            :news="item"
                            :item-index="index"
                            :format="newsListFormat"
                    />
                </b-col>
            </b-row>
            <b-row v-if="news && news.length === 0 && isSearch && !isCollapsed">
                <b-col cols="12">There are no news item results for your search term "{{$route.params.query}}"</b-col>
            </b-row>
        </b-container>
    </section>
</template>

<script>
  import NewsItem from "./NewsItem";
  import ContentSearchBar from "./ContentSearchBar";
  import Toolbar from "./Toolbar";
  import store from '../store';
  import {mapGetters} from 'vuex';
  import NewsService from '../services/NewsService'

  export default {
    name: "LatestNews",
    store: store,
    props: {
      showExcerpt: {
        default: true,
      },
      showSearchBar: {
        default: false,
      },
      numberNewsItems: {
        default: null
      },
      'isSearch': {
        default: false
      },
    },
    data() {
      return {
        news: [],
        isCollapsed: false
      }
    },
    mounted() {
      if (this.isSearch) {
        this.searchNews()
      } else {
        this.getNews()
      }
    },
    methods: {
      async getNews() {
        const response = await NewsService.all()
        this.news = response.data
      },
      async searchNews() {
        let query = this.$route.params.query;
        const response = await NewsService.search(query);
        this.news = response.data.results
      }
    },
    components: {Toolbar, ContentSearchBar, NewsItem},
    computed: {
      blockTitle() {
        if (this.isSearch) {
          return 'News search results for "' + this.$route.params.query + '"'
        } else {
          return 'Latest News'
        }

      },
      ...mapGetters([
        'newsListFormat'
      ]),
      smCols() {
        if (this.newsListFormat === 'list') {
          return '12'
        } else {
          return '6'
        }
      },
      mdCols() {
        if (this.newsListFormat === 'list') {
          return '12'
        } else {
          return '3'
        }
      },
    }

  }
</script>

<style lang="scss">
    .latest-news {
        &__col {
            margin-bottom: 24px;
        }

        &__title-bar {
            margin-bottom: 20px;

            h2 {
                margin-bottom: 0;
            }
        }
    }
</style>

This is how Chrome dev tools shows the HTML when yarn serveed

enter image description here

1
Should't you add Vue.use(BootstrapVue); that is exported module from bootstrap-vue? I don't know does it solve the problem though - onuriltan
The same thing is happening to me. No idea why as I've followed the instructions in the docs. One odd thing is that each instance of Bootstrap has a different data tag associated with it, ie., [data-v-d66bcac4] - Hawkes
I thought it may have something to do with using scoped in my styles but removing that hasn't changed anything. @Hawkes - Mark Williams
I ended up doing a custom import of both Bootstrap and Bootstrap Vue, then using PurifyCSS to trim any unused styles from the imported modules. It helped, but the CSS resulting from yarn build is still 1.2MB which seems excessively large. - Hawkes

1 Answers

0
votes

This has been resolved :)

The issue was caused by including the bootstrap scss files in an scss file that was @imported into Vue's main.js so that Bootstrap's mixins could be used on single file component's styles

Removing the Bootstrap scss imports and importing the bootstrap css files in the main.js file fixed the issue.