Commit 66ae1db4 authored by Master Q's avatar Master Q

init

parents
{
"plugins": ["./babel-plugins/babel-plugins-react-test.js"],
"presets": [
["@babel/preset-env", {
"targets": "> 0.25%, not dead"
}]
]
}
\ No newline at end of file
node_modules
> lesson1 lesson2 lesson3 分别对应三种 babel 的简单使用
> lesson3 主要就是react 的解析思路 配合 src/Light 下的简单 方式可以 实现 类react 的框架用法。 后续你可以在 这里上面进行 改动 比如 使用 componentDisMount 和 unMount 的生命周期 ref 等。 本质上是没有 diff 的 react, 低情商,不就是react吗, 高情商, wc 竟然能够完美解决 react 的diff 算法问题。
大家可以简单看下, 能够帮助我们了解 react 原理。
\ No newline at end of file
const _defaultJsx = require('@babel/plugin-syntax-jsx').default
const targetArr = ['log'].map(r => `console.${r}`)
const config = {
pragma: 'Light.createElement'
}
module.exports = function(api) {
const {
types,
template
} = api
function toMemberExpress(str) {
return str.split('.').map(n => types.identifier(n)).reduce((pre, curr) => types.memberExpression(pre, curr))
}
function CallCreateElementExpression(args) {
const t = types.cloneNode(toMemberExpress(config.pragma))
return types.callExpression(t, args)
}
function getTag(n) {
const tagExp = convertJSXIdentifier(n.node.name)
let tagName
if (types.isIdentifier(tagExp)) {
tagName = tagExp.name
} else if (types.isStringLiteral(tagExp)) {
tagName = tagExp.value
}
if (tagName && /^[a-z]*$/.test(tagName)) {
return types.stringLiteral(tagName)
} else {
return tagExp
}
}
/**
* 转化jsxName
* @param {*} node
* @returns
*/
function convertJSXIdentifier(node) {
if (types.isJSXIdentifier(node)) {
if (types.isValidIdentifier(node.name, false)) {
node.type = "Identifier" // 这里是因为下面的 type。memberExpression 需要type 为 Identifier的
} else {
return types.stringLiteral(node.name)
}
} else if (types.isJSXMemberExpression(node)) {
return types.memberExpression(convertJSXIdentifier(node.object), convertJSXIdentifier(node.property))
}
return node
}
function initProps(path) {
const attribs = path.get('attributes')
const objs = []
attribs.reduce(function(pre, cur) {
const node = cur.node
if (types.isJSXSpreadAttribute(cur)) {
const arg = node.argument
if (types.isObjectExpression(arg)) {
pre.push(...arg.properties)
} else {
pre.push(types.spreadElement(arg))
}
return pre
}
const t = cur.node.value || types.booleanLiteral(true)
const value = types.isJSXExpressionContainer(t) ? t.expression : t
if (types.isValidIdentifier(node.name.name, false)) {
node.name.type = "Identifier"
}
pre.push(types.objectProperty(node.name, value))
return pre
}, objs)
return types.objectExpression(objs)
}
function buildCreateElementExp(path) {
const openELe = path.get('openingElement')
return CallCreateElementExpression([getTag(openELe), initProps(openELe), ...types.react.buildChildren(path.node)])
}
return {
inherits: _defaultJsx,
visitor: {
ArrowFunctionExpression(path, state) {
const node = path.node
console.log(node)
const params = node.params
let body = node.body
if (!types.isBlockStatement(body)) {
body = types.blockStatement([types.returnStatement(body)])
}
const functionExpression = types.functionExpression(null, params, body)
path.replaceWith(functionExpression)
},
CallExpression(path) {
const node = path.node
if (node.isSkip) return
const calleeStr = path.get('callee').toString()
if (targetArr.includes(calleeStr)) {
let newLog = template.expression(`console.log('%c%s', 'color: green', '=======test=====')`)()
path.insertBefore(newLog)
newLog.isSkip = true
node.isSkip = true
}
},
Program: {
enter(path) {
const pragma = config.pragma
}
},
JSXElement: {
exit(path, state) {
const node = path.node
const openEle = path.get('openingElement')
const newNode = buildCreateElementExp(path)
path.replaceWith(newNode)
}
}
}
}
}
\ No newline at end of file
const parser = require('@babel/parser')
const traverse = require('@babel/traverse').default
const generator = require('@babel/generator').default
const types = require('@babel/types')
const sourceCode = `
const gn = (a, b) => a + b;
const fb = function(a, b) {var c =3; return a + b};
`
const ast = parser.parse(sourceCode, {
sourceType: 'unambiguous'
})
traverse(ast, {
ArrowFunctionExpression(path, state) {
const node = path.node
const params = node.params
let body = node.body
if (!types.isBlockStatement(body)) {
body = types.blockStatement([types.returnStatement(body)])
}
const functionExpression = types.functionExpression(null, params, body)
path.replaceWith(functionExpression)
}
})
const {
code
} = generator(ast)
console.log(code)
const parser = require('@babel/parser')
const traverse = require('@babel/traverse').default
const generator = require('@babel/generator').default
const types = require('@babel/types')
const template = require('@babel/template').default
const sourceCode = `
console.log(a)
class TT {
render() {
console.log(123)
}
}
`
const ast = parser.parse(sourceCode, {
sourceType: 'unambiguous'
})
const targetArr = ['log'].map(r => `console.${r}`)
traverse(ast, {
CallExpression(path) {
const node = path.node
if (node.isSkip) return
const calleeStr = path.get('callee').toString()
if (targetArr.includes(calleeStr)) {
let newLog = template.expression(`console.log('%c%s', 'color: green', '=======test=====')`)()
path.insertBefore(newLog)
newLog.isSkip = true
node.isSkip = true
}
}
})
const {
code
} = generator(ast)
console.log(code)
const parser = require('@babel/parser')
const traverse = require('@babel/traverse').default
const generator = require('@babel/generator').default
const types = require('@babel/types')
const template = require('@babel/template').default
const sourceCode = `
console.log(a)
class TT {
render() {
console.log(123)
return <div>
<FYGE.Container>123</FYGE.Container>
</div>
}
}
`
const config = {
pragma: 'Light.createElement'
}
function toMemberExpress(str) {
return str.split('.').map(n => types.identifier(n)).reduce((pre, curr) => types.memberExpression(pre, curr))
}
function CallCreateElementExpression(args) {
const t = types.cloneNode(toMemberExpress(config.pragma))
return types.callExpression(t, args)
}
function getTag(n) {
const tagExp = convertJSXIdentifier(n.node.name)
let tagName
if (types.isIdentifier(tagExp)) {
tagName = tagExp.name
} else if (types.isStringLiteral(tagExp)) {
tagName = tagExp.value
}
if (tagName && /^[a-z]*$/.test(tagName)) {
return types.stringLiteral(tagName)
} else {
return tagExp
}
}
/**
* 转化jsxName
* @param {*} node
* @returns
*/
function convertJSXIdentifier(node) {
if (types.isJSXIdentifier(node)) {
if (types.isValidIdentifier(node.name, false)) {
node.type = "Identifier" // 这里是因为下面的 type。memberExpression 需要type 为 Identifier的
} else {
return types.stringLiteral(node.name)
}
} else if (types.isJSXMemberExpression(node)) {
return types.memberExpression(convertJSXIdentifier(node.object), convertJSXIdentifier(node.property))
}
return node
}
function initProps(path) {
const attribs = path.get('attributes')
const objs = []
attribs.reduce(function(pre, cur) {
const node = cur.node
if (types.isJSXSpreadAttribute(cur)) {
const arg = node.argument
if (types.isObjectExpression(arg)) {
pre.push(...arg.properties)
} else {
pre.push(types.spreadElement(arg))
}
return pre
}
const t = cur.node.value || types.booleanLiteral(true)
const value = types.isJSXExpressionContainer(t) ? t.expression : t
if (types.isValidIdentifier(node.name.name, false)) {
node.name.type = "Identifier"
}
pre.push(types.objectProperty(node.name, value))
return pre
}, objs)
return types.objectExpression(objs)
}
function buildCreateElementExp(path) {
const openELe = path.get('openingElement')
return CallCreateElementExpression([getTag(openELe), initProps(openELe), ...types.react.buildChildren(path.node)])
}
const ast = parser.parse(sourceCode, {
plugins: ['jsx'],
sourceType: 'unambiguous'
})
const targetArr = ['log'].map(r => `console.${r}`)
traverse(ast, {
CallExpression(path) {
const node = path.node
if (node.isSkip) return
const calleeStr = path.get('callee').toString()
if (targetArr.includes(calleeStr)) {
let newLog = template.expression(`console.log('%c%s', 'color: green', '=======test=====')`)()
path.insertBefore(newLog)
newLog.isSkip = true
node.isSkip = true
}
},
JSXElement: {
exit(path, state) {
const node = path.node
const openEle = path.get('openingElement')
const newNode = buildCreateElementExp(path)
path.replaceWith(newNode)
}
}
})
const {
code
} = generator(ast)
console.log(code)
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else {
var a = factory();
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
}
})(self, () => {
return /******/ (() => { // webpackBootstrap
var __webpack_exports__ = {};
/*!***********************!*\
!*** ./src/index.jsx ***!
\***********************/
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
// import Light from './Light'
// class Modal extends Light.Component {
// render() {
// return <img width="200" src="http://qnpic.top/yoona2.jpg" />
// }
// }
// class TT extends Light.Component {
// render() {
// return (
// <div class="test" style={{
// color: '#cccccc'
// }}>
// 123
// <Modal></Modal>
// </div>
// )
// }
// }
// const root = document.getElementById('root') || document.body.appendChild(<div id="root"></div>)
// Light.renderDom(root, <TT></TT>)
var a = _defineProperty({
data: [1, 2, 3]
}, Symbol.iterator, function () {
var self = this;
var i = 0;
var len = self.data.length;
return {
next: function next() {
if (i < len) {
return {
value: self.data[i++],
done: false
};
} else {
return {
done: true
};
}
}
};
});
var _iterator = _createForOfIteratorHelper(a),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var i = _step.value;
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
/******/ return __webpack_exports__;
/******/ })()
;
});
//# sourceMappingURL=output.js.map
\ No newline at end of file
{"version":3,"file":"output.js","mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD,O;;;;;;;;;;;;;ACVA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AAEA,IAAMA,CAAC;EACLC,IAAI,EAAE,CAAC,CAAD,EAAG,CAAH,EAAK,CAAL;AADD,GAEJC,MAAM,CAACC,QAFH,EAEc,YAAW;EAC5B,IAAIC,IAAI,GAAG,IAAX;EACA,IAAIC,CAAC,GAAG,CAAR;EACA,IAAMC,GAAG,GAAGF,IAAI,CAACH,IAAL,CAAUM,MAAtB;EACA,OAAO;IACLC,IAAI,EAAE,gBAAW;MACf,IAAIH,CAAC,GAAGC,GAAR,EAAa;QACX,OAAO;UACLG,KAAK,EAAEL,IAAI,CAACH,IAAL,CAAUI,CAAC,EAAX,CADF;UAELK,IAAI,EAAE;QAFD,CAAP;MAID,CALD,MAKO;QACL,OAAO;UACLA,IAAI,EAAE;QADD,CAAP;MAGD;IACF;EAZI,CAAP;AAcD,CApBI,CAAP;;2CAsBcV;;;;EAAd,oDAAiB;IAAA,IAARK,CAAQ;EAAE","sources":["webpack://babellesson1/webpack/universalModuleDefinition","webpack://babellesson1/./src/index.jsx"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse {\n\t\tvar a = factory();\n\t\tfor(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];\n\t}\n})(self, () => {\nreturn ","// import Light from './Light'\n\n// class Modal extends Light.Component {\n// render() {\n// return <img width=\"200\" src=\"http://qnpic.top/yoona2.jpg\" />\n// }\n// }\n\n// class TT extends Light.Component {\n// render() {\n// return (\n// <div class=\"test\" style={{\n// color: '#cccccc'\n// }}>\n// 123\n// <Modal></Modal>\n// </div>\n// )\n// }\n// }\n\n// const root = document.getElementById('root') || document.body.appendChild(<div id=\"root\"></div>)\n\n// Light.renderDom(root, <TT></TT>)\n\nconst a = {\n data: [1,2,3],\n [Symbol.iterator]: function() {\n var self = this\n var i = 0\n const len = self.data.length\n return {\n next: function() {\n if (i < len) {\n return {\n value: self.data[i++],\n done: false\n }\n } else {\n return {\n done: true\n }\n }\n }\n }\n }\n}\nfor (let i of a) {}"],"names":["a","data","Symbol","iterator","self","i","len","length","next","value","done"],"sourceRoot":""}
\ No newline at end of file
{
"name": "babellesson1",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server",
"build": "webpack"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.19.3",
"@babel/plugin-syntax-jsx": "^7.18.6",
"babel-loader": "^8.2.5",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.11.1"
},
"dependencies": {
"@babel/preset-env": "^7.19.4"
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="output.js"></script>
</body>
</html>
\ No newline at end of file
export function render(dom, t) {
dom.appendChild(t)
}
export function createElement(tag, props, ...children) {
let el
if (typeof tag === 'string') {
el = document.createElement(tag)
// if (props.id) {
// el.id = props.id
// }
// if (props.style) {
// for (let k in props.style) {
// el.style[k] = props.style[k]
// }
// }
for (let k in props) {
const v = props[k]
if (typeof v == 'object') {
for (let s in v) {
el[k][s] = v[s]
}
} else {
el[k] = v
}
}
props.ref(el)
children.forEach(item => {
if (typeof item === 'string') {
item = document.createTextNode(item)
}
el.appendChild(item)
})
} else {
const ins = new tag(props)
return ins.render()
}
return el
}
export class Compent {
props
constructor(props) {
this.props = props
}
render() {
}
}
\ No newline at end of file
import { Compent, createElement, render } from "./createElement";
export default {
Component: Compent,
createElement: createElement,
renderDom: render
}
\ No newline at end of file
import Light from './Light'
class Modal extends Light.Component {
render() {
return <img width="200" src="http://qnpic.top/yoona2.jpg" />
}
}
class TT extends Light.Component {
render() {
return (
<div class="test" ref={(el ) => {}} style={{
color: '#cccccc'
}}>
123
<Modal></Modal>
</div>
)
}
}
const root = document.getElementById('root') || document.body.appendChild(<div id="root"></div>)
Light.renderDom(root, <TT></TT>)
// const a = {
// data: [1,2,3],
// [Symbol.iterator]: function() {
// var self = this
// var i = 0
// const len = self.data.length
// return {
// next: function() {
// if (i < len) {
// return {
// value: self.data[i++],
// done: false
// }
// } else {
// return {
// done: true
// }
// }
// }
// }
// }
// }
// for (let i of a) {}
\ No newline at end of file
const parser = require('@babel/parser')
const traverse = require('@babel/traverse').default
const generator = require('@babel/generator').default
const types = require('@babel/types')
const template = require('@babel/template').default
const {
transform,
transformFileSync
} = require('@babel/core')
const sourceCode = `
var a
if (true) {
console.log(a)
a = 5
function a() {let b}
function b() {}
a = 0
console.log(a)
}
console.log(a)
console.log(b)
const gn = (a, b) => a + b;
[1,2,3].map((t) => {
return 'stage' + t
})
import Light from './Light'
class TT extends Light.Component {
render() {
return (
<div className="test">123</div>
)
}
}
const root = document.getElementById('root') || document.body.appendChild(<div id="root"></div>)
Light.renderDom(root, <TT></TT>)
`
// const ast = parser.parse(sourceCode, {
// plugins: ['jsx'],
// sourceType: 'unambiguous'
// })
// const targetArr = ['log'].map(r => `console.${r}`)
// const config = {
// pragma: 'Light.createElement'
// }
// function toMemberExpress(str) {
// return str.split('.').map(n => types.identifier(n)).reduce((pre, curr) => types.memberExpression(pre, curr))
// }
// function CallCreateElementExpression(args) {
// const t = types.cloneNode(toMemberExpress(config.pragma))
// return types.callExpression(t, args)
// }
// function getTag(n) {
// const tagExp = convertJSXIdentifier(n.node.name)
// let tagName
// if (types.isIdentifier(tagExp)) {
// tagName = tagExp.name
// } else if (types.isStringLiteral(tagExp)) {
// tagName = tagExp.value
// }
// if (tagName && /^[a-z]*/.test(tagName)) {
// return types.stringLiteral(tagName)
// } else {
// return tagExp
// }
// }
// /**
// * 转化jsxName
// * @param {*} node
// * @returns
// */
// function convertJSXIdentifier(node) {
// if (types.isJSXIdentifier(node)) {
// if (types.isValidIdentifier(node.name, false)) {
// node.type = "Identifier" // 这里是因为下面的 type。memberExpression 需要type 为 Identifier的
// } else {
// return types.stringLiteral(node.name)
// }
// } else if (types.isJSXMemberExpression(node)) {
// return types.memberExpression(convertJSXIdentifier(node.object), convertJSXIdentifier(node.property))
// }
// return node
// }
// function initProps(path) {
// const attribs = path.get('attributes')
// const objs = []
// attribs.reduce(function(pre, cur) {
// const node = cur.node
// if (types.isJSXSpreadAttribute(cur)) {
// const arg = node.argument
// if (types.isObjectExpression(arg)) {
// pre.push(...arg.properties)
// } else {
// pre.push(types.spreadElement(arg))
// }
// return pre
// }
// const t = cur.node.value || types.booleanLiteral(true)
// const value = types.isJSXExpressionContainer(t) ? t.expression : t
// if (types.isValidIdentifier(node.name.name, false)) {
// node.name.type = "Identifier"
// }
// pre.push(types.objectProperty(node.name, value))
// return pre
// }, objs)
// return types.objectExpression(objs)
// }
// function buildCreateElementExp(path) {
// const openELe = path.get('openingElement')
// return CallCreateElementExpression([getTag(openELe), initProps(openELe), ...types.react.buildChildren(path.node)])
// }
// traverse(ast, {
// ArrowFunctionExpression(path, state) {
// const node = path.node
// console.log(node)
// const params = node.params
// let body = node.body
// if (!types.isBlockStatement(body)) {
// body = types.blockStatement([types.returnStatement(body)])
// }
// const functionExpression = types.functionExpression(null, params, body)
// path.replaceWith(functionExpression)
// },
// CallExpression(path) {
// const node = path.node
// if (node.isSkip) return
// const calleeStr = path.get('callee').toString()
// if (targetArr.includes(calleeStr)) {
// let newLog = template.expression(`console.log('%c%s', 'color: green', '=======test=====')`)()
// path.insertBefore(newLog)
// newLog.isSkip = true
// node.isSkip = true
// }
// },
// Program: {
// enter(path) {
// const pragma = config.pragma
// }
// },
// JSXElement: {
// exit(path, state) {
// const node = path.node
// const openEle = path.get('openingElement')
// const newNode = buildCreateElementExp(path)
// path.replaceWith(newNode)
// }
// }
// })
// const {
// code
// } = generator(ast)
// console.log(code)
// const arrowFunctionPlugin = {
// visitor: {
// ArrowFunctionExpression(path, state) {
// console.log(path)
// }
// }
// }
const testPlugin = require('./babel-plugins/babel-plugins-react-test.js')
// const {code} = transform(sourceCode, {
// plugins: [testPlugin]
// })
const {
code
} = transformFileSync('./src/index.jsx', {
plugins: [testPlugin]
})
console.log(code)
const path = require('path')
module.exports = {
mode: 'development',
devtool: 'source-map',
entry: {
index: './src/index'
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /(node_modules)/,
use: [
{
loader: 'babel-loader',
}
],
exclude: /node_modules/
}
],
},
resolve: {
alias: {
'@': './src'
},
extensions: ['.tsx', '.ts', '.js', '.jsx']
},
output: {
filename: 'output.js',
path: __dirname, // path.resolve(__dirname, './dist'),
libraryTarget: 'umd'
},
devServer: {
port: 9011,
hot: true
}
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment