欢迎来到258分享网,纯净的网络源码分享基地!

258资源分享网

全部作品
全部作品
网站源码
微信源码
素材特效
源码插件
视频教程
建站学院
热门搜索: 织梦  农业种植  农业  安全设置  官方
258资源分享 > 建站学院 > 微信开发 > 【babel+小程序】下

推荐下载

HTML5响应式自适应网咯设计

2020-05-12   浏览:789

HTML5自适应律师工作室类网

2020-04-04   浏览:654

高端HTML5响应式企业通用网

2020-05-06   浏览:560

html5响应式外贸网站英文版

2020-05-08   浏览:545

HTML5影视传媒文化公司类网

2020-05-12   浏览:543

【babel+小程序】下

发布时间:2020-11-02  
babel插件替换全局常量 1.思路

想必大家肯定很熟悉这种模式

let host = '' if(process.env.NODE_ENV === 'production'){ host = '' }

通过这种只在编译过程中存在的全局常量,我们可以做很多值的匹配。

因为wepy已经预编译了一层,在框架内的业务代码是读取不了process.env.NODE_ENV的值。我就想着要不做一个类似于webpack的DefinePlugin的babel插件吧。具体的思路是babel编译过程中访问ast时匹配需要替换的标识符或者表达式,然后替换掉相应的值。例如:

In

export default class extends wepy.app { config = { pages: __ROUTE__, window: { backgroundTextStyle: 'light', navigationBarBackgroundColor: '#fff', navigationBarTitleText: '大家好我是渣渣辉', navigationBarTextStyle: 'black' } } //... } Out export default class extends wepy.app { config = { pages: [ 'modules/home/pages/index', ], window: { backgroundTextStyle: 'light', navigationBarBackgroundColor: '#fff', navigationBarTitleText: '大家好我是渣渣辉', navigationBarTextStyle: 'black' } } //... } 2.学习如何编写babel插件

编写Babel插件入门手册

AST转换器

编写babel插件之前先要理解抽象语法树这个概念。编译器做的事可以总结为:解析,转换,生成。具体的概念解释去看入门手册可能会更好。这里讲讲我自己的一些理解。

解析包括词法分析与语法分析。

解析过程吧。其实按我的理解(不知道这样合适不合适= =)抽象语法树跟DOM树其实很类似。词法分析有点像是把html解析成一个一个的dom节点的过程,语法分析则有点像是将dom节点描述成dom树。

转换过程是编译器最复杂逻辑最集中的地方。首先要理解“树形遍历”与“访问者模式”两个概念。

“树形遍历”如手册中所举例子:

假设有这么一段代码:

function square(n) { return n * n; }

那么有如下的树形结构:

- FunctionDeclaration - Identifier (id) - Identifier (params[0]) - BlockStatement (body) - ReturnStatement (body) - BinaryExpression (argument) - Identifier (left) - Identifier (right)

进入 FunctionDeclaration

进入 Identifier (id)

走到尽头

退出 Identifier (id)

进入 Identifier (params[0])

走到尽头

退出 Identifier (params[0])

进入 BlockStatement (body)

进入 ReturnStatement (body)

进入 BinaryExpression (argument)

进入 Identifier (left)

退出 Identifier (left)

进入 Identifier (right)

退出 Identifier (right)

退出 BinaryExpression (argument)

退出 ReturnStatement (body)

退出 BlockStatement (body)

“访问者模式”则可以理解为,进入一个节点时被调用的方法。例如有如下的访问者:

const idVisitor = { Identifier() {//在进行树形遍历的过程中,节点为标识符时,访问者就会被调用 console.log("visit an Identifier") } }

结合树形遍历来看,就是说每个访问者有进入、退出两次机会来访问一个节点。

而我们这个替换常量的插件的关键之处就是在于,访问节点时,通过识别节点为我们的目标,然后替换他的值!

3.动手写插件

话不多说,直接上代码。这里要用到的一个工具是 babel-types ,用来检查节点。

难度其实并不大,主要工作在于熟悉如何匹配目标节点。如匹配memberExpression时使用matchesPattern方法,匹配标识符则直接检查节点的name等等套路。最终成品及用法可以见 我的github

const memberExpressionMatcher = (path, key) => path.matchesPattern(key)//复杂表达式的匹配条件 const identifierMatcher = (path, key) => path.node.name === key//标识符的匹配条件 const replacer = (path, value, valueToNode) => {//替换操作的工具函数 path.replaceWith(valueToNode(value)) if(path.parentPath.isBinaryExpression()){//转换父节点的二元表达式,如:var isProp = __ENV__ === 'production' ===> var isProp = true const result = path.parentPath.evaluate() if(result.confident){ path.parentPath.replaceWith(valueToNode(result.value)) } } } export default function ({ types: t }){//这里需要用上babel-types这个工具 return { visitor: { MemberExpression(path, { opts: params }){//匹配复杂表达式 Object.keys(params).forEach(key => {//遍历Options if(memberExpressionMatcher(path, key)){ replacer(path, params[key], t.valueToNode) } }) }, Identifier(path, { opts: params }){//匹配标识符 Object.keys(params).forEach(key => {//遍历Options if(identifierMatcher(path, key)){ replacer(path, params[key], t.valueToNode) } }) }, } } } 4.结果

本文标签

: