集成第三方库后VueJS组件库Webpack构建目录结构异常问题
问题:Vue组件库集成第三方库后TypeScript声明文件目录结构异常
我将第三方库集成到共享VueJS组件库后,Webpack构建输出的目录结构发生异常,类型声明文件位置错误,导致其他项目无法正确导入该共享库。
正常构建目录结构
- dist - components - ComponentBase.vue.d.ts - index.d.ts - index.d.ts - index.js
集成第三方库后的异常结构
- dist - src - components - ComponentBase.vue.d.ts - index.d.ts - UsesComponent.vue.d.ts - index.d.ts - index.js
我们使用Webpack 4.41.5版本,当前webpack.config.js配置如下:
/* eslint-disable no-undef */ /* eslint-disable object-curly-newline */ const path = require('path'); const VueLoaderPlugin = require('vue-loader/lib/plugin'); const WebpackShellPlugin = require('webpack-shell-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = { entry: './src/index.ts', target: 'web', resolve: { extensions: ['.ts', '.js', '.vue'], modules: [path.resolve(__dirname, './node_modules')], }, module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', }, { test: /\.ts$/, loader: 'ts-loader', options: { appendTsSuffixTo: [/\.vue$/] }, }, { test: /\.js$/, loader: 'babel-loader', exclude: (file) => /node_modules/.test(file) && !/\.vue\.js/.test(file), }, { test: /\.css$/, use: [ 'vue-style-loader', { loader: 'css-loader', options: { importLoaders: 1 }, }, 'postcss-loader', ], }, ], }, output: { filename: 'index.js', path: path.resolve(__dirname, 'dist'), library: 'component_library', libraryTarget: 'umd', }, externals: { 'core-js': { commonjs: 'core-js', commonjs2: 'core-js', amd: 'core-js', root: '_', }, moment: { commonjs: 'moment', commonjs2: 'moment', amd: 'moment', root: '_', }, vue: { commonjs: 'vue', commonjs2: 'vue', amd: 'vue', root: '_' }, 'vue-class-component': { commonjs: 'vue-class-component', commonjs2: 'vue-class-component', amd: 'vue-class-component', root: '_', }, 'vue-property-decorator': { commonjs: 'vue-property-decorator', commonjs2: 'vue-property-decorator', amd: 'vue-property-decorator', root: '_', }, 'vue-router': { commonjs: 'vue-router', commonjs2: 'vue-router', amd: 'vue-router', root: '_', }, vuex: { commonjs: 'vuex', commonjs2: 'vuex', amd: 'vuex', root: '_' }, '@microsoft/signalr': { commonjs: '@microsoft/signalr', commonjs2: '@microsoft/signalr', amd: '@microsoft/signalr', root: '_', }, '@tinymce/tinymce-vue': { commonjs: '@tinymce/tinymce-vue', commonjs2: '@tinymce/tinymce-vue', amd: '@tinymce/tinymce-vue', root: '_', }, 'v-tooltip': { commonjs: 'v-tooltip', commonjs2: 'v-tooltip', amd: 'v-tooltip', root: '_', }, '@types/prismjs': { commonjs: '@types/prismjs', commonjs2: '@types/prismjs', amd: '@types/prismjs', root: '_', }, prismjs: { commonjs: 'prismjs', commonjs2: 'prismjs', amd: 'prismjs', root: '_', }, '@progress/kendo-drawing': { commonjs: '@progress/kendo-drawing', commonjs2: '@progress/kendo-drawing', amd: '@progress/kendo-drawing', root: '_', }, '@progress/kendo-licensing': { commonjs: '@progress/kendo-licensing', commonjs2: '@progress/kendo-licensing', amd: '@progress/kendo-licensing', root: '_', }, '@progress/kendo-svg-icons': { commonjs: '@progress/kendo-svg-icons', commonjs2: '@progress/kendo-svg-icons', amd: '@progress/kendo-svg-icons', root: '_', }, '@progress/kendo-vue-animation': { commonjs: '@progress/kendo-vue-animation', commonjs2: '@progress/kendo-vue-animation', amd: '@progress/kendo-vue-animation', root: '_', }, '@progress/kendo-vue-buttons': { commonjs: '@progress/kendo-vue-buttons', commonjs2: '@progress/kendo-vue-buttons', amd: '@progress/kendo-vue-buttons', root: '_', }, '@progress/kendo-vue-common': { commonjs: '@progress/kendo-vue-common', commonjs2: '@progress/kendo-vue-common', amd: '@progress/kendo-vue-common', root: '_', }, '@progress/kendo-vue-dialogs': { commonjs: '@progress/kendo-vue-dialogs', commonjs2: '@progress/kendo-vue-dialogs', amd: '@progress/kendo-vue-dialogs', root: '_', }, '@progress/kendo-vue-dropdowns': { commonjs: '@progress/kendo-vue-dropdowns', commonjs2: '@progress/kendo-vue-dropdowns', amd: '@progress/kendo-vue-dropdowns', root: '_', }, '@progress/kendo-vue-editor': { commonjs: '@progress/kendo-vue-editor', commonjs2: '@progress/kendo-vue-editor', amd: '@progress/kendo-vue-editor', root: '_', }, '@progress/kendo-vue-form': { commonjs: '@progress/kendo-vue-form', commonjs2: '@progress/kendo-vue-form', amd: '@progress/kendo-vue-form', root: '_', }, '@progress/kendo-vue-inputs': { commonjs: '@progress/kendo-vue-inputs', commonjs2: '@progress/kendo-vue-inputs', amd: '@progress/kendo-vue-inputs', root: '_', }, '@progress/kendo-vue-intl': { commonjs: '@progress/kendo-vue-intl', commonjs2: '@progress/kendo-vue-intl', amd: '@progress/kendo-vue-intl', root: '_', }, '@progress/kendo-vue-layout': { commonjs: '@progress/kendo-vue-layout', commonjs2: '@progress/kendo-vue-layout', amd: '@progress/kendo-vue-layout', root: '_', }, '@progress/kendo-vue-pdf': { commonjs: '@progress/kendo-vue-pdf', commonjs2: '@progress/kendo-vue-pdf', amd: '@progress/kendo-vue-pdf', root: '_', }, '@progress/kendo-vue-popup': { commonjs: '@progress/kendo-vue-popup', commonjs2: '@progress/kendo-vue-popup', amd: '@progress/kendo-vue-popup', root: '_', }, '@progress/kendo-vue-progressbars': { commonjs: '@progress/kendo-vue-progressbars', commonjs2: '@progress/kendo-vue-progressbars', amd: '@progress/kendo-vue-progressbars', root: '_', }, }, plugins: [ new VueLoaderPlugin(), //new WebpackShellPlugin({onBuildEnd: ["pnpm run kendoTest"]}), new CleanWebpackPlugin(), ], };
目前我通过执行shell命令调整输出目录作为临时方案,但这种方式并不合理,恳请提供解决该问题的建议。
解决建议
1. 配置tsconfig.json的输出路径
在项目根目录的tsconfig.json中明确指定TypeScript的输出目录和源码根目录,确保声明文件直接输出到dist下,而非嵌套src结构:
{ "compilerOptions": { "declaration": true, // 开启声明文件生成 "declarationDir": "./dist", // 声明文件输出目录 "outDir": "./dist", // 编译后的JS文件输出目录 "rootDir": "./src", // 源码根目录 // 其他已有配置... }, "include": ["src/**/*"], "exclude": ["node_modules"] }
2. 确保ts-loader使用tsconfig配置
在webpack的ts-loader规则中,显式指定加载项目的tsconfig.json,避免webpack覆盖TypeScript的输出配置:
{ test: /\.ts$/, loader: 'ts-loader', options: { appendTsSuffixTo: [/\.vue$/], configFile: path.resolve(__dirname, 'tsconfig.json') // 指向项目的tsconfig } }
3. 排查第三方库的类型影响
部分第三方库的类型定义可能会干扰TypeScript的路径解析,检查externals配置是否正确排除了所有第三方库的代码及类型,确保只有自身组件库的代码被编译打包。
4. 使用fork-ts-checker-webpack-plugin优化类型处理(可选)
如果项目体积较大,推荐使用fork-ts-checker-webpack-plugin单独处理类型检查和声明文件生成,避免与webpack编译流程冲突,同时提升构建速度:
首先安装插件:
npm install fork-ts-checker-webpack-plugin --save-dev
然后修改webpack配置:
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); module.exports = { // ...其他配置 module: { rules: [ { test: /\.ts$/, loader: 'ts-loader', options: { appendTsSuffixTo: [/\.vue$/], transpileOnly: true // 仅转译,类型检查交给插件处理 } } ] }, plugins: [ // ...其他插件 new ForkTsCheckerWebpackPlugin({ typescript: { configFile: path.resolve(__dirname, 'tsconfig.json'), declaration: true, declarationDir: './dist' } }) ] };
内容的提问来源于stack exchange,提问作者Eliot
相关产品推荐
相关产品推荐

