Taro插件:defineConstants自动生成TS声明文件

场景
通常我们会使用Typescript来开发Taro项目 并使用Taro约定的config
选项defineConstants
来定义我们项目中的全局变量(如:cdn地址)

但是当我们在使用这些全局变量时,会发现编辑器中(如:Webstorm)会报以下错误:

这是为什么呢 我们明明在全局已经定义过了叫cdnURL
的变量 为啥说找不到呢🤔
分析
简单介绍下我编写这个插件的心路历程嗷:
-
首先分析错误提示信息 🧐
- 前置错误类型提示TS2304 说明是Typescript在对变量进行静态校验的时候找不到
cdnUrl
这个变量
- 前置错误类型提示TS2304 说明是Typescript在对变量进行静态校验的时候找不到
-
思考变量存在哪里 🤔
-
通过官网defineConstants的介绍了解到 他是基于Webpack DefinePlugin来实现的声明全局变量的功能 它大概是个什么东西呢🤔
//webpack.config.js const webpack = require('webpack'); module.exports = { entry: { index: "index.js" }, output: { path: "dist/", filename: "[name].js", }, plugins: [ new webpack.DefinePlugin({ simba: 'sweeeet' }) ] }; //index.js console.log(simba); // 编译结果 function(module, exports, __webpack_require__) { console.log((sweeeet)); }
说明
defineConstants
的变量是通过打包生成的变量再给到Taro进行内部的处理 所以Typescript自然也没办法解析到我们内部的变量📦
-
-
查阅官方issues 有无相关内容
-
翻阅了接近6页的issues 找到了1条相关并给出解决方案的issues
-
这样确实可以解决TS报错的问题 但是如果有几十个这样的全局变量 然后全部还要自己手动去声明一次 感觉有点不太聪明的亚子 既然提供了这样的配置选项 感觉可以做的更好一点吧
-
-
于是乎我就开搞了!😎
开搞
首先先了解了下Taro插件机制和Wepack类似 提供了主要的三个Hook:
// plugin.js
export default (ctx, options) => {
// plugin 主体
ctx.onBuildStart(() => {
console.log('编译开始!')
})
ctx.onBuildFinish(() => {
console.log('Webpack 编译结束!')
})
ctx.onBuildComplete(() => {
console.log('Taro 构建完成!')
})
}
然后再项目配置中如何引入(因为是独立的功能,这里暂时先不考虑使用presets插件集的方式)
// config/index.js
const config = {
plugins: [
// 引入 npm 安装的插件
'@tarojs/plugin-mock',
// 引入 npm 安装的插件,并传入插件参数
[
'@tarojs/plugin-mock',
{
mocks: {
'/api/user/1': {
name: 'judy',
desc: 'Mental guy',
},
},
},
],
// 从本地绝对路径引入插件,同样如果需要传入参数也是如上
'/absulute/path/plugin/filename',
],
}
(!!!)Plugin支持本地绝对路径 所以可以在项目本地开发 但是如果没有使用打包工具(如:Rollup),在项目中开发上述plugin.js
的示例代码要改为es5的模块
// plugin.js
module.exports = (ctx, options) => {
// plugin 主体
ctx.onBuildStart(() => {
console.log('编译开始!')
})
ctx.onBuildFinish(() => {
console.log('Webpack 编译结束!')
})
ctx.onBuildComplete(() => {
console.log('Taro 构建完成!')
})
}
(我习惯自己开发npm包了 所以就不采用这种方式 愿意折腾的可以继续往下看0.0)
OK 知己知彼百战百胜 开始搭建我们的npm包环境
-
npm init
创建我们项目的package.json
-
创建打包相关的目录(如:src/dist/lib) 配置打包使用的依赖 我这边使用的是Rollup/Typescript来进行开发
(详细打包相关的不展开说明了 可以去看下我的github)
-
核心逻辑是
generateDeclare
函数- 递归读取我们
defineConstants
中的对象 通过JSON.parse
&typeof value
来确定我们最终定义的类型 - (!!!)特殊情况说明:这里考虑到大家总是对
defineConstants
中定义字符串出错不敏感 因为如果要定义字符串必须通过JSON.stringify
/'"xxx"'
来定义 特别是后者这种模式我感觉是很反人类的 所以我在开发这块儿的时候给这里做了特殊处理 详见代码
- 递归读取我们
-
写入我们的类型声明文件
- 插件主体这块我考虑过后只使用了
onBuildStart
钩子来处理逻辑 - 这里考虑到如果是打包成生产环境(即
production
)不需要声明文件 所以直接逻辑会直接中断 写一个提示语告诉用户开始编译- 调用node fs模块中的
writeFile
异步写入声明文件- 这块对比了下
options
中使用追加写入 or 覆盖写入的差别 认为不需要再额外写特殊的diff逻辑 直接覆盖也不会有很大的性能开销 所以还是选择了覆盖写入
- 这块对比了下
写一个编译结束时的结束语
- 插件主体这块我考虑过后只使用了
-
编写单测(还没整 -
将
package.json
中的version字段改为beta版本version: 0.0.1-beta
-
添加
.npmrc
文件写入自己的token 执行npm publish
发布
食用方法 🔨
#安装依赖
npm install -D taro-plugin-auto-declare-define-constants
#or yarn
yarn add -D taro-plugin-auto-declare-define-constants
// config/index.js
const config = {
//...
plugins: [
'taro-plugin-auto-declare-define-constants'
]
//...
}
#最后将项目跑起来 看下项目根目录是否出现「defineConstants.d.ts」
npm run dev:weapp
#or yarn
yarn dev:weapp
这样我们就对defineConstants
进行全局的类型声明 解决了TS的报错问题 编辑器也不会报错啦 🎉
- 如果有其他的更好的建议 欢迎给我提issues thx 🤓