如何用Vite+TypeScript打包NPM包实现多路径导入
我正在使用Vite和TypeScript开发NPM组件库,目录结构包含src/atoms、src/molecules等子模块,当前仅能通过根路径@mypackage/library导入组件,希望实现@mypackage/library/atom这类分模块导入路径。我已配置package.json的exports字段,但在Laravel+React项目中导入子模块(如@workdigital/component-library-react/theme)时出现运行时错误:
Failed to load url /resources/js/theme/ThemeProvider (resolved id: /resources/js/theme/ThemeProvider). Does the file exist?
但无TypeScript报错且IntelliSense正常。以下是相关配置:
目录结构
- src - atoms - molecules - organism - index.ts (当前仅导入导出所有内容)
package.json相关配置
{ "entry": "src/index.ts", "main": "dist/index.cjs.js", "module": "dist/index.es.js", "types": "dist/index.d.ts", "files": [ "dist", "src" ], "exports": { ".": { "import": "./dist/index.es.js", "require": "./dist/index.cjs.js", "types": "./dist/index.d.ts" }, "./package.json": "./package.json", "./atoms": "./src/atoms/index.ts", "./molecules": "./src/molecules/index.ts", "./organisms": "./src/organisms/index.ts", "./theme": "./src/theme/index.ts" }, }
vite.config.ts
import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import dts from 'vite-plugin-dts'; import path from 'path'; export default defineConfig({ build: { lib: { entry: path.resolve(__dirname, 'src/index.ts'), formats: ['es', 'cjs'], name: '@workdigtital/component-library-react', fileName: (format) => `index.${format}.js` }, rollupOptions: { external: ['react', 'react-dom'], output: { globals: { react: 'React', 'react-dom': 'ReactDOM' }, exports: 'named' } } }, plugins: [react(), dts({ insertTypesEntry: true })], resolve: { alias: { '@': path.resolve(__dirname, './src') } } });
问题核心是package.json的exports配置直接指向了源码文件,而Laravel+React的构建工具无法正确处理未编译的源码,需要让子模块指向编译后的dist产物,同时修改Vite配置构建子模块入口。
1. 修改Vite配置,构建多模块入口
当前Vite仅构建了根入口,需要添加子模块的单独构建配置,让每个子模块生成对应的编译文件:
export default defineConfig({ build: { lib: { // 配置多入口映射 entry: { index: path.resolve(__dirname, 'src/index.ts'), atoms: path.resolve(__dirname, 'src/atoms/index.ts'), molecules: path.resolve(__dirname, 'src/molecules/index.ts'), organisms: path.resolve(__dirname, 'src/organisms/index.ts'), theme: path.resolve(__dirname, 'src/theme/index.ts'), }, formats: ['es', 'cjs'], name: '@workdigtital/component-library-react', // 调整文件名规则,让子模块产物对应路径 fileName: (format, entryName) => `${entryName}.${format}.js` }, rollupOptions: { external: ['react', 'react-dom'], output: { globals: { react: 'React', 'react-dom': 'ReactDOM' }, exports: 'named' } } }, plugins: [react(), dts({ insertTypesEntry: true })], resolve: { alias: { '@': path.resolve(__dirname, './src') } } });
2. 更新package.json的exports字段
将子模块的指向改为dist目录下的编译产物,同时补充类型文件路径:
{ "entry": "src/index.ts", "main": "dist/index.cjs.js", "module": "dist/index.es.js", "types": "dist/index.d.ts", "files": [ "dist", "src" ], "exports": { ".": { "import": "./dist/index.es.js", "require": "./dist/index.cjs.js", "types": "./dist/index.d.ts" }, "./package.json": "./package.json", "./atoms": { "import": "./dist/atoms.es.js", "require": "./dist/atoms.cjs.js", "types": "./dist/atoms.d.ts" }, "./molecules": { "import": "./dist/molecules.es.js", "require": "./dist/molecules.cjs.js", "types": "./dist/molecules.d.ts" }, "./organisms": { "import": "./dist/organisms.es.js", "require": "./dist/organisms.cjs.js", "types": "./dist/organisms.d.ts" }, "./theme": { "import": "./dist/theme.es.js", "require": "./dist/theme.cjs.js", "types": "./dist/theme.d.ts" } } }
3. 验证类型文件生成
vite-plugin-dts会根据配置自动生成每个子模块的.d.ts文件,确保insertTypesEntry: true开启,构建后dist目录下会出现对应子模块的类型文件。
4. 重新构建并测试
执行npm run build,此时dist目录会生成所有子模块的编译产物,重新发布组件库或通过npm link在本地Laravel项目中测试,即可正常使用@workdigital/component-library-react/theme这类分模块导入路径。
额外检查点
- 确认
src/atoms、src/theme等子目录下存在index.ts,且正确导出了模块内容。 - 本地测试时刷新Laravel项目的依赖缓存,避免旧配置影响。
内容的提问来源于stack exchange,提问作者Snake_py

