修改了react-native的编译配置,将renderNative和i18n都以plugin的方式注入babel

This commit is contained in:
Xu Chang 2023-12-04 18:47:20 +08:00
parent 0e0ea10b51
commit 381503e494
6 changed files with 139 additions and 85 deletions

View File

@ -9,16 +9,37 @@ const Regex =
const ModuleDict = {};
const ReactNativeProjectDict = {};
function parseFileModuleAndNs(cwd, filename) {
const relativePath = relative(cwd, filename);
let cwd2 = cwd;
if (cwd.endsWith('native')) {
// react-native环境需要重新定位一下项目根目录
if (ReactNativeProjectDict.hasOwnProperty(cwd)) {
if (ReactNativeProjectDict[cwd]) {
cwd2 = join(cwd, '..');
}
}
else {
const nodeModulePath = join(cwd, '..', 'node_modules');
const packageJsonPath = join(cwd, '..', 'package.json');
if (fs.existsSync(packageJsonPath) && fs.existsSync(nodeModulePath)) {
ReactNativeProjectDict[cwd] = true;
cwd2 = join(cwd, '..');
}
else {
ReactNativeProjectDict[cwd] = false;
}
}
}
const relativePath = relative(cwd2, filename);
if (relativePath.startsWith('node_modules') || relativePath.startsWith('..')) { // 在测试环境下是相对路径
const moduleRelativePath = relativePath
.replace(/\\/g, '/')
.split('/')
.slice(0, 2);
const modulePath = join(cwd, ...moduleRelativePath);
const modulePath = join(cwd2, ...moduleRelativePath);
const moduleDir = moduleRelativePath[1];
let moduleName = ModuleDict[moduleDir];
@ -52,12 +73,12 @@ function parseFileModuleAndNs(cwd, filename) {
else {
let moduleName = ModuleDict['./'];
if (!moduleName) {
const { name } = require(join(cwd, 'package.json'));
const { name } = require(join(cwd2, 'package.json'));
ModuleDict['./'] = name;
moduleName = name;
}
const rel2paths = relative(cwd, filename)
const rel2paths = relative(cwd2, filename)
.replace(/\\/g, '/')
.split('/');
@ -123,55 +144,58 @@ module.exports = (babel) => {
) {
const { moduleName, ns } = parseFileModuleAndNs(cwd, filename);
const arguments = node.arguments;
const [arg0, arg1] = arguments;
assert(arg0);
if (arg1) {
// 一般是对象,也可能是变量,表达式不予考虑
if (t.isObjectExpression(arg1)) {
const { properties } = arg1;
const oakNsProp = properties.find(
ele => t.isStringLiteral(ele.key) && ele.key.value === oakNsPropName
);
if (!oakNsProp) {
properties.push(
t.objectProperty(t.stringLiteral(oakNsPropName), t.stringLiteral(ns)),
t.objectProperty(t.stringLiteral(oakModulePropName), t.stringLiteral(moduleName))
if (arguments.length < 2) {
// react-native会调用两次这里要保护一下
const [arg0, arg1] = arguments;
assert(arg0);
if (arg1) {
// 一般是对象,也可能是变量,表达式不予考虑
if (t.isObjectExpression(arg1)) {
const { properties } = arg1;
const oakNsProp = properties.find(
ele => t.isStringLiteral(ele.key) && ele.key.value === oakNsPropName
);
if (!oakNsProp) {
properties.push(
t.objectProperty(t.stringLiteral(oakNsPropName), t.stringLiteral(ns)),
t.objectProperty(t.stringLiteral(oakModulePropName), t.stringLiteral(moduleName))
);
}
}
else if (t.isIdentifier(arg1)) {
arguments.splice(1, 1, t.callExpression(
t.memberExpression(
t.identifier('Object'),
t.identifier('assign')
),
[
arg1,
t.objectExpression(
[
t.objectProperty(t.stringLiteral(oakNsPropName), t.stringLiteral(ns)),
t.objectProperty(t.stringLiteral(oakModulePropName), t.stringLiteral(moduleName))
]
)
]
));
}
else {
// 不处理,这里似乎会反复调用,不知道为什么
}
}
else if (t.isIdentifier(arg1)) {
arguments.splice(1, 1, t.callExpression(
t.memberExpression(
t.identifier('Object'),
t.identifier('assign')
),
[
arg1,
t.objectExpression(
[
t.objectProperty(t.stringLiteral(oakNsPropName), t.stringLiteral(ns)),
t.objectProperty(t.stringLiteral(oakModulePropName), t.stringLiteral(moduleName))
]
)
]
));
}
else {
// 不处理,这里似乎会反复调用,不知道为什么
// 如果无参数就构造一个对象传入
arguments.push(
t.objectExpression(
[
t.objectProperty(t.stringLiteral(oakNsPropName), t.stringLiteral(ns)),
t.objectProperty(t.stringLiteral(oakModulePropName), t.stringLiteral(moduleName))
]
)
)
}
}
else {
// 如果无参数就构造一个对象传入
arguments.push(
t.objectExpression(
[
t.objectProperty(t.stringLiteral(oakNsPropName), t.stringLiteral(ns)),
t.objectProperty(t.stringLiteral(oakModulePropName), t.stringLiteral(moduleName))
]
)
)
}
}
}
},

View File

@ -31,12 +31,14 @@ module.exports = (babel) => {
const pathProperty = properties.find(
ele => t.isObjectProperty(ele) && t.isIdentifier(ele.key) && ele.key.name === 'path'
);
// console.log(filename, 'oakPath');
if (pathProperty) {
console.warn(`${resolvePath}页面的OakPage中还是定义了path可以删除掉了`);
// react-native的编译器会走两次这里会被命中
// console.warn(`${resolvePath}页面的OakPage中还是定义了path可以删除掉了`);
pathProperty.value = t.stringLiteral(relativePath);
}
else {
properties.push(
properties.unshift(
t.objectProperty(t.identifier('path'), t.stringLiteral(relativePath))
);
}

View File

@ -0,0 +1,18 @@
const t = require('@babel/types');
const { parse } = require('path');
const { injectGetRender } = require('../utils/injectGetRender');
module.exports = (babel) => {
return {
visitor: {
CallExpression(path, state) {
const { cwd, filename } = state;
const { base } = parse(filename);
const node = path.node;
if (['index.ts', 'index.js'].includes(base) && t.isCallExpression(node) && t.isIdentifier(node.callee) && node.callee.name === 'OakComponent') {
injectGetRender(node, cwd, filename, 'native');
}
},
},
};
};

View File

@ -22,6 +22,8 @@ const replaceEnvExpressionPlugin = require('./babelEnvPlugin');
const { injectGetRender } = require('../utils/injectGetRender');
const oakPathTsxPlugin = require('../babel-plugin/oakPath');
const oakRenderNativePlugin = require('../babel-plugin/oakRenderNative');
const oakI18nPlugin = require('../babel-plugin/oakI18n');
async function renderToCSS({ src, filename, options = {} }) {
const { lessOptions = {} } = options;
@ -51,7 +53,7 @@ function transform({ filename, options, plugins, src }) {
cwd: options.projectRoot,
highlightCode: true,
filename,
plugins: plugins.concat([replaceEnvExpressionPlugin, oakPathTsxPlugin]),
plugins: plugins.concat([replaceEnvExpressionPlugin, oakPathTsxPlugin, oakRenderNativePlugin, oakI18nPlugin]),
sourceType: "module",
// NOTE(EvanBacon): We split the parse/transform steps up to accommodate
// Hermes parsing, but this defaults to cloning the AST which increases
@ -71,18 +73,19 @@ function transform({ filename, options, plugins, src }) {
const transformResult = transformFromAstSync(sourceAst, src, babelConfig);
// 为page和componet下的OakComponent注入getRender函数去取得同目录下的render.native.tsx
const resultAst = transformResult.ast;
const { base } = path.parse(filename);
if (['index.ts', 'index.js'].includes(base)) {
traverse(resultAst, {
CallExpression(path) {
const node = path.node;
if (t.isIdentifier(node.callee) && node.callee.name === 'OakComponent') {
injectGetRender(node, options.projectRoot, filename, 'native');
}
}
})
}
// 改成plugin注入
// const resultAst = transformResult.ast;
// const { base } = path.parse(filename);
// if (['index.ts', 'index.js'].includes(base)) {
// traverse(resultAst, {
// CallExpression(path) {
// const node = path.node;
// if (t.isIdentifier(node.callee) && node.callee.name === 'OakComponent') {
// injectGetRender(node, options.projectRoot, filename, 'native');
// }
// }
// })
// }
return {
ast: nullthrows(transformResult.ast),

View File

@ -161,31 +161,36 @@ function injectGetRender(node, projectRoot, filename, env) {
*/
const arg = node.arguments[0];
assert(t.isObjectExpression(arg));
const propertyRender = t.objectProperty(
t.identifier('getRender'),
t.functionExpression(null, [], t.blockStatement(
[
t.variableDeclaration('var', [
t.variableDeclarator(
t.identifier('oakRenderFn'),
t.memberExpression(
t.callExpression(
t.identifier('require'),
[
t.stringLiteral('./render')
]
// react-native的编译器会命中两次
if (!arg.properties.find(
(ele) => t.isObjectProperty(ele) && t.isIdentifier(ele.key) && ele.key.name === 'getRender'
)) {
const propertyRender = t.objectProperty(
t.identifier('getRender'),
t.functionExpression(null, [], t.blockStatement(
[
t.variableDeclaration('var', [
t.variableDeclarator(
t.identifier('oakRenderFn'),
t.memberExpression(
t.callExpression(
t.identifier('require'),
[
t.stringLiteral('./render')
]
),
t.identifier('default')
),
t.identifier('default')
),
)
]),
t.returnStatement(
t.identifier('oakRenderFn')
)
]),
t.returnStatement(
t.identifier('oakRenderFn')
)
]
))
);
arg.properties.unshift(propertyRender);
]
))
);
arg.properties.unshift(propertyRender);
}
}
}

View File

@ -11,6 +11,8 @@ buildscript {
ndkVersion = "23.1.7779620"
}
repositories {
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/jcenter' }
google()
mavenCentral()
}