使用Babel的AST功能,来智能分析处理源码

在重构时,往往会遇到一些不合理的代码需要被批量替换。这种需求一般的全文替换是可以的,但是如果要根据文件名、变量名动态的进行智能替换,而且被替换的代码块格式不一,这时还有什么方式?正则是一个办法,但是还有没有别的方法可以尝试呢?

有的!之前在重构某些项目时,有许多属性需要批量替换,但是我希望能加入一些逻辑判断、和一些其他变量的状态获取。在查询许多资料之后,除了正则+脚本,还有Babel能帮我解决这个问题

Babel

我们一般前端开发是用Babel来转换新语法,然而它的API也能让你来自定义转换源码。这个API就是将你的源码转换成AST(Abstract Syntax Tree)抽象语法树。能实现AST转换的其实不止Babel一家,在Babel之前还有Esprima等。只不过我们大部分用的都是Babel,为了和.babelrc语法一致,所以我更推荐使用Babel来进行AST转换

AST(抽象语法树)

维基百科:在计算机科学中,抽象语法树(AST),或简称语法树,是用编程语言编写的源代码的抽象语法结构的树表示。树的每个节点表示源代码中出现的一个构造。

例如:Program -[Code1 ,Code2],同时Code1又包含
VariableDeclaration(变量定义)、CallExpression(函数定义)等,在函数内又有许多语法在其中。这么一看,是不是很像一颗树呢?有树层次、节点关系等^_^。然后实践的过程中,只要我们增减其中的节点,或者是修改节点的属性值,再将AST转换成源码,这样就可以很轻松的达到“智能转换代码”的功能了!

学习资料

官方手册:
https://github.com/jamiebuilds/babel-handbook/blob/master/translations/zh-Hans/README.md

AST Explorer(在线解析语法AST):https://astexplorer.net/

维基百科定义:https://en.wikipedia.org/wiki/Abstract_syntax_tree

具体实践

只是给出几个定义感觉不直观,让我们直接上手AST吧!相信AST能让你今后的重构或者代码调整,能够如虎添翼,这并不是奇巧淫技,而是真正提升你效率的一个利器!下面列出一个Github仓库,这是我实际用AST进行转换的例子:

Github仓库:
https://github.com/tun100/ReplaceContentByBabelAST

实际需求:

替换前文件
替换后文件

我们现在需要拿到{form.getFieldDecorator(‘myname’, {})}的“myname”字符串,这是定义form的prop值的。然后对Form.Item的label需要改为传递<ErrorTooltip>

一般正则是可以使用,但是AST也可以帮助你实现这个功能,让我们打开index.js这个文件

index.js文件概览

在进行AST处理时,我们会通过core.parse得到一颗树。那么我们怎么去遍历,去拿到这个值呢?这时候会用到traverse这个函数,通过这个函数,它可以帮你遍历所有的节点,如果你判断当前的tree node符合你的条件,那么就立刻进行处理,如下图:

具体解析转换代码

在语法树中,每个节点都有自己的定义,比如:节点是什么语法,带有什么属性,自身是什么值,在自己语法下还有没有更深层次的子树存在。那么这些节点具体有哪些属性,我应该怎么知道呢?

其实有一个很快捷的方式,就是把你的代码拷贝到 https://astexplorer.net (如果不放心可以clone它的仓库,在本地运行,不过我检查过不会有隐私问题),然后在菜单顶部选择babylon7,这样右侧就会有你想要的各个节点的属性和之间的关系

AST-Explorer具体使用

手动配置webpack 4.x,定义属于自己的脚手架

概述

webpack作为一个构建工具是非常优秀的,提供了多页面、Plugin、Loader等功能,而且还有基于webpack的零配置工具(如create-react-app)等。在webpack应用如此广泛的情况下,我觉得有必要深入了解webpack并从零开始配置,因为至少出了问题能很快的找到异常配置并快速修改好。之前搭建webpack也好多次了,但是没有进行总结。这次决定从头开始搭建,然后边操作边记录

之前还用过Parcel等新秀解决方案,它讲究的是零配置,用过在一些小项目上,但貌似还不太稳定,经常会出编译错误,所以又跑回了webpack的怀抱^_^

测试环境

Node.js: 8.14.0

Npm: 6.4.1

已搭建好环境的仓库

为了方便随时Clone出webpack编译环境,我把最终环境部署在Github仓库上了,
地址是:https://github.com/tun100/webpack-basic-frame

依赖初始化

npm init -y

