先抛个问题,JavaScript 是一门编译型语言仍是解释型语言?css
const module1 = require('module1')
import modul2 from 'module2'
const result = 123
复制代码
咱们在项目会写不少这种依赖引入,那 Webpack 获取这段代码的时候,它应该怎么去识别它?有的同窗就大腿一拍,这还不简单,用正则来判断下不就好,简单的确定能够,可是复杂,大段替换,单单正则是搞不定的,那们想一想,大学有一门课叫 编译原理,把高级语言编译成机器能识别的,编译最开始就是 扫描你的代码,抽象成一颗语法树,而后进行词法分析,那这个树就叫 抽象语法树,简称AST,Babel 把 const
专换成 var
就是利用 这个特性, 把代码转换成 AST,而后处理这颗 AST 树,处理完成,而后又生成 code,一样 Webpack 处理 require,import
依赖,也是在遍历 AST 树, 今天咱们就聊下 AST前端
现代前端是离不开AST,咱们用到的React,Vue,Angular,小程序
,这些框架本质上最后都是转换成被浏览器能识别的 JavaScript 代码,它们均可以理解成一种 DSL ,你会了你能够写一个本身的框架,比方叫avr
,语法来个三不像,也很好晚,流行的 mpvue,taro,react-netive
,都是在处理 AST,专换成你须要的代码,因此掌握AST很是重要,AST这一层大部分是框架处理,通常开发接触不到,致使不少人对AST都很陌生,这篇的目的是让你们大概了解下 AST,不会深刻去写AST,对AST感兴趣的能够关注我下,后面我会写个三不像的avr
框架,详细介绍 ASTvue
先来个最简单的语法,咱们把 const test = 123
转换成 var test = 123
,看代码node
const acron = require('acorn')
const traverse = require("ast-traverse");
const escodegen = require('escodegen')
const code = `const test = 123`
let ast = acron.parse(code)
traverse(ast, {
pre: function (node, parent, prop, idx) {
if (node.kind == 'const') {
node.kind = 'var'
}
}
})
let esCode = escodegen.generate(ast)
console.log(esCode)
复制代码
let ast = acron.parse(code)
会把代码转换成 一个tree的数据类型,tree的截图以下react
你们能够看到 ast 其实就是对代码文本的一种抽象,经过 type来标记,咱们要作的是 就是遍历这颗 tree,把 const
替换成 let
,就行了,而后在把 ast 转换成 code,代码很是简单,能够本身跑一下webpack
ast 语法简单的介绍下,网上又不少的详细的介绍, 各个框架都提供了一个 对应的 *.loader
插件,这些loader 就是把框架的DSL转换成 JavaScript,Eslint,postcss,这些都是用的AST,咱们脑洞开一下,有了 AST 咱们是否是能够把 React,Vue 相互转换,定义本身公司独有的语法,折腾本身的框架,定义本身的 sass,批量替换老的API,AST 就像手术刀,底层处理代码,很值得深刻学习,web
回到 Webpack,在第一篇里,咱们在Webpack 整个流程里讲过,Webpack 把每一个 文件都当作一个个Module,Module上的这些 require,import
依赖,也是经过 ast来判断的 依赖,而后经过 Resolve来加载这些模块,chrome
那咱们日常写的语法常见的有下面这样的小程序
// webpack.config.js
module.exports = {
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
}
}
};
// main.js
const module1 = require('module1')
import modul2 from 'module2'
import util from '../../util/'
import util from '@/util'
import '../style/main.css'
复制代码
各类依赖 文件路径处理须要 resove的,Webpack 把这个独立出来了一个库 叫 enhanced-resolve
,下篇就讲下 resolve 实现浏览器
那回到第一个问题 JavaScript 是一门编译型语言仍是解释型语言?
JavaScript 是一门编译型语言,只不过 编译时间很是短,给人感受是解释型语言
sum(1,2)
function sum(a,b){
return a + b
}
复制代码
若是是解释型语言,代码一行行的读,这段代码是要报错的,但没有报错,我门说这个是函数提高,实际上就是 浏览器的编译过程 若是你喜欢也能够关注个人 公众号 「chromedev」