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

如何解决 monorepo 中 npm workspaces 与 Vite 的缓存问题

问题背景

项目基于SvelteKit + Vite + npm workspaces,架构如下:

- apps/
    - project-a/
        - package.json
        - vite.config.ts
- packages/
    - common-lib-a/
        - package.json
        - vite.config.ts
- package.json

project-a的package.json中依赖@namespace/common-lib-a(版本^0.0.1),其vite.config.ts配置:

import { sveltekit } from '@sveltejs/kit/vite';
import dns from 'dns';
import Icons from 'unplugin-icons/vite';
import { defineConfig } from 'vite';
import { purgeCss } from 'vite-plugin-tailwind-purgecss';

const hash = Math.floor(Math.random() * 90000) + 10000;
dns.setDefaultResultOrder('verbatim');

export default defineConfig({
    plugins: [
        sveltekit(),
        purgeCss(),
        Icons({
            compiler: 'svelte'
        })
    ],
    resolve: {
        preserveSymlinks: true,
        dedupe: ['@namespace/common-lib-a']
    },
    optimizeDeps: {
        exclude: ['@namespace/common-lib-a']
    },
    build: {
        rollupOptions: {
            output: {
                entryFileNames: `[name]${hash}.js`,
                chunkFileNames: `[name]${hash}.js`,
                assetFileNames: `[name]${hash}.[ext]`
            }
        }
    }
});

根package.json的脚本用于监听common-lib-a变更并重启服务:

"scripts": {
    "dev-project-a": "npm run build -w @namespace/common-lib-a && npm run dev -w @namespace/project-a",
    "watch-project": "nodemon -x 'npm run dev-project-a' -e svelte,js,ts,json --watch packages/common-lib-a/src"
}

问题:修改common-lib-a后,必须清除浏览器缓存,变更才会在project-a的dev服务中生效,如何解决?

解决办法

1. 让common-lib-a开启watch模式,避免重复重启project-a

现在每次改库都要重新构建再重启dev服务,既慢又容易触发缓存。直接给common-lib-a加个watch脚本,实时编译:

  • 修改common-lib-a/package.json的scripts:
    "scripts": {
        "build": "vite build",
        "watch": "vite build --watch"
    }
    
  • 根package.json的scripts改成并行启动:
    "scripts": {
        "dev-project-a": "npm run watch -w @namespace/common-lib-a & npm run dev -w @namespace/project-a",
        "watch-project": "npm run dev-project-a"
    }
    

这样库改了会自动编译,不用重启dev服务,缓存问题自然少很多。

2. 给Vite加配置,禁用依赖缓存

在project-a/vite.config.ts里加这些配置,让Vite不对common-lib-a搞缓存:

export default defineConfig({
    // ...原有配置
    server: {
        watch: {
            // 监听库的构建产物变化
            include: ['../packages/common-lib-a/dist/**/*']
        }
    },
    optimizeDeps: {
        exclude: ['@namespace/common-lib-a'],
        // 直接禁用预构建缓存
        cacheDir: false
    },
    // 关闭Vite的文件系统缓存
    cacheDir: false
});

要是极端情况HMR不生效,还能把server.hmr.fullReload设为true,强制全页刷新。

3. 给库的构建产物加动态哈希

在common-lib-a/vite.config.ts里配置构建输出带哈希,这样每次编译出来的文件名都不一样,浏览器自动加载新文件,不用手动清缓存:

import { defineConfig } from 'vite';

export default defineConfig({
    build: {
        rollupOptions: {
            output: {
                entryFileNames: '[name].[hash].js',
                chunkFileNames: '[name].[hash].js',
                assetFileNames: '[name].[hash].[ext]'
            }
        }
    }
});

4. 直接链接库的源码,跳过构建环节

确保npm workspaces已经把common-lib-a软链接到project-a/node_modules(根目录跑npm install就行),然后在project-a/vite.config.ts里加别名指向源码:

resolve: {
    preserveSymlinks: true,
    dedupe: ['@namespace/common-lib-a'],
    alias: {
        '@namespace/common-lib-a': '../packages/common-lib-a/src'
    }
}

这样Vite直接监听源码变化,HMR实时生效,连库的构建步骤都省了,效率更高。

5. 开发环境禁用浏览器缓存

在project-a/src/hooks.server.ts里加响应头,强制浏览器不缓存:

import type { Handle } from '@sveltejs/kit';

export const handle: Handle = async ({ event, resolve }) => {
    const response = await resolve(event);
    if (import.meta.env.DEV) {
        response.headers.set('Cache-Control', 'no-cache, no-store, must-revalidate');
        response.headers.set('Pragma', 'no-cache');
        response.headers.set('Expires', '0');
    }
    return response;
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 14:51:05