天地玄黄,宇宙洪荒
前端开发,重要的就是 2 个(类)文件:
index.html
静态资源:js & css
一个一站式的前端开发框架,要做的就是定义、构建、使用以上文件,其中
「定义」是静态的,是描述式的
「构建」和「使用」是运行时的
由于 webpack 的普遍使用,「定义」的一大部分工作就是围绕 webpack 进行;「构建」和本地开发服务器的运行,也都是依赖 webpack
具体到 umi 框架,使用精巧的插件体系,把上述操作更加语义化以及细化
从纵向看,就是使用插件对 index.html 文件和 webpack files 进行配置
- webpack files 是一大堆文件:webpack config / webpackrc / entry.js / router.js / etc
从横向看,就是执行命令,并且通过 apply 插件得到定制过的相关文件、配置作为 webpack 的输入
再搜索 umi 源码,可以看到更精细的插件 hook 点
html 相关
- modifyHTML
webpack 相关
modifyWebpackConfig
modifyAFWebpackOpts
modifyEntryFile
router 相关
modifyRouterFile
modifyRouteComponent
modifyRoutes
以上这几个 hook 都是比较「纯粹」的,看名字就知道了:「modify」
还有一些 hook 点就不那么 pure 了,比如:generateFiles
作用是生成 DvaContainer.js 文件,直接就写到 writeSync 了
(为啥不搞成 pure hook 呢?可以的)
还有一些 hook 点是和运行时的生命周期挂钩的,看命名也就知道了
beforeServerWithApp
onStart
beforeDevAsync
beforeGenerateHTML
buildSuccess(为啥不叫 onBuildSuccess ???)
etc
关于 umi 命令生命周期如图所示:
传送门🚁:https://github.com/umijs/umi/issues/87
然后,插件就可以选取自己需要的 hook 点进行配置,以 umi-plugin-dva 插件为例:
chenni:umi-plugin-dva/ (master✗) $ grep -rn 'api.register' * [12:28:58]
lib/index.js:210: api.register('generateFiles', () => {
lib/index.js:226: api.register('modifyRouterFile', ({
lib/index.js:241: api.register('modifyRouteComponent', ({
lib/index.js:273: api.register('modifyEntryFile', ({
lib/index.js:285: api.register('modifyAFWebpackOpts', ({
lib/index.js:298: api.register('modifyPageWatchers', ({
src/index.js:178: api.register('generateFiles', () => {
src/index.js:201: api.register('modifyRouterFile', ({ memo }) => {
src/index.js:222: api.register('modifyRouteComponent', ({ memo, args }) => {
src/index.js:255: api.register('modifyEntryFile', ({ memo }) => {
src/index.js:269: api.register('modifyAFWebpackOpts', ({ memo }) => {
src/index.js:285: api.register('modifyPageWatchers', ({ memo }) => {
所以,最后再总结一下:
umi 使用插件体系进行框架的配置和使用
从纵向看,是静态的,通过插件配置各种 hook 点,定义 index 文件、webpack 配置、生命周期 hook
纯配置类 hook,modifyXXX
生命周期类 hook,on/before/afterXXX
其他不纯洁的 hook😅
从横向看,是运行时的,加载需要的插件,在生命周期的各个点读取和执行 hook
ref:
- umi as a Compiler: https://hackmd.io/s/ByGeBtv9z
未完待续(代码走读:插件的加载和执行)