You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel/Vue3项目生产构建后b-modal组件失效求助

Laravel+Vue3项目中bootstrap-vue-next的b-modal生产构建后失效问题

Laravel+Vue3项目使用bootstrap-vue-next的b-modal组件,开发环境执行npm run dev时组件正常工作,但执行npm run prod(即vite build)进行生产资源构建后,模态框完全失效。已尝试更换vite、bootstrap-vue-next版本,甚至改用webpack构建,问题仍未解决。以下是项目相关配置及代码片段,请求排查。


项目配置文件

package.json

{
    "private": false,
    "scripts": {
        "dev": "vite",
        "prod": "vite build"
    },
    "devDependencies": {
        "@popperjs/core": "^2.11.6",
        "@vitejs/plugin-vue": "^4.3.4",
        "axios": "^0.25.0",
        "lodash": "^4.17.19",
        "postcss": "^8.1.14",
        "sass": "^1.56.1",
        "vue": "^3.3.4"
    },
    "dependencies": {
        "@anivive/vue3-form-wizard": "^1.0.1",
        "@chenfengyuan/vue-countdown": "^2.1.1",
        "@ckeditor/ckeditor5-build-classic": "^36.0.1",
        "@ckeditor/ckeditor5-vue": "^4.0.1",
        "@fullcalendar/bootstrap5": "^6.1.5",
        "@fullcalendar/core": "^6.1.5",
        "@fullcalendar/daygrid": "^6.1.5",
        "@fullcalendar/interaction": "^6.1.5",
        "@fullcalendar/list": "^6.1.5",
        "@fullcalendar/timegrid": "^6.1.5",
        "@fullcalendar/vue3": "^6.1.5",
        "@j-t-mcc/vue3-chartjs": "^1.3.0",
        "@vitejs/plugin-vue": "^4.3.4",
        "@vue-leaflet/vue-leaflet": "^0.9.0",
        "@vue/compiler-sfc": "^3.2.47",
        "@vueform/multiselect": "^2.6.1",
        "@vueform/slider": "^2.1.7",
        "@vuelidate/core": "^2.0.0",
        "@vuelidate/validators": "^2.0.0",
        "bootstrap": "^5.2.0",
        "bootstrap-vue-next": "^0.6.7",
        "dropzone": "^6.0.0-beta.2",
        "fullcalendar": "^6.1.4",
        "i18n": "^0.15.1",
        "laravel-vite-plugin": "^0.7.4",
        "leaflet": "^1.9.3",
        "maska": "^1.5.0",
        "metismenujs": "^1.4.0",
        "simplebar-vue": "^2.3.1",
        "simplebar-vue3": "^0.2.0",
        "sweetalert2": "^11.7.3",
        "vite": "^4.4.9",
        "vite-plugin-static-copy": "^0.13.1",
        "vue-carousel": "^0.18.0",
        "vue-cropperjs": "^5.0.0",
        "vue-draggable-next": "^2.1.1",
        "vue-easy-lightbox": "^1.15.0",
        "vue-form-wizard": "^0.8.4",
        "vue-i18n": "^9.2.2",
        "vue-loader": "^17.0.1",
        "vue-router": "^4.1.6",
        "vue3-apexcharts": "^1.4.1",
        "vue3-carousel": "^0.2.13",
        "vue3-datepicker": "^0.3.4",
        "vue3-dropzone": "^2.0.1",
        "vue3-google-map": "^0.15.0",
        "vuelidate": "^0.7.7",
        "vuex": "^4.0.2"
    }
}

vite.config.js

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import { viteStaticCopy } from 'vite-plugin-static-copy'
import vue from '@vitejs/plugin-vue';

