当前位置: 首页 > Web前端 > vue.js

用typescript开发一个Vue第三方插件(一)

时间:2023-04-01 01:28:21 vue.js

写一个基于qiankun微前端的Vue专用插件本项目的目的是写一个基于qiankun的Vue专用插件qiankun的微前端框架,方便在这里使用Vue项目。一开始想用js写。但是配合目前第三方类库的开发,必须要考虑通用性。如果是用js写的,如果使用的项目是typescriptvue项目,会遇到缺少类型定义文件的问题。所以用ts开发。这样,声明文件的生成就变得容易了。项目地址https://github.com/Hades-li/qiankun-vue安装yarnaddqiankun-vuenpminstallqiankun-vue--save从vue-cli到手写webpack配置vue-cli是Vue官方的脚手架工具,傻瓜-likeBuild项目,非常好用。但也许它更适合开发一整套应用程序,而不是一个小型的第三方库。目录结构build:存放webpack配置文件(稍后手写)dist:最终文件输出目录example:用于展示的例子。其实这个目录就是原来vue-cli生成的src目录,但是由于我们要开发第三方库,src目录是用来存放库的源码的,所以我们改了下目录。src:放置源代码的地方。types:typescript类型定义文件使用vue-cli官方的构建方式(deprecated)vue-cli提供了官方的构建库方式vue-cli-servicebuild--targetlib--namemyLib[entry]此次构建的结果为和官方展示的一样,会同时生成多个js库文件。在实际项目参考中,我们只用到一个。也就是说,我们只是不想生成一堆我们不想要的东西。修改vue.config.jsbuild(deprecated)放弃使用vue-cli官方方法。剩下的方法就是重写vue.config.js配置,快速实现构建。下面是一些重要的代码片段来解释if(isProd){config.entry('index').clear().add('./src/index.ts')config.output.filename('index.js')//输出文件名.libraryTarget('umd')//打包type.library('QiankunVue')//全局变量名...}在生产环境中,入口文件是src路径下的入口文件。输出文件设置为index.js,目标类型为umd格式,全局变量为QiankunVueif(!isProd){config.entry('index').clear().add('./example/main.ts')}在开发环境中,目的不是为了打包输出src的源码,而是为了运行example中的例子。所以将入口文件设置为example下的main.ts文件。//排除Vueconfig.externals({vue:{root:'Vue',commonjs:'vue',commonjs2:'vue',amd:'vue'}})由于我们开发的是vue插件,所以需要添加vue被排除在外。此时执行yarnrunbuild后,dist目录下只会生成一个index.js文件。当然,由于我没有屏蔽html模板插件,所以还是会生成index.html。最后放弃了以上两种vue-cli的构建方式,因为我发现打包后的index.js文件大小高达120+KB。这个尺寸明显偏大。但是我找不到原因。webpack配置的这次改动的目的是让它完全独立于vue-cli,开发和生产环境完全定制化。build.js-以函数式方式执行webpack打包。(暂时放弃)以下是webpack.config.base.js基本配置的一些关键代码片段,包括生产和开发环境需要配置module.rules//预处理.ts文件{test:/\.ts$/,use:['babel-loader',{loader:'ts-loader',options:{appendTsSuffixTo:[/\.vue$/],transpileOnly:true}}],exclude:/node_modules/},//预处理。vuefile{test:/\.vue$/,loader:'vue-loader'},这两段代码主要是预处理.ts文件和.vue文件。babel-loader是可选的,它的作用是将es6代码转换为es5以兼容浏览器。现在的chrome、edge、firefox等现代浏览器对es6甚至es7的支持都很好。不加babel-loader可以进一步减小打包文件的体积,运行效率可以更高,但是本着可能还有人还在用ie的态度,还是加吧。//预处理scss{test:/\.s[ac]ss$/,use:[env.NODE_ENV!=='production'?'vue-style-loader':MiniCssExtractPlugin.loader,'css-loader','sass-loader']},//预处理css{test:/\.css$/,use:[env.NODE_ENV!=='生产'?'vue-style-loader':MiniCssExtractPlugin.loader,'css-loader']},预处理scss和css样式。其实在vue-cli搭建的项目中,也是可以支持less和stylu另外两个预编译样式文件的,只是我们现在自定义webpack配置,本着随用随用的原则,我们只需要满足我们自己的要求刚需。//预处理图像{test:/\.(png|jpe?g|gif|webp)(\?.*)?$/,loader:'url-loader',options:{limit:4096,esModule:false,//为5.0及以上版本添加fallback:{loader:'file-loader',options:{name:'img/[name].[hash:8].[ext]'}}}}预处理图像,这里让我们重点说说这个配置项的坑。该配置用于解析图片/文件路径,并对图片进行base64转换。一开始直接用vue-cli查了一个webpack的配置文件,把这部分复制过来。与上面的代码相比,只有esModule没有参数:false。运行结果是所有图片都没有显示出来,图片的查看路径是这样的。所以加上esModule:false就可以了。上面的原因是vue-loader解析.vue文件时,标签会被编译成createElement('img',{attrs:{src:require('../image.png')//commonJS语法导入函数现在这是一个模块请求}})require是commonJS规范的导入函数。url-loader默认识别es6的import语法,即import。所以最终转换后的代码无法正常显示图片。esModule:false是开启commonJS导入方式。那为什么vue-cli搭建的项目不需要配置这个参数呢?因为vue-cli使用的url-loader版本号还是2.x.x。而且最新版本已经到了4.x.x。老版本的url-loader没有这个限制机制。新版url-loader鼓励采用es6标准规范导入文件。commonJs是nodejs的规范。pluginsplugins:[newVueLoaderPlugin(),//配合vue-loadernewForkTsCheckerWebpackPlugin(),//单独线程运行ts-loader类型检查,加快编译速度newwebpack.DefinePlugin({'process.env':{NODE_ENV:'"'+env.NODE_ENV+'"',BASE_URL:'"/"'}}),//将全局变量添加到浏览器代码newFriendlyErrorsPlugin(),//友好的错误消息newMiniCssExtractPlugin(),//cssextractionnewCaseSensitivePathsPlugin()//Strictpathcase]上面的插件基本上是查看vue-cli后添加的。有的可以不加,但是加了对开发会有很大的帮助。webpack.config.prd.js生产环境配置。module.exports=merge(baseConf({NODE_ENV:env}),{模式:env,入口:'./src/index.ts',输出:{路径:resolve('dist'),文件名:'index.js',publicPath:'/',chunkFilename:'js/[name].[contenthash:8].js',libraryTarget:'umd',library:'QiankunVue'},externals:{vue:{root:'Vue',commonjs:'vue',commonjs2:'vue',amd:'vue'}},plugins:[//清理dist文件夹newCleanWebpackPlugin()]})生产环境配置比较简单,先通过webpack-mergeplugin合并webpack.config.base.js的配置,添加入口和输出配置项,使用cleanwebpackPlugin插件清理dist目录,一键打包即可。webpack.config.dev.js开发环境中的配置。入口:'./example/main.ts',输出:{路径:解析('dist'),文件名:'app.js',publicPath:'/'},devServer:{contentBase:解析('dist'),port:8080,hot:true,progress:true,//0-100%进度提示quiet:true//去除一堆警告信息},devtool:'eval-source-map',开发环境,也合并webpack.config.base.js,重写入口指向example/main.ts。配置开发服务器devServer,记住,不要忘记安装包webpack-dev-server。pluginsplugins:[newwebpack.HotModuleReplacementPlugin(),//支持模块热替换newHtmlWebpackPlugin({title:'qiankun',template:resolve('public/index.html'),favicon:resolve('public/favicon.ico')}),//配置index.html模板newCopyWebpackPlugin([{from:resolve('public'),to:resolve('dist'),toType:'dir',ignore:['index.html']}])//复制插件,用于将一些不参与打包的静态资源复制到dist目录下]这些是开发模式下必备的插件。上面的webpack配置比vue-cli提供的要少很多。比如我们连loader的配置项都没有为.js文件编译,因为我们的项目纯粹是针对ts的。实际用vue-cli搭建的ts项目,可以用于js和ts的混合开发。但是纯手写webpack的目的就是只匹配你需要的。本期重点介绍webpack配置,这也是本项目的难点之一,费时费力。遗留问题1-无法自动生成*.d.ts文件来开发标准的js库,无论是用js开发还是ts开发,现在,都得自己写ts类型声明文件。像lodash和jquery这样的著名库在早期是没有声明文件的。导致如果用于ts项目开发,无法进行类型检测机制(早期没有typescript)。但是现在,这些库都添加了类型声明。类型声明可以手写,但是太费力了。最好的当然是自动生成。根据官方说法,在tsconfig.js中配置declaration:true属性时,可以自动生成。但实际上什么都没有发生。当然,如果直接用tsc--declaration命令行编译,是可以生成的。这是目前的遗留问题。如果有知道解决办法的高手,忘了指教。