修改了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 ModuleDict = {};
const ReactNativeProjectDict = {};
function parseFileModuleAndNs(cwd, filename) { 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('..')) { // 在测试环境下是相对路径 if (relativePath.startsWith('node_modules') || relativePath.startsWith('..')) { // 在测试环境下是相对路径
const moduleRelativePath = relativePath const moduleRelativePath = relativePath
.replace(/\\/g, '/') .replace(/\\/g, '/')
.split('/') .split('/')
.slice(0, 2); .slice(0, 2);
const modulePath = join(cwd, ...moduleRelativePath); const modulePath = join(cwd2, ...moduleRelativePath);
const moduleDir = moduleRelativePath[1]; const moduleDir = moduleRelativePath[1];
let moduleName = ModuleDict[moduleDir]; let moduleName = ModuleDict[moduleDir];
@ -52,12 +73,12 @@ function parseFileModuleAndNs(cwd, filename) {
else { else {
let moduleName = ModuleDict['./']; let moduleName = ModuleDict['./'];
if (!moduleName) { if (!moduleName) {
const { name } = require(join(cwd, 'package.json')); const { name } = require(join(cwd2, 'package.json'));
ModuleDict['./'] = name; ModuleDict['./'] = name;
moduleName = name; moduleName = name;
} }
const rel2paths = relative(cwd, filename) const rel2paths = relative(cwd2, filename)
.replace(/\\/g, '/') .replace(/\\/g, '/')
.split('/'); .split('/');
@ -123,6 +144,8 @@ module.exports = (babel) => {
) { ) {
const { moduleName, ns } = parseFileModuleAndNs(cwd, filename); const { moduleName, ns } = parseFileModuleAndNs(cwd, filename);
const arguments = node.arguments; const arguments = node.arguments;
if (arguments.length < 2) {
// react-native会调用两次这里要保护一下
const [arg0, arg1] = arguments; const [arg0, arg1] = arguments;
assert(arg0); assert(arg0);
@ -174,6 +197,7 @@ module.exports = (babel) => {
} }
} }
} }
}
}, },
}, },
}; };

View File

@ -31,12 +31,14 @@ module.exports = (babel) => {
const pathProperty = properties.find( const pathProperty = properties.find(
ele => t.isObjectProperty(ele) && t.isIdentifier(ele.key) && ele.key.name === 'path' ele => t.isObjectProperty(ele) && t.isIdentifier(ele.key) && ele.key.name === 'path'
); );
// console.log(filename, 'oakPath');
if (pathProperty) { if (pathProperty) {
console.warn(`${resolvePath}页面的OakPage中还是定义了path可以删除掉了`); // react-native的编译器会走两次这里会被命中
// console.warn(`${resolvePath}页面的OakPage中还是定义了path可以删除掉了`);
pathProperty.value = t.stringLiteral(relativePath); pathProperty.value = t.stringLiteral(relativePath);
} }
else { else {
properties.push( properties.unshift(
t.objectProperty(t.identifier('path'), t.stringLiteral(relativePath)) 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 { injectGetRender } = require('../utils/injectGetRender');
const oakPathTsxPlugin = require('../babel-plugin/oakPath'); const oakPathTsxPlugin = require('../babel-plugin/oakPath');
const oakRenderNativePlugin = require('../babel-plugin/oakRenderNative');
const oakI18nPlugin = require('../babel-plugin/oakI18n');
async function renderToCSS({ src, filename, options = {} }) { async function renderToCSS({ src, filename, options = {} }) {
const { lessOptions = {} } = options; const { lessOptions = {} } = options;
@ -51,7 +53,7 @@ function transform({ filename, options, plugins, src }) {
cwd: options.projectRoot, cwd: options.projectRoot,
highlightCode: true, highlightCode: true,
filename, filename,
plugins: plugins.concat([replaceEnvExpressionPlugin, oakPathTsxPlugin]), plugins: plugins.concat([replaceEnvExpressionPlugin, oakPathTsxPlugin, oakRenderNativePlugin, oakI18nPlugin]),
sourceType: "module", sourceType: "module",
// NOTE(EvanBacon): We split the parse/transform steps up to accommodate // NOTE(EvanBacon): We split the parse/transform steps up to accommodate
// Hermes parsing, but this defaults to cloning the AST which increases // 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); const transformResult = transformFromAstSync(sourceAst, src, babelConfig);
// 为page和componet下的OakComponent注入getRender函数去取得同目录下的render.native.tsx // 为page和componet下的OakComponent注入getRender函数去取得同目录下的render.native.tsx
const resultAst = transformResult.ast; // 改成plugin注入
const { base } = path.parse(filename); // const resultAst = transformResult.ast;
if (['index.ts', 'index.js'].includes(base)) { // const { base } = path.parse(filename);
traverse(resultAst, { // if (['index.ts', 'index.js'].includes(base)) {
CallExpression(path) { // traverse(resultAst, {
const node = path.node; // CallExpression(path) {
if (t.isIdentifier(node.callee) && node.callee.name === 'OakComponent') { // const node = path.node;
injectGetRender(node, options.projectRoot, filename, 'native'); // if (t.isIdentifier(node.callee) && node.callee.name === 'OakComponent') {
} // injectGetRender(node, options.projectRoot, filename, 'native');
} // }
}) // }
} // })
// }
return { return {
ast: nullthrows(transformResult.ast), ast: nullthrows(transformResult.ast),

View File

@ -161,6 +161,10 @@ function injectGetRender(node, projectRoot, filename, env) {
*/ */
const arg = node.arguments[0]; const arg = node.arguments[0];
assert(t.isObjectExpression(arg)); assert(t.isObjectExpression(arg));
// react-native的编译器会命中两次
if (!arg.properties.find(
(ele) => t.isObjectProperty(ele) && t.isIdentifier(ele.key) && ele.key.name === 'getRender'
)) {
const propertyRender = t.objectProperty( const propertyRender = t.objectProperty(
t.identifier('getRender'), t.identifier('getRender'),
t.functionExpression(null, [], t.blockStatement( t.functionExpression(null, [], t.blockStatement(
@ -188,6 +192,7 @@ function injectGetRender(node, projectRoot, filename, env) {
arg.properties.unshift(propertyRender); arg.properties.unshift(propertyRender);
} }
} }
}
module.exports = { module.exports = {
injectGetRender injectGetRender

View File

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