@areslabs/alita-core
Version:
alita-core
511 lines (422 loc) • 16 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _default;
exports.getFinalSource = getFinalSource;
var npath = _interopRequireWildcard(require("path"));
var path = npath;
var _ErrorLogTraverse = _interopRequireDefault(require("../util/ErrorLogTraverse"));
var t = _interopRequireWildcard(require("@babel/types"));
var _util = require("../util/util");
var _configure = _interopRequireDefault(require("../configure"));
var _cacheModuleInfos = require("../util/cacheModuleInfos");
var fse = _interopRequireWildcard(require("fs-extra"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
/**
* Copyright (c) Areslabs.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
function _default(ast, filepath, webpackContext) {
const appJSON = {
pages: [],
window: {
"backgroundTextStyle": "light",
'backgroundColor': '#E9E9E9',
'enablePullDownRefresh': false
}
};
const moduleMap = {};
const pngMap = {};
const pageInfos = [];
const tabInfos = [];
const go = (0, _util.geneOrder)('_');
(0, _ErrorLogTraverse.default)(ast, {
enter: path => {
if (path.type === 'StringLiteral' && (0, _util.isStaticRes)(path.node.value)) {
const pp = path.parentPath;
if (pp.type === 'VariableDeclarator') {
// @ts-ignore
pngMap[pp.node.id.name] = path.node.value;
pp.parentPath.remove();
}
return;
}
if (path.type === 'ImportDeclaration') {
const pnode = path.node;
const source = pnode.source.value;
const rs = getRealSource(source, filepath);
const originPath = getOriginPath(rs, filepath);
const specifiers = pnode.specifiers;
specifiers.forEach(spe => {
const name = spe.local.name;
moduleMap[name] = {
originPath,
// @ts-ignore
attri: spe.imported ? spe.imported.name : 'default',
source: source
}; //originPath
});
return;
} // require 目录 小程序不支持需要处理
// @ts-ignore
if (path.type === 'CallExpression' && path.node.callee.type === 'Identifier' && path.node.callee.name === 'require') {
// @ts-ignore
const source = path.node.arguments[0].value;
const rs = getRealSource(source, filepath);
const originPath = getOriginPath(rs, filepath); // @ts-ignore
const id = path.parentPath.node.id;
if (id.type === 'Identifier') {
moduleMap[id.name] = {
originPath,
attri: '',
source: source
};
} else if (id.type === 'ObjectPattern') {
id.properties.map(pro => {
if (pro.type === 'ObjectProperty') {
moduleMap[pro.value.name] = {
originPath,
attri: pro.key.name,
source: source
};
}
});
}
return;
}
},
exit: path => {
if (path.type === 'JSXAttribute' // @ts-ignore
&& (path.node.name.name === 'image' || path.node.name.name === 'selectedImage') // @ts-ignore
&& path.parentPath.node.name.name === 'TabRouter') {
// @ts-ignore
const v = path.node.value;
if (v.type === 'JSXExpressionContainer') {
const picName = v.expression.name; // @ts-ignore
path.node.value = t.stringLiteral(pngMap[picName]);
}
return;
} // @ts-ignore
if (path.type === 'JSXOpeningElement' && path.node.name.name === 'Route') {
let compAttri = null;
let key = null;
let subpage = null;
const pnode = path.node;
pnode.attributes.forEach(ele => {
ele = ele;
if (ele.name.name === 'component') {
compAttri = ele;
}
if (ele.name.name === 'key') {
if (ele.value.type === 'JSXExpressionContainer' && ele.value.expression.type === 'StringLiteral') {
key = ele.value.expression.value;
}
if (ele.value.type === 'StringLiteral') {
key = ele.value.value;
}
}
if (ele.name.name === 'subpage') {
if (ele.value.type === 'JSXExpressionContainer' && ele.value.expression.type === 'StringLiteral') {
subpage = ele.value.expression.value;
}
if (ele.value.type === 'StringLiteral') {
subpage = ele.value.value;
}
}
});
const name = compAttri.value.expression.name;
pageInfos.push({
comp: name,
subpage: subpage,
key: key
});
pnode.attributes.push(t.jsxAttribute(t.jsxIdentifier('diuu'), t.stringLiteral(go.next)));
if (subpage) {
// 分包的依赖将会被处理为异步加载,固这里需要处理其引用,以免报错
path.node.name.name = 'view';
path.parentPath.node.closingElement && (path.parentPath.node.closingElement.name.name = 'view'); // @ts-ignore
pnode.attributes = pnode.attributes.filter(attri => attri.name.name !== 'component');
}
return;
} // @ts-ignore
if (path.type === 'JSXOpeningElement' && path.node.name.name === 'TabRouter') {
const pp = path.parentPath; // @ts-ignore
const children = pp.node.children;
let initKey = null;
for (let i = 0; i < children.length; i++) {
const child = children[i];
if (child.type === 'JSXElement' && child.openingElement.name.name === 'Route') {
const oe = child.openingElement;
const keyAttr = oe.attributes.filter(ele => ele.name.name === 'key')[0];
if (keyAttr.value.type === 'JSXExpressionContainer' && keyAttr.value.expression.type === 'StringLiteral') {
initKey = keyAttr.value.expression.value;
}
if (keyAttr.value.type === 'StringLiteral') {
initKey = keyAttr.value.value;
}
break;
}
}
const tabBarElement = {
initKey: initKey
};
const pnode = path.node;
pnode.attributes.forEach(attri => {
attri = attri;
const v = attri.value.value;
if (attri.name.name === 'text') {
tabBarElement.text = v;
}
if (attri.name.name === 'image') {
tabBarElement.iconPath = v;
}
if (attri.name.name === 'selectedImage') {
tabBarElement.selectedIconPath = v;
}
});
tabInfos.push(tabBarElement);
pnode.attributes.push(t.jsxAttribute(t.jsxIdentifier('diuu'), t.stringLiteral(go.next)));
return;
}
if (path.type === 'JSXOpeningElement') {
const jsxOp = path.node;
const key = go.next;
jsxOp.attributes.push(t.jsxAttribute(t.jsxIdentifier('diuu'), t.stringLiteral(key)));
return;
}
if (path.type === 'JSXAttribute' && path.node.name.name === 'wxNavigationOptions') {
const value = path.node.value;
if (value.type === 'JSXExpressionContainer' && value.expression.type === 'ObjectExpression') {
const v = value.expression;
const props = v.properties;
for (let i = 0; i < props.length; i++) {
const p = props[i];
const k = p.key.name;
const v = p.value.value;
appJSON.window[k] = v;
}
}
return;
}
}
});
const tabBarList = getTabbarList(tabInfos, pageInfos, moduleMap);
if (tabBarList.length > 0) {
appJSON.tabBar = {
list: tabBarList
};
}
const {
historyMap,
pageCompPaths,
pagePaths,
pages,
subpackages,
removeModules,
ensureStatements,
allChunks
} = miscPageInfos(pageInfos, moduleMap);
_configure.default.allChunks = allChunks;
appJSON.pages = pages;
if (subpackages.length > 0) {
appJSON.subpackages = subpackages;
}
(0, _ErrorLogTraverse.default)(ast, {
exit: path => {
if (path.type === 'ExportDefaultDeclaration') {
// @ts-ignore
if (path.node.declaration.type === 'ClassDeclaration') {
// TODO 可能存在其他情况吗
// @ts-ignore
path.node.declaration.type = 'ClassExpression';
}
path.replaceWith(t.variableDeclaration('const', [// @ts-ignore
t.variableDeclarator(t.identifier('RNAppClass'), path.node.declaration)]));
}
if (path.type === 'ImportDeclaration') {
const pnode = path.node;
const source = pnode.source.value;
if (removeModules.has(source)) {
path.remove();
}
return;
}
if (path.type === 'CallExpression' && path.node.callee.type === 'Identifier' && path.node.callee.name === 'require') {
// @ts-ignore
const source = path.node.arguments[0].value;
if (removeModules.has(source)) {
path.parentPath.parentPath.remove();
}
return;
} // module.exports = A => const RNAppClass = A
if (path.type === 'AssignmentExpression' // @ts-ignore
&& path.node.operator === '=' // @ts-ignore
&& path.node.left.type === 'MemberExpression' // @ts-ignore
&& path.node.left.object.name === 'module' // @ts-ignore
&& path.node.left.property.name === 'exports') {
path.parentPath.replaceWith(t.variableDeclaration('const', [// @ts-ignore
t.variableDeclarator(t.identifier('RNAppClass'), path.node.right)]));
}
if (path.type === 'Program') {
/* 导出 RNApp 实例
* const RNApp = new RNAppClass()
* RNApp.childContext = RNApp.getChildContext ? RNApp.getChildContext() : {}
* export default RNApp
*/
const pnode = path.node; // be lazy
pnode.body.push(t.expressionStatement(t.identifier(`React.renderApp(RNAppClass)`)));
/**
* 初始化路由
*/
// be lazy
pnode.body.push(t.expressionStatement(t.identifier(`wx._historyConfig = ${JSON.stringify(historyMap, null)}`))); // be lazy
pnode.body.push(t.expressionStatement(t.assignmentExpression('=', t.identifier('wx._pageCompMaps'), t.objectExpression(pageCompPaths))));
pnode.body.push(t.expressionStatement(t.identifier(`wx._getCompByPath = function(path) {
return new Promise((resolve) =>{
if (wx._pageCompMaps[path]) {
resolve(wx._pageCompMaps[path])
} else {
wx._pageCompMaps[path] = resolve
}
})
}`)));
ensureStatements.forEach(state => {
pnode.body.push(state);
});
}
}
});
(0, _cacheModuleInfos.setEntryModuleInfo)(filepath, {
appJSON
});
return {
entryAst: ast,
allCompSet: new Set(pagePaths)
};
}
function getOriginPath(source, filepath) {
const originPath = npath.resolve(npath.dirname(filepath), source).replace(_configure.default.inputFullpath + npath.sep, '').replace(/\\/g, '/'); // 考虑win平台
return originPath;
}
function getRealSource(source, filepath) {
if (npath.extname(source) !== '') {
return source;
} // 小程序不支持require/import 一个目录
if (source.startsWith('/') || source.startsWith('./') || source.startsWith('../')) {
return getFinalSource(filepath, source);
} else {
return source;
}
}
/**
* 获取 最终的导入路径,如果导入的是目录,需要补全index
* @param filepath
* @param source
*/
function getFinalSource(filepath, source) {
const originalPath = path.resolve(path.dirname(filepath), source);
if (fse.existsSync(originalPath)) {
return `${source}/index`;
}
return source;
}
function getTabbarList(tabInfos, pageInfos, moduleMap) {
const tabBarList = [];
for (let i = 0; i < tabInfos.length; i++) {
const tabInfo = tabInfos[i];
const initKey = tabInfo.initKey;
const initCompInfo = pageInfos.filter(info => info.key === initKey)[0]; // tab页必需在主包
initCompInfo.subpage = null;
const projectRelativePath = moduleMap[initCompInfo.comp].originPath;
tabBarList.push({
pagePath: projectRelativePath,
text: tabInfo.text,
iconPath: tabInfo.iconPath,
selectedIconPath: tabInfo.selectedIconPath
});
}
return tabBarList;
}
function miscPageInfos(pageInfos, moduleMap) {
const pages = [];
const subpages = {};
const pagePaths = [];
const historyMap = {};
const pageCompPaths = [];
const allChunks = ['_rn_'];
const removeModules = new Set();
for (let i = 0; i < pageInfos.length; i++) {
const info = pageInfos[i];
const {
comp,
subpage,
key
} = info;
const projectRelativePath = moduleMap[comp].originPath;
pagePaths.push(projectRelativePath);
if (!subpage) {
pages.push(projectRelativePath);
historyMap[key] = `/${projectRelativePath}`;
pageCompPaths.push(t.objectProperty(t.stringLiteral(projectRelativePath), t.identifier(comp)));
} else {
if (!subpages[subpage]) {
subpages[subpage] = [];
}
subpages[subpage].push(comp);
removeModules.add(moduleMap[comp].source);
historyMap[key] = `/${subpage}/${projectRelativePath}`;
}
}
const ensureStatements = [];
const subpackages = [];
const allSubPages = Object.keys(subpages);
for (let i = 0; i < allSubPages.length; i++) {
const subpage = allSubPages[i];
allChunks.push(`${subpage}/_rn_`);
const allComps = subpages[subpage];
const depsStr = allComps.map(comp => `"${moduleMap[comp].source}"`).join(',');
let requireStr = allComps.map(comp => {
const {
source,
attri
} = moduleMap[comp];
return `var ${comp} = require("${source}")${attri ? `.${attri}` : ''}`;
}).join(';');
const pageCompResolve = allComps.map(comp => {
return `
compOrResolve = wx._pageCompMaps["${moduleMap[comp].originPath}"];
if (typeof compOrResolve === "function") {
compOrResolve(${comp});
};
wx._pageCompMaps["${moduleMap[comp].originPath}"] = ${comp};
`;
}).join(';');
let callbackStr = `(require) => {${requireStr};
var compOrResolve;
${pageCompResolve}}`;
let chunkName = `"${subpage}/_rn_"`;
const ensureStatement = t.expressionStatement(t.identifier(`require.ensure([${depsStr}], ${callbackStr}, ${chunkName});`));
ensureStatements.push(ensureStatement);
subpackages.push({
root: subpage,
name: subpage,
pages: allComps.map(comp => moduleMap[comp].originPath)
});
}
return {
pages,
subpackages,
ensureStatements,
removeModules,
pagePaths,
historyMap,
pageCompPaths,
allChunks
};
}