export default defineConfig({
    build: {
        manifest: true,
        outDir: 'public/build/',
        cssCodeSplit: true,
        rollupOptions: {
            output: {
                assetFileNames: (assetInfo) => {
                    if (assetInfo.name.endsWith('.css')) {
                        return `css/[name].[hash].css`;
                    }
                    return `assets/[name].[hash][extname]`;
                },
                entryFileNames: 'js/[name].[hash].js',
            },
        },
        chunkSizeWarningLimit: 2000,
        manualChunks: {
            'chunk-vendor': ['vue'],
            'chunk-app': ['app.js', 'app-rtl.scss'],
            'chunk-bootstrap': ['bootstrap.scss'],
            'chunk-icons': ['icons.scss'],
        },
    },
    plugins: [
        laravel({
            input: [
                'resources/sass/app.scss',
                'resources/sass/app-rtl.scss',
                'resources/sass/bootstrap.scss',
                'resources/sass/icons.scss',
                'resources/js/app.js',
            ],
            refresh: true,
        }),
        vue({
            template: {
                transformAssetUrls: {
                    base: null,
                    includeAbsolute: false,
                },
            },
        }),
        viteStaticCopy({
            targets: [
                {
                    src: 'resources/fonts',
                    dest: ''
                },
                {
                    src: 'resources/images',
                    dest: ''
                },
            ],
        })
    ],
    resolve: {
        alias: {
            vue: 'vue/dist/vue.esm-bundler.js',
        },
    },
});

模态框代码片段

<b-modal>
    <div class="card-body">
        <form action="javascript:void(0)" >
            <div class="row">
                <div class="col-lg-4">
                    <div class="mb-3">
                        <label for="name">Name</label>
                        <input type="text" class="form-control" id="name65" placeholder="Enter Device Name" v-model="obj.name" @input="validateName"/>
                        <span v-if="validationErrors.nameError" class="text-danger">{{validationErrors.nameError}}</span>
                    </div>
                </div>
                <div class="col-lg-4">
                    <div class="mb-3">
                        <label for="reg_no6">Unique ID</label>
                        <input type="text" class="form-control" id="reg_no" placeholder="Enter ID emitted by the object" v-model="obj.unique_id" @input="validateRegistration" />
                        <span v-if="validationErrors.unique_idError" class="text-danger">{{validationErrors.unique_idError}}</span>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-lg-12">
                    <div class="text-end">
                        <button type="submit" class="btn btn-primary" @click="saveObj">Submit</button>
                    </div>
                </div>
            </div>
        </form>
    </div>
</b-modal>

排查方向建议

  1. 确认bootstrap-vue-next注册方式:检查app.js中是否全局注册了bootstrap-vue-next,生产构建的tree-shaking可能移除未正确注册的组件。正确全局注册代码:
import { createApp } from 'vue'
import BootstrapVueNext from 'bootstrap-vue-next'
import 'bootstrap-vue-next/dist/bootstrap-vue-next.css'

const app = createApp(App)
app.use(BootstrapVueNext)

若为按需引入,需显式导入并注册b-modal,避免被tree-shaking误删。

  1. 调整tree-shaking配置:vite生产模式默认开启tree-shaking,若组件未被识别为使用中会被移除。可在vite.config.js的build.rollupOptions中添加:
external: ['bootstrap-vue-next'],
// 或临时开启模块保留测试
output: {
  preserveModules: true
}

测试是否解决问题,逐步定位是否为tree-shaking导致。

  1. 检查CSS加载状态:生产构建后,通过浏览器开发者工具查看b-modal元素的类名是否完整,对应的bootstrap-vue-next CSS规则是否加载成功。

  2. 补全组件核心属性:当前代码中的b-modal缺少v-model绑定控制显示/隐藏状态,开发环境宽松规则可能正常工作,但生产环境严格编译会导致组件无法触发。需添加:

<b-modal v-model="showModal">
  <!-- 内容 -->
</b-modal>

并在组件data中定义showModal: false,通过按钮触发showModal = true打开模态框。

  1. 验证依赖版本兼容性:当前使用的bootstrap-vue-next@0.6.7与bootstrap@5.2.0、vue@3.3.4可能存在版本适配问题。尝试升级bootstrap-vue-next到最新稳定版,同时确保bootstrap版本与之匹配。

  2. 查看生产环境控制台错误:打开浏览器开发者工具的Console面板,排查是否有JS报错(如模块未找到、变量未定义等),这类错误通常是组件失效的直接原因。


内容的提问来源于stack exchange,提问作者Law

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 06:15:09