Open jwdzzhz777 opened 4 years ago
我们写项目的时候最喜欢干的优化应该就是就是解耦了, 把一块功能独立出来封装成独立的插件,清晰整洁,强迫症表示一本满足。
本文就是我从 eggjs 项目中抽出一个组件的过程和坑。
eggjs
首先 啥是插件?
一个插件其实就是一个『迷你的应用』,和应用(app)几乎一样:
Service
中间件
配置
框架扩展等等
Router
Controller
plugin.js
所以抽的时候根据现有结构把相关代码抽出来就好了。
那就开始
先把代码抽出来,放在 /lib/genome 中,做成内置的插件,参考渐进式开发。
/lib/genome
我要抽的是功能类似于 swagger 的自动生成 api 的插件, 主要涉及到这些地方:
swagger
api
helper
config
app.ts
那么抽完大概就这样:
. ├── app │ ├── extend │ │ └── helper.ts │ ├── lib │ │ ├── decorators.ts │ │ ├── types.ts │ │ └── utils.ts │ ├── middleware │ │ └── genome.ts │ └── view │ └── api.njk ├── app.ts ├── config │ └── config.default.ts ├── index.ts └── package.json
note:package.json 是需要的,在这里主要用来声明插件 "eggPlugin": { "name": "genome", "dependencies": [ "nunjucks" ] }
note:package.json 是需要的,在这里主要用来声明插件
package.json
"eggPlugin": { "name": "genome", "dependencies": [ "nunjucks" ] }
因为还在项目中所以不需要 tsconfig.json 以及 package.json 的其他配置。 而且 egg-ts-helper 也会自动添加 d.ts 文件。 自己在写一个额外的 index.d.ts 就可以使用了。
tsconfig.json
egg-ts-helper
d.ts
index.d.ts
import 'egg'; declare module 'egg' { interface Controller { /** 此方法只有 api 装饰器修饰过的 controller 才有!! */ getMetadata(name: string): any; } }
接下来像正常的插件一样使用就可以了,在 plugin.ts 中通过 path 来挂载插件:
plugin.ts
path
nunjucks: { enable: true, package: 'egg-view-nunjucks' }, genome: { enable: true, path: join(__dirname, '../app/lib/plugin/egg-genome') }
note: 因为插件没有 plugin.ts 所以如果插件依赖其他插件的话只能在项目中手动挂载依赖项
运行一下
/path 路由成功跳转我的页面了
/path
抽成单独的组件
接下来就是正式抽离项目了 就像正常的项目一样初始化并吧代码复制进来,不一样的是需要加上自己的 tsconfig.ts了,而且 package.json 也要完整一下。添加一下依赖:
tsconfig.ts
"dependencies": { "reflect-metadata": "^0.1.13" }, "devDependencies": { "egg": "^2.25.0", "tslib": "^1.10.0", "tslint": "^5.20.1", "tslint-config-egg": "^1.0.0", "typescript": "^3.7.2" },
note: 注意添加 tslib 和 tslint-config-egg 两个依赖
tslib
tslint-config-egg
因为发布的插件必须是 .js 的所以需要把 .ts 翻译成 .js 过后再发布,增加 script:
.js
.ts
script
"scripts": { "pub": "yarn tsc && yarn publish --non-interactive && yarn clean", "tsc": "tsc -p tsconfig.json", "clean": "tsc -b --clean" },
添加发布的文件和关键字
"files": [ "index.js", "app.js", "*.d.ts", "app/view/**", "app/**/*.js", "config/**/*.js" ], "keywords": [ "egg", "egg-plugin", "eggPlugin", "genome", "egg-genome" ]
ok, 发布,试试效果
emmmmmmmmmm...
一开始我还以为是引入的问题 导致的不能解构赋值,一直在 tsconfig.json 的 "module": "commonjs", 这一行改来改去, 后来发现 哪怕我 import * as xxx from 引入虽然不报错,但得到的压根是 undefined。 应该是入口 index.ts 有问题。
"module": "commonjs",
import * as xxx from
undefined
index.ts
于是查了查,再看看别人的插件,看来是我对 ts 的了解果然还是不够深,其实是 index.d.ts 的编写有问题,我只写了额外的 egg 声明, 插件的模块声明没有写..好在我们是 ts 写的组件 自动生成一下就好了。 tsconfig.json 加这么一行 "declaration": true,
egg
"declaration": true,
这样所有文件就会自动生成 .js 和 .d.ts 文件了。
.d.ts
然后 package.json 也改一下:
"files": [ "index.js", "app.js", "*.d.ts", "app/view/**", "app/**/*.js", "config/**/*.js", "app/**/*.d.ts", "config/**/*.d.ts" ],
最后把原先 index.d.ts 中的东西挪到 index.ts 中
export * from './app/lib/types'; export * from './app/lib/decorators'; import 'egg'; declare module 'egg' { interface Controller { /** 此方法只有 api 装饰器修饰过的 controller 才有!! */ getMetadata(name: string): any; } interface Context { } }
最后打包发布 ok, 成功。 附上项目地址
总结一下:其实过程中并没有遇到什么很大的问题,都是一些小细节(也有可能是我忘了),写这个的目的也是鼓励自己多做尝试,多写一些有意思的东西,并在一开始就做好单独抽出来的准备,进行渐进式开发。毕竟结果不重要,但过程很享受。
从 Eggjs 项目中抽组件(Typescript)
我们写项目的时候最喜欢干的优化应该就是就是解耦了, 把一块功能独立出来封装成独立的插件,清晰整洁,强迫症表示一本满足。
本文就是我从
eggjs
项目中抽出一个组件的过程和坑。首先 啥是插件?
一个插件其实就是一个『迷你的应用』,和应用(app)几乎一样:
Service
、中间件
、配置
、框架扩展等等
。Router
和Controller
.plugin.js
,只能声明跟其他插件的依赖,而不能决定其他插件的开启与否。 摘抄自官网所以抽的时候根据现有结构把相关代码抽出来就好了。
那就开始
先把代码抽出来,放在
/lib/genome
中,做成内置的插件,参考渐进式开发。我要抽的是功能类似于
swagger
的自动生成api
的插件, 主要涉及到这些地方:helper
方法config
配置app.ts
中注册中间件那么抽完大概就这样:
因为还在项目中所以不需要
tsconfig.json
以及package.json
的其他配置。 而且egg-ts-helper
也会自动添加d.ts
文件。 自己在写一个额外的index.d.ts
就可以使用了。接下来像正常的插件一样使用就可以了,在
plugin.ts
中通过path
来挂载插件:运行一下
/path
路由成功跳转我的页面了抽成单独的组件
接下来就是正式抽离项目了 就像正常的项目一样初始化并吧代码复制进来,不一样的是需要加上自己的
tsconfig.ts
了,而且package.json
也要完整一下。添加一下依赖:因为发布的插件必须是
.js
的所以需要把.ts
翻译成.js
过后再发布,增加script
:添加发布的文件和关键字
ok, 发布,试试效果
emmmmmmmmmm...
一开始我还以为是引入的问题 导致的不能解构赋值,一直在
tsconfig.json
的"module": "commonjs",
这一行改来改去, 后来发现 哪怕我import * as xxx from
引入虽然不报错,但得到的压根是undefined
。 应该是入口index.ts
有问题。于是查了查,再看看别人的插件,看来是我对 ts 的了解果然还是不够深,其实是
index.d.ts
的编写有问题,我只写了额外的egg
声明, 插件的模块声明没有写..好在我们是 ts 写的组件 自动生成一下就好了。tsconfig.json
加这么一行"declaration": true,
这样所有文件就会自动生成
.js
和.d.ts
文件了。然后
package.json
也改一下:最后把原先
index.d.ts
中的东西挪到index.ts
中最后打包发布 ok, 成功。 附上项目地址
总结一下:其实过程中并没有遇到什么很大的问题,都是一些小细节(也有可能是我忘了),写这个的目的也是鼓励自己多做尝试,多写一些有意思的东西,并在一开始就做好单独抽出来的准备,进行渐进式开发。毕竟结果不重要,但过程很享受。