新增复用OakComponent的插件支持
This commit is contained in:
parent
61f5a2c1c1
commit
784f5433d6
|
|
@ -0,0 +1,63 @@
|
|||
const t = require('@babel/types');
|
||||
const generate = require('@babel/generator').default;
|
||||
const { relative, dirname, parse, join } = require('path');
|
||||
const fs = require('fs');
|
||||
const { getStatements } = require('../utils/injectGetRender');
|
||||
|
||||
module.exports = (babel) => {
|
||||
return {
|
||||
visitor: {
|
||||
ExportDefaultDeclaration(path, state) {
|
||||
|
||||
const { declaration } = path.node;
|
||||
const { cwd, filename } = state;
|
||||
const { base } = parse(filename);
|
||||
if (['index.ts', 'index.js'].includes(base) && t.isIdentifier(declaration) && declaration.name === 'OakComponent') {
|
||||
const dir = dirname(filename);
|
||||
const statements = getStatements(dir);
|
||||
|
||||
const resetRenderFunction = t.arrowFunctionExpression(
|
||||
[],
|
||||
t.blockStatement([
|
||||
...statements
|
||||
])
|
||||
);
|
||||
|
||||
const newComponent = t.arrowFunctionExpression(
|
||||
[t.identifier('props')],
|
||||
t.blockStatement([
|
||||
t.returnStatement(
|
||||
t.callExpression(
|
||||
t.memberExpression(t.identifier('React'), t.identifier('createElement')),
|
||||
[
|
||||
t.identifier('OakComponent'),
|
||||
t.objectExpression([
|
||||
t.spreadElement(t.identifier('props')),
|
||||
// #开头的不是identifier,而是StringLiteral
|
||||
t.objectProperty(t.stringLiteral('#resetRender'), resetRenderFunction)
|
||||
])
|
||||
]
|
||||
)
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
// 输出一下生成的内容:
|
||||
// const { code } = generate(newComponent);
|
||||
// console.log(code);
|
||||
|
||||
path.replaceWith(
|
||||
t.exportDefaultDeclaration(newComponent)
|
||||
);
|
||||
|
||||
// 先判断有没有import React,没有的话,插入
|
||||
if (!path.findParent(t.File).node.body.some(node => t.isImportDeclaration(node) && node.source.value === 'react')) {
|
||||
path.insertBefore(t.importDeclaration([t.importDefaultSpecifier(t.identifier('React'))], t.stringLiteral('react')));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -4,6 +4,127 @@ const t = require('@babel/types');
|
|||
const traverse = require('@babel/traverse').default;
|
||||
const assert = require('assert');
|
||||
|
||||
function getStatements(dir) {
|
||||
// web要根据this.props.width的宽度决定注入web.tsx还是web.pc.tsx
|
||||
const tsxFile = join(dir, 'web.tsx');
|
||||
const jsFile = join(dir, 'web.js');
|
||||
const jsxFile = join(dir, 'web.jsx');
|
||||
|
||||
let webDestFile;
|
||||
if (fs.existsSync(tsxFile)) {
|
||||
webDestFile = './web.tsx';
|
||||
}
|
||||
else if (fs.existsSync(jsFile)) {
|
||||
webDestFile = './web.js';
|
||||
}
|
||||
else if (fs.existsSync(jsxFile)) {
|
||||
webDestFile = './web.jsx';
|
||||
}
|
||||
const acquireWebFileStmt = webDestFile && t.variableDeclaration('const', [
|
||||
t.variableDeclarator(
|
||||
t.identifier('oakRenderFn'),
|
||||
t.memberExpression(
|
||||
t.callExpression(t.identifier('require'), [
|
||||
t.stringLiteral(webDestFile),
|
||||
]),
|
||||
t.identifier('default')
|
||||
)
|
||||
),
|
||||
]);
|
||||
|
||||
let pcDestFile;
|
||||
const pcTsxFile = join(dir, 'web.pc.tsx');
|
||||
const pcJsFile = join(dir, 'web.pc.js');
|
||||
const pcJsxFile = join(dir, 'web.pc.jsx');
|
||||
if (fs.existsSync(pcTsxFile)) {
|
||||
pcDestFile = './web.pc.tsx';
|
||||
}
|
||||
else if (fs.existsSync(pcJsFile)) {
|
||||
pcDestFile = './web.pc.js';
|
||||
}
|
||||
else if (fs.existsSync(pcJsxFile)) {
|
||||
pcDestFile = './web.pc.jsx';
|
||||
}
|
||||
const acquirePcFileStmt = pcDestFile && t.variableDeclaration('const', [
|
||||
t.variableDeclarator(
|
||||
t.identifier('oakRenderFn'),
|
||||
t.memberExpression(
|
||||
t.callExpression(t.identifier('require'), [
|
||||
t.stringLiteral(pcDestFile),
|
||||
]),
|
||||
t.identifier('default')
|
||||
)
|
||||
),
|
||||
]);
|
||||
|
||||
const getStatementsInner = () => {
|
||||
/** 根据tsx文件存在的情况,注入如下的getRender函数
|
||||
* if (this.props.width === 'xs') {
|
||||
const oakRenderFn = require('./web.tsx').default;
|
||||
return oakRenderFn;
|
||||
}
|
||||
else {
|
||||
const oakRenderFn = require('./web.pc.tsx').default;
|
||||
return oakRenderFn;
|
||||
}
|
||||
*/
|
||||
const statements = [];
|
||||
if (acquirePcFileStmt && acquireWebFileStmt) {
|
||||
statements.push(
|
||||
t.ifStatement(
|
||||
t.binaryExpression(
|
||||
'===',
|
||||
t.memberExpression(
|
||||
t.memberExpression(
|
||||
t.thisExpression(),
|
||||
t.identifier('props')
|
||||
),
|
||||
t.identifier('width')
|
||||
),
|
||||
t.stringLiteral('xs')
|
||||
),
|
||||
t.blockStatement([
|
||||
acquireWebFileStmt,
|
||||
t.returnStatement(
|
||||
t.identifier('oakRenderFn')
|
||||
)
|
||||
]),
|
||||
t.blockStatement([
|
||||
acquirePcFileStmt,
|
||||
t.returnStatement(
|
||||
t.identifier('oakRenderFn')
|
||||
)
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (acquirePcFileStmt) {
|
||||
statements.push(
|
||||
acquirePcFileStmt,
|
||||
t.returnStatement(
|
||||
t.identifier('oakRenderFn')
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (acquireWebFileStmt) {
|
||||
statements.push(
|
||||
acquireWebFileStmt,
|
||||
t.returnStatement(
|
||||
t.identifier('oakRenderFn')
|
||||
)
|
||||
);
|
||||
} else {
|
||||
assert(
|
||||
false,
|
||||
`${dir}文件夹中不存在web.tsx或者web.pc.tsx,无法渲染`
|
||||
);
|
||||
}
|
||||
return statements;
|
||||
};
|
||||
|
||||
return getStatementsInner();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} node
|
||||
|
|
@ -15,123 +136,7 @@ function injectGetRender(node, projectRoot, filename, env) {
|
|||
assert(t.isCallExpression(node) && t.isIdentifier(node.callee) && node.callee.name === 'OakComponent');
|
||||
const dir = dirname(filename);
|
||||
if (env === 'web') {
|
||||
// web要根据this.props.width的宽度决定注入web.tsx还是web.pc.tsx
|
||||
const tsxFile = join(dir, 'web.tsx');
|
||||
const jsFile = join(dir, 'web.js');
|
||||
const jsxFile = join(dir, 'web.jsx');
|
||||
|
||||
let webDestFile;
|
||||
if (fs.existsSync(tsxFile)) {
|
||||
webDestFile = './web.tsx';
|
||||
}
|
||||
else if (fs.existsSync(jsFile)) {
|
||||
webDestFile = './web.js';
|
||||
}
|
||||
else if (fs.existsSync(jsxFile)) {
|
||||
webDestFile = './web.jsx';
|
||||
}
|
||||
const acquireWebFileStmt = webDestFile && t.variableDeclaration('const', [
|
||||
t.variableDeclarator(
|
||||
t.identifier('oakRenderFn'),
|
||||
t.memberExpression(
|
||||
t.callExpression(t.identifier('require'), [
|
||||
t.stringLiteral(webDestFile),
|
||||
]),
|
||||
t.identifier('default')
|
||||
)
|
||||
),
|
||||
]);
|
||||
|
||||
let pcDestFile;
|
||||
const pcTsxFile = join(dir, 'web.pc.tsx');
|
||||
const pcJsFile = join(dir, 'web.pc.js');
|
||||
const pcJsxFile = join(dir, 'web.pc.jsx');
|
||||
if (fs.existsSync(pcTsxFile)) {
|
||||
pcDestFile = './web.pc.tsx';
|
||||
}
|
||||
else if (fs.existsSync(pcJsFile)) {
|
||||
pcDestFile = './web.pc.js';
|
||||
}
|
||||
else if (fs.existsSync(pcJsxFile)) {
|
||||
pcDestFile = './web.pc.jsx';
|
||||
}
|
||||
const acquirePcFileStmt = pcDestFile && t.variableDeclaration('const', [
|
||||
t.variableDeclarator(
|
||||
t.identifier('oakRenderFn'),
|
||||
t.memberExpression(
|
||||
t.callExpression(t.identifier('require'), [
|
||||
t.stringLiteral(pcDestFile),
|
||||
]),
|
||||
t.identifier('default')
|
||||
)
|
||||
),
|
||||
]);
|
||||
|
||||
const getStatements = () => {
|
||||
/** 根据tsx文件存在的情况,注入如下的getRender函数
|
||||
* if (this.props.width === 'xs') {
|
||||
const oakRenderFn = require('./web.tsx').default;
|
||||
return oakRenderFn;
|
||||
}
|
||||
else {
|
||||
const oakRenderFn = require('./web.pc.tsx').default;
|
||||
return oakRenderFn;
|
||||
}
|
||||
*/
|
||||
const statements = [];
|
||||
if (acquirePcFileStmt && acquireWebFileStmt) {
|
||||
statements.push(
|
||||
t.ifStatement(
|
||||
t.binaryExpression(
|
||||
'===',
|
||||
t.memberExpression(
|
||||
t.memberExpression(
|
||||
t.thisExpression(),
|
||||
t.identifier('props')
|
||||
),
|
||||
t.identifier('width')
|
||||
),
|
||||
t.stringLiteral('xs')
|
||||
),
|
||||
t.blockStatement([
|
||||
acquireWebFileStmt,
|
||||
t.returnStatement(
|
||||
t.identifier('oakRenderFn')
|
||||
)
|
||||
]),
|
||||
t.blockStatement([
|
||||
acquirePcFileStmt,
|
||||
t.returnStatement(
|
||||
t.identifier('oakRenderFn')
|
||||
)
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (acquirePcFileStmt) {
|
||||
statements.push(
|
||||
acquirePcFileStmt,
|
||||
t.returnStatement(
|
||||
t.identifier('oakRenderFn')
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (acquireWebFileStmt) {
|
||||
statements.push(
|
||||
acquireWebFileStmt,
|
||||
t.returnStatement(
|
||||
t.identifier('oakRenderFn')
|
||||
)
|
||||
);
|
||||
} else {
|
||||
assert(
|
||||
false,
|
||||
`${dir}文件夹中不存在web.tsx或者web.pc.tsx,无法渲染`
|
||||
);
|
||||
}
|
||||
return statements;
|
||||
};
|
||||
const statements = getStatements();
|
||||
const statements = getStatements(dir);
|
||||
node.arguments.forEach((node4) => {
|
||||
if (t.isObjectExpression(node4)) {
|
||||
const propertyRender = t.objectProperty(
|
||||
|
|
@ -195,5 +200,6 @@ function injectGetRender(node, projectRoot, filename, env) {
|
|||
}
|
||||
|
||||
module.exports = {
|
||||
injectGetRender
|
||||
injectGetRender,
|
||||
getStatements
|
||||
};
|
||||
|
|
@ -34,6 +34,7 @@ const oakRenderTsxPlugin = require('../babel-plugin/oakRender');
|
|||
const oakI18nPlugin = require('../babel-plugin/oakI18n');
|
||||
const oakStylePlugin = require('../babel-plugin/oakStyle');
|
||||
const oakRpxToPxPlugin = require('../postcss-plugin/oakRpxToPx');
|
||||
const reuseOakComponentPlugin = require('../babel-plugin/reuse-oak-component');
|
||||
|
||||
// Source maps are resource heavy and can cause out of memory issue for large source files.
|
||||
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
|
||||
|
|
@ -582,6 +583,7 @@ module.exports = function (webpackEnv) {
|
|||
oakRenderTsxPlugin,
|
||||
// oakRouterPlugin,
|
||||
oakI18nPlugin,
|
||||
reuseOakComponentPlugin,
|
||||
// [
|
||||
// 'import',
|
||||
// {
|
||||
|
|
|
|||
Loading…
Reference in New Issue