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

Laravel修改resources目录JS文件后,npm run dev不生效如何解决?

Laravel Vite开发模式下JS修改不生效的解决思路

问题描述

我是编程新手,近期正在使用Laravel框架开发网站。发现每次修改/resources目录下的JavaScript文件时,必须运行npm run build才能在网站上看到更新。了解到Vite后,使用npm run dev修改JS文件仍无法生效,附上vite配置、package.json及文件夹结构,恳请各位提供解决思路,谢谢。

我的Vite配置

import { defineConfig } from 'vite';
import laravel, { refreshPaths } from 'laravel-vite-plugin';

import fs from 'fs-extra';
import path from 'path';

const folder = {
    src: "resources/", // 源文件目录
    src_assets: "resources/", // 源资源目录
    dist: "public/", // 构建输出目录
    dist_assets: "public/build/" // 构建资源输出目录
};

export default defineConfig({
    build: {
        manifest: true,
        rtl: true,
        outDir: 'public/build/',
        cssCodeSplit: true,
        rollupOptions: {
            output: {
                assetFileNames: (css) => {
                    if (css.name.split('.').pop() == 'css') {
                        return 'css/' + `[name]` + '.min.' + 'css';
                    } else {
                        return 'icons/' + css.name;
                    }
                },
                entryFileNames: 'js/' + `[name]` + `.js`,
            },
        },
    },
    plugins: [
        laravel(
            {
                input: [
                    'resources/scss/bootstrap.scss',
                    'resources/scss/icons.scss',
                    'resources/scss/app.scss',
                    'resources/scss/custom.scss',
                ],
                refresh: [
                    ...refreshPaths,
                    'resources/views/**',
                ],
            }
        ),
        {
            name: 'copy-specific-packages',
            async writeBundle() {

                try {
                    // 复制图片、json、字体和js
                    await Promise.all([
                        fs.copy(folder.src_assets + 'fonts', folder.dist_assets + 'fonts'),
                        fs.copy(folder.src_assets + 'images', folder.dist_assets + 'images'),
                        fs.copy(folder.src_assets + 'js', folder.dist_assets + 'js'),
                        fs.copy(folder.src_assets + 'json', folder.dist_assets + 'json'),
                    ]);
                } catch (error) {
                    console.error('复制资源出错:', error);
                }

                const outputPath = path.resolve(__dirname, folder.dist_assets); // 调整目标路径
                const configPath = path.resolve(__dirname, 'package-copy-config.json');

                try {
                    const configContent = await fs.readFile(configPath, 'utf-8');
                    const { packagesToCopy } = JSON.parse(configContent);

                    for (const packageName of packagesToCopy) {
                        const destPackagePath = path.join(outputPath, 'libs', packageName);

                        const sourcePath = (fs.existsSync(path.join(__dirname, 'node_modules', packageName + "/dist"))) ?
                            path.join(__dirname, 'node_modules', packageName + "/dist")
                            : path.join(__dirname, 'node_modules', packageName);

                        try {
                            await fs.access(sourcePath, fs.constants.F_OK);
                            await fs.copy(sourcePath, destPackagePath);
                        } catch (error) {
                            console.error(`包 ${packageName} 不存在。`);
                        }
                    }
                } catch (error) {
                    console.error('复制并重命名包出错:', error);
                }
            },
        },

    ],
});

package.json

{
    "private": true,
    "name": "cfm",
    "version": "1.0",
    "type": "module",
    "author": "test",
    "scripts": {
        "clean": "rimraf public/build",
        "dev": "vite dev",
        "build": "npm run clean && vite build",
        "build-rtl": "rtlcss public/build/css/app.min.css & rtlcss public/build/css/bootstrap.min.css"
    },
    "devDependencies": {
        "@popperjs/core": "^2.10.2",
        "axios": "^1.6.5",
        "laravel-vite-plugin": "^1.0.1",
        "lodash": "^4.17.19",
        "popper.js": "^1.12",
        "postcss": "^8.3.5",
        "postcss-import": "^14.0.1",
        "resolve-url-loader": "^5.0.0",
        "rimraf": "^5.0.1",
        "rtlcss": "^3.0.0",
        "sass-loader": "^11.0.1",
        "vite": "^5.0.12"
    },
    "dependencies": {
        "@ckeditor/ckeditor5-build-classic": "^38.0.1",
        "@simonwep/pickr": "^1.8.2",
        "@tarekraafat/autocomplete.js": "^10.2.7",
        "aos": "^2.3.4",
        "apexcharts": "^3.41.0",
        "bootstrap": "5.3.2",
        "card": "^2.5.4",
        "chart.js": "4.3.0",
        "choices.js": "^10.2.0",
        "cleave.js": "^1.6.0",
        "dom-autoscroller": "^2.3.4",
        "dragula": "^3.7.3",
        "dropzone": "^6.0.0-beta.2",
        "echarts": "^5.4.2",
        "feather-icons": "^4.29.0",
        "fg-emoji-picker": "^1.0.1",
        "filepond": "^4.30.4",
        "filepond-plugin-file-encode": "^2.1.10",
        "filepond-plugin-file-validate-size": "^2.2.8",
        "filepond-plugin-image-exif-orientation": "^1.0.11",
        "filepond-plugin-image-preview": "^4.6.11",
        "flatpickr": "^4.6.13",
        "fs": "^0.0.1-security",
        "fs-extra": "^11.2.0",
        "fullcalendar": "^6.1.8",
        "glightbox": "^3.2.0",
        "gmaps": "^0.4.25",
        "gridjs": "^6.0.6",
        "isotope-layout": "^3.0.6",
        "jsvectormap": "1.4.2",
        "leaflet": "^1.9.4",
        "list.js": "^2.3.1",
        "list.pagination.js": "^0.1.1",
        "masonry-layout": "^4.2.2",
        "moment": "^2.30.1",
        "multi.js": "^0.5.3",
        "node-waves": "^0.7.6",
        "nouislider": "^15.7.0",
        "particles.js": "^2.0.0",
        "prismjs": "^1.29.0",
        "quill": "^1.3.7",
        "rater-js": "^1.0.1",
        "sass": "^1.69.5",
        "shepherd.js": "^11.1.1",
        "simplebar": "^6.2.5",
        "sortablejs": "^1.15.0",
        "sweetalert2": "^11.6.13",
        "swiper": "^9.3.2",
        "toastify-js": "^1.12.0",
        "wnumb": "^1.2.0"
    }
}

文件夹结构

resources目录下包含fonts、images、js、json、scss、views子目录,public目录下有build文件夹。


解决步骤

1. 将JS文件加入Vite入口配置

当前Vite配置的laravel插件input数组仅包含SCSS文件,未添加JS文件。Vite只会监听入口文件及其依赖的变化,需把你的JS主文件添加进去:

laravel({
    input: [
        'resources/scss/bootstrap.scss',
        'resources/scss/icons.scss',
        'resources/scss/app.scss',
        'resources/scss/custom.scss',
        // 添加你的JS入口文件,比如主逻辑文件
        'resources/js/app.js'
    ],
    refresh: [
        ...refreshPaths,
        'resources/views/**',
    ],
})

若有多个JS文件,全部添加到input数组即可。

2. 移除手动复制JS的逻辑

自定义的copy-specific-packages插件中,writeBundle钩子仅在vite build时触发,开发模式下不会执行,导致修改JS后无法自动同步到public目录。且Vite开发模式通过HMR(热模块替换)直接推送更新到浏览器,无需手动复制文件。

删除插件中复制JS的代码:

// 移除这一行
fs.copy(folder.src_assets + 'js', folder.dist_assets + 'js'),

3. 确保视图正确使用Vite指令

Blade视图中必须使用@vite指令引入资源,不能直接引用public/build下的静态文件:

{{-- 正确写法 --}}
@vite(['resources/js/app.js', 'resources/scss/app.scss'])

{{-- 错误写法:直接引用静态文件,开发模式下不会更新 --}}
<script src="{{ asset('build/js/app.js') }}"></script>

4. 检查开发服务器状态

  • 确保npm run dev命令正在运行,终端无报错
  • 打开浏览器控制台,查看是否有Vite连接错误(如端口被占用)
  • 清除浏览器缓存或使用无痕模式测试,避免加载旧的JS缓存文件

5. 可选:调整Vite资源处理逻辑

若JS文件依赖图片、字体等静态资源,无需手动复制,Vite会自动处理资源引用路径。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 20:43:16