框架开发指南(误)- 模板篇之文件解析
前言
本篇打算开一个系列,来和大家分享一下个人对于框架的认知(仅个人观点),以及了解和平常业务不一样的前端开发。本文大多数以流程图的形式介绍,因为流程思维才是最重要的,并且读源码的最终目的也是如此,如果有哪里不懂的推荐自行下载源码比照来看,最终目标就一句话:
总有人教你学vue、react、angular等,为什么不写个框架来让他们来学(给自己happy用用也可以)
项目地址: gitee.com/beon/eason
框架总结
经过我不成熟的使用感受下来,其实框架最主要的是在这两块上:
- 框架运行模式:比如vue的双向绑定、react的setState触发更新、angular的异步更新,以及怎么实现更新是否有虚拟dom还是直接进行更新等等
- 模板处理:现在感觉主要就分为两大类,一个是以react为首的jsx语法结构,另一个就是直接进行自己的模板解析
其中模板的文件解析处理这一块我觉得各个框架都还有不同的地方,比如:
- angular的各个文件自行注入,没有新东西
- react的.jsx文件,看着和.js一样的感觉
- vue的.vue文件,是不是一开始看起来就很蒙蔽
那么接下来我们就抛开运行模式来介绍模板文件处理吧
模板文件篇
我们首先需要知道的是,vue和jsx怎么配置才会正常加载,如果不太清楚的同学可以先自行百度一下,我在这里就做简单的总结
vue文件利用vue-loader来在webpack中进行添加.vue文件的rule
jsx文件利用配置preset-react在babel中配置实现
那么这里我们就需要知道他们是怎么进行翻译的,因为这些文件本身都不是js,肯定是没法正常处理的所以经过翻译后就可以达到正常运行的目的。简单的流程图就如下所示
这里就可以很明显的看出来vue主要是用了webpack,react主要用了babel。那么接下来就该进入我们的主题了,自己做一个框架的模板中的文件编译
开发文件解析(.eason文件)
目标文件
<eason-html>
<div class="ceshi">我就是我3123</div>
</eason-html>
<eason-script lang="js">
im该ort { Eason } from "Eason";
export default class First extends Eason {
beforeMount() {
console.log(1)
}
didMount() {
console.log(2)
^_^(let a = {a: 1});
window.test = a
}
}
</eason-script>
<eason-style lang="less">
.ceshi{
color: pink;
}
</eason-style>
作为我们新的框架,一定要吸收各种框架文件编译的方式,所以我们用webpack和babel来共同处理。
项目文件和作用
该项目的链接地址放在最后,感兴趣的可以去下载看看,是一个很简单的很简单甚至不能用的框架,但是本文所说的两种模板处理方式都有
package.json
了解一个项目我们要先从用了哪些依赖开始,我们就来先看看我们的依赖,这里就不做过多说明,不清楚某个依赖可以直接百度就行
"devDependencies": {
"@babel/core": "^7.19.3",
"@babel/preset-env": "^7.19.4",
"babel-loader": "^8.2.5",
"babylon": "^6.18.0",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.7.1",
"html-webpack-plugin": "^5.5.0",
"less-loader": "^11.1.0",
"loader-utils": "^1.1.0",
"qs": "^6.11.0",
"style-loader": "^3.3.1",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.11.1",
"webpack-merge": "^5.8.0"
}
webpack.*.js
当我们了解了我们使用了哪些插件之后就开始最重要的webpack配置了,我们在webpack的rules中先行添加一个eason文件的匹配规则然后再指定我们自己的处理文件就像这样。
这样设置之后该文件的解析就进入我们自己定义的webpack loader中了。
eason-webpack/index.js
在这里我们首先需要知道的是webpack的loader模型,其实就是我们常说的洋葱模型(虽然这里用不上但是知道总是好的)
然后我们把三块内容分别加载,template需要我们的模板引起来转换(但是我们没有),script就是简单的js加载,style需要我们用less来进行翻译。我们把这三块再进行分别引入后再独立进行自己的文件编译,这里相对比较抽象(不好理解),并且还有一定的inline loader知识,所以我们先上图方便理解。
这里就有一定的小知识点了,关于webpack如何去利用inline loader将文件处理走多个规则,以下是webpack官网原文
We use
!=!
syntax in that pitching loader to set matchResource for the request, i.e., we'll usethis.resourcePath + '.webpack[javascript/auto]'
to match with themodule.rules
instead of the original resource,
我们来一步步分析:
- 首先webpack中采用inline loader可以执行单文件的loader处理,顺序是由后到前
- !=!可以帮助我们将文件走一个额外的匹配规则
- 那么比如我们的style的import内容就是这样的:
-
src/index.eason.style.less!=!/eason-webapck/Select.js!*/src/index.eason?type=style(理解这一步很重要)
再来把那一句引入拆一下就是这几个部分
- src/index.eason.style.less // 这一块是为了让资源走less规则匹配
- !=! 官网文档写的作用
- /eason-webpack/Select.js! // 这一步是inline loader的规则
- /src/index.eason //这是最初的入口资源
那么这一句话loader会怎么处理呢?
其余模块类似,这样就可以通过我们的select.js来分发资源,给最终的不同类型进行loader加载了
babel.config.json
{
"presets": [
[
"@babel/preset-env"
]
],
"plugins": [
"./eason-babel/index.js"
]
}
这里就很简单就是添加了一个自己的babel插件而已
eason-babel/index.js
其实这个地方可以讲解的内容不多,因为这里处理有两种方式:
- 利用现有的语法规则,进行特殊的匹配后修改内容,比如对象的memberExprsion转换成functionExpression来将对象获取转换成函数做获取拦截,实现类似于get的方法,都可以从语法层面来实现
- 利用特殊语法匹配,然后转换成标准的语法规则,比如这里的:^_^(let a = {a: 1});这一句话在babel中处理后就变成了a = new this.HandleProxy({a: 1});
因为这一块完全是属于语法分析了,如果以后有机会的话可以写一篇文章来介绍一些常见的语法分析修改。但是在这里,我采用的是正则来实现特殊语法(懒,简单,演示用)
基础流程分析
其实通过上述的文件分析,流程都已经出来了,这里就放一个.eason文件经过了哪些修改最后运行到页面上的
成果展示
在经过我们的处理之后我们的eason文件已经解析完成了这个时候添加一点小小的框架思维,将我们的tempalte渲染到dom上面之后就成了
当然了,简单展示肯定不得行,那么我们再简单的再加一点代码之后就可以变成这样了
小结
以上就是大概的内容了,相较于我们平常开发业务,会接触到很多不常用的知识点。看似无用,其实真的没啥用(可以获得一些设计思维),当然了这其实也是提升我们自己的技术深入度的机会,能够去学习一些源码然后进行自我总结。
本篇内容就是这么多,接下来如果有可能的话还有模板篇之模板解析、运行篇等等(不一定),如果有问题欢迎大家留言,我也会接受大家的批评和给大家答疑。
项目地址:gitee.com/beon/eason
转载自:https://juejin.cn/post/7158286601477423111