然后将下面的依赖信息添加到package.json(因为不同依赖版本的差异,容易导致bug,如果使用我的这个依赖,我确信肯定能构建环境成功^_^),在添加成功之后执行npm i -S && npm i -D

   "scripts": {
     "dev": "npx webpack-dev-server --config ./webpack.dev.config.js --progress --profile --colors --watch --mode development",
     "dist": "npx webpack --config 

【React快速学习一】基础JSX语法和生命周期

学习React也有近两年多的时间,因为一些知识点用久了容易忘记,决定找空闲时间整理下自己理解的React知识文章,顺便做一下总结!😀

什么是React

React不同于以往的JQuery+BootStrap,它是一个简单的View层框架,搭配上周边生态(Redux/Mobx/ReactRouter等),就能构建起各种逻辑复杂的系统。

我所理解的React框架具备以下特点:

1.,使用JSX语法

借助该语法,可以在JavaScript文件里混编类似HTML的代码,不仅支持原生H5标签,还可以支持用户自定义的React组件,该语法风格如下:

let Clock = () =<divthis is clock</div// 此处渲染了一个React组件
ReactDOM.render(
    <Clock/,
    document.querySelector('#root')
);

2,采用VirtualDOM优化渲染性能

浏览器内核有JS引擎和渲染引擎,每当JS手工去操作DOM树的时候,往往会引起Repaint或者Reflow,这个操作会比较耗时,从而导致页面性能不佳

于是,开源社区想出了一个VirtualDOM的解决方案。使用JavaScript来虚拟定义一个DOM树,并且更新之前会对虚拟DOM节点进行比较,React会根据比较结果,只会部分更新所需的DOM节点,减少了不必要的渲染工作

不仅React,还有Vue等框架也采用了VirtualDOM diff算法,思想都是大同小异,下面是相关代码说明

// 在React里,VirtualDOM定义的元素格式如下
{
  type: "div",
  props: null,
  children: [{type: "text", props: {textContent: "Hello"}}]

使用SSH密钥,更安全快速的免密登陆到Linux服务器

为什么用密钥替代传统的密码

因为密码虽然可以设置复杂一些,但终究还是不方便管理,需要管理员手动输入一遍又一遍。还有密码的安全性也是一个令人担忧的地方,如果要在公网暴露公网IP,我不太敢让服务器提供密码鉴权服务(虽然也有failban,但是依旧不信任),毕竟有那么多攻击四处寻找目标,一切要以安全为核心

如果使用密钥,上面的担忧都可以消除了!因为密钥首先加密长度不短,需要暴力破解没个几年日夜不停的话,被攻击成功的可能性还是比较小的。其次,密钥在手,可以免密登陆,在经常登陆的场景下非常方便,甚至一个私钥我可以登陆所有服务器,而不需要任何密码输入,可以说非常方便

密钥创建

如果是windows,请先安装git-bash,它会给你许多Linux下的工具(不是所有)。如果是Linux,不需要做任何操作,一般都有必备的软件工具

在自己的主目录下创建.ssh主目录(win是C:\users\${user},Linux是~):

ssh-keygen -b 4048

第一次询问文件名称,如果没有即回车,有的话将会输出到当前文件夹下。后面的询问都直接回车即可

正常情况下,应该是生成了test.pub和test这两个文件(我拿test作为示例),test.pub是公钥,是传送给目标Linux服务器的,test是私钥,是用来后续登陆使用的

拷贝公钥到目标服务器

ssh-copy-id -i ./test.pub root@${ssh_ip} -p ${ssh_port}

拷贝最后会要求输入密码,输入之后没有错误即完成了

使用私钥进行SSH登陆

ssh -i ./test root@{ssh_ip} -p ${ssh_port}

更安全的SSH登陆配置

只是密钥登陆还不是最佳实践,更安全的配置请参考我之前的写的文章…

Linux服务器安全建议以及相关配置

能处处都特别理想,我按照我思考的最理想的配置来描述,可能有不对的地方,请多多包涵和指出!

1,永远不要关闭iptables

我以前为了方便开发调试,经常执行iptables -F清空所有规则,但是后面深入了解网络安全,发现这样会导致服务器处于无保护状态。至少要确保每个端口开放都是明确的,否则会很不安全

2,SSH只允许密钥登陆,禁止密码登陆和Root远程登陆权限,修改22端口

如果密码不复杂,那么允许密码登陆也会导致服务器不安全。我推荐使用密钥进行登陆,过几天有空写一些专门的SSH密钥配置流程。

接下来编辑/etc/ssh/sshd_config,修改一些参数:

修改22端口,和禁止Root登陆
禁止密码登陆

3,不能随意给Root权限,在chmod设置权限的时候谨慎给与其他用户组rwx

root账号应该是顶级用户使用的,具体分配给成员各自的账号,在/var/log/下各种操作都可以一目了然。如果都是root权限,那么在出问题的时候很难查出是谁操作的(随意删除操作日志、.bash_history等)。还有,Linux的权限系统限定了owner,group,other users,不能随意的设置文件777权限,这可能会导致部分用户可以读取执行隐私文件…

Linux系统配置lrzsz,配合XShell提升使用体验

在传统的Linux文件上传下载,一般是需要用到SFTP或者Rsync、FTP等协议,然而有一个更快捷更方便的方法,可以让你在上传下载时效率提升N倍

这里用CentOS7作为示例,首先安装相关的软件包:

yum -y install lrzsz

然后,在windows打开xshell,登陆目标服务器的SSH控制台,你可以尝试拖拽一个文件到控制台下,如图:

是不是很方便,它传送的目标地址就是你当前控制台的位置

那么怎么传送当前控制台下的某个文件呢?很简单,输入 sz ${YOUR_TARGET_FILE}即可:

sz mytarget.tar

选择好目标即可进行传送

这个方法真的非常提升效率,减少了误操作,强烈推荐


Linux的LANG语言编码配置

语言编码配置,是非常重要的,如果设置了不恰当的语言编码(比如英文或者GBK),同时你又尝试运行基于UTF-8的Java应用程序,那么乱码概率可是相当的大的!

临时设置:

export LANG=en.US

永久设置

vi /etc/locale.conf ,使目标编码生效即可(去除前面的#号)…

CentOS7在执行groupinstall的时候报错

因为在一开始选择了minmal install,许多依赖包没有安装,输入下面命令执行就可以了

yum groupinstall “Office Suite and Productivity” –setopt=group_package_types=mandatory,default,optional

然后,再执行yum group list,可以看到有许多套件,安装即可(记得组建名要大小写一致,用引号标注):

Nginx常规操作:压缩配置、反向代理、http转向等

概述

nginx真的很好用!而且配置清晰,我在nginx遇到的功能特性以及特性都描述在这里,文档不定时更新

压缩配置

在Web开发中,传输资源(JS/CSS/图片)的体积非常影响使用者的体验。据说,一个页面只要超过7秒钟,浏览者就会失去等待的耐心,并关掉页面。

那么如何尽量减少体积呢?代码混淆压缩是一方面,其实我们还可以在更高角度对资源进行压缩,这个压缩,就是gzip。无论是前端还是后端,在资源体积过大的情况下,都应该使用gzip。我曾经使用gzip,成功将5M的文件压缩成700k

下面描述相关配置:

在http下,输入:

gzip  on; # 打开gzip
gzip_min_length 1k; # 低于1k的不压缩
gzip_comp_level 9; # 压缩比例,1-9,越高压缩率越大
gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css;
gzip_disable "MSIE [1-6]\.";
gzip_vary on; 
然后调用curl,并查看返回的Content-Encoding
可以看到Content-Encoding是gzip,表明该资源是gzip压缩传送过来的

反向代理

有一些内网机器,并不想暴露在对外网络中,又或者是需要做负载均衡。那么这个情况下,就需要nginx的反向代理作为对外的入口了,我常用nginx的代理在http层的代理(貌似最新版本支持tcp代理了)

反向代理是什么?其实这个就应该和正向代理一起来讲述。正向代理,就像是一台中转路由器,它明确告诉你,它不是服务器,只是替你转发请求。而反向代理,就是伪装自己是最终端的服务器,它告诉你它就是处理服务器的终点,但实际上并不是,它还需要将请求转发给内网的其他服务器,这一个转发的过程你不知道,所以这是反向代理。

反向代理的配置如下:

proxy_pass http://127.0.0.1:55161; 
proxy_set_header 

使用Lodash编写安全、高效、优雅的JavaScript应用

在编写JS应用时,相信很多开发者会遇到“Uncaught TypeError: Cannot read property ‘prop’ of null” ,这种情况一般是没有做安全预判断。然而如果每一处都要加 obj != null && obj != undefined,不仅编写繁琐,也让代码的信噪比降低

为了让应用safety first,同时编写代码能够优雅高效,JS社区终于出现了一个瑞士军刀–Lodash。它的前身其实是underscore,这个和Lodash的概念差不多,其实API有点不一致而已,我主要介绍以下Lodash^_^

Lodash使用非常简单,你只需要记住它的变量是_就可以了(下划线)。在Lodash的编程哲学里,安全是第一的,而且融入了函数式编程。通过使用Lodash,你能感觉到它所有的API都可以大幅度减少无用的代码,让你的JS应用从1000行减到200行。我相信你会喜欢Lodash,而且在使用的过程中会逐渐理解贯彻它的编程哲学的

使用资料

Lodash官方仓库:
https://github.com/lodash/lodash

Lodash参考文档:
https://www.css88.com/doc/lodash/#_bindfunc-thisarg-partials

API简介

你在使用Lodash一段时间会发现,_.map既可以用在Object也可以用在Array,_.pickBy可以过滤Object不需要的key值,同时哪怕你传进去是null/undefined/NaN,Lodash也不会直接报错中断当前执行,而且返回一个空的结果(数字0,空数组,空对象等),可以确保你不会收到异常的情况。

在Lodash一些方法,比如_.difference,_.differenceBy, _.differenceWith,它们分别是默认处理函数,提供指定属性或者函数结果值来判断,手动编写compartor来进行判断

接下来,我介绍一些常用的API和它们的用途,其他的API如果感兴趣可以看上面的参考文档^_^

_.isNil

判断传参是不是null或者undefined,这对于常规的判断非常有用

_.get(object,path,[defaultvalue])

这是最常用的API,能够让你对一个数组或者数字,进行路径path的值访问,而且如果这个path的值是为空的,将会使用defaultvalue,举例:

// path的格式:
// 比如a.0.c对应的path路径就是 obj = {a:[{c: