在 Vite 的 monorepo 架构中动态导入公共包中的静态 JS 文件,需遵循以下步骤:
1. 配置 Monorepo 项目结构- 使用工具(如 pnpm、yarn 或 npm)创建工作区,确保公共包(如 @common/utils)和主项目位于同一工作区根目录下。
- 示例目录结构:monorepo-root/├── packages/│ ├── common-utils/ # 公共包│ │ ├── src/│ │ │ └── loaders.js # 静态 JS 文件(ESM 格式)│ │ └── package.json # 声明包名(如 "name": "@common/utils")│ └── main-project/ # 主项目│ ├── vite.config.js│ └── src/
2. 在公共包中导出静态 JS 文件- 确保 JS 文件使用 ESM 语法:在公共包的 src/ 目录下创建 JS 文件,使用 export 导出函数或变量。// packages/common-utils/src/loaders.jsexport const loadJs = (url) => { return new Promise((resolve, reject) => { const script = document.createElement('script'); script.src = url; script.onload = resolve; script.onerror = reject; document.head.appendChild(script); });};
- 更新公共包的 package.json:指定 "type": "module" 以强制使用 ESM,或确保文件扩展名为 .mjs。
3. 在主项目中安装并导入公共包- 链接公共包:通过工作区命令(如 pnpm add @common/utils)将公共包安装到主项目,避免手动复制文件。
- 动态导入公共包中的 JS 函数:
直接导入导出成员:若公共包已正确导出,直接使用包名导入。// 主项目中的代码import { loadJs } from '@common/utils';// 动态加载外部 JS 文件loadJs('
https://example.com/external.js'
) .then(() => console.log('JS loaded')) .catch(err => console.error('Failed to load:', err));动态导入整个模块:若需按需加载,可使用 import() 动态导入(返回 Promise)。const module = await import('@common/utils');module.loadJs('
https://example.com/external.js'
);
4. 处理非 ESM 模块的兼容性- 若公共包的 JS 文件使用 CommonJS(CJS):
在 Vite 中,CJS 模块需通过默认导入访问(如 import utils from '@common/utils'),然后使用 utils.loadJs。
更好的方案是修改公共包代码为 ESM,或在 vite.config.js 中配置 optimizeDeps 强制转换:// vite.config.jsexport default { optimizeDeps: { include: ['@common/utils'], },};
5. 避免使用相对路径- 始终使用包名导入:如 @common/utils,而非 ../common-utils/src/loaders.js。这确保 Vite 能正确解析工作区依赖。
6. 验证 Vite 配置- 检查 resolve.alias:若包名未自动解析,需在 vite.config.js 中手动配置别名:import { fileURLToPath, URL } from 'node:url';export default { resolve: { alias: { '@common/utils': fileURLToPath(new URL('../common-utils/src', import.meta.url)), }, },};
7. 运行和调试关键注意事项- ESM 规范:确保公共包的 JS 文件使用 export 而非 module.exports。
- 动态加载时机:若在客户端动态加载 JS,需处理异步逻辑(如 Promise 或 async/await)。
- TypeScript 支持:若使用 TS,在公共包中添加 types 字段到 package.json,或创建 index.d.ts 声明文件。
通过以上步骤,可实现 Vite monorepo 中公共包静态 JS 文件的动态导入,同时保持代码可维护性和模块化。