增加了大量和native相关的代码
This commit is contained in:
parent
ca48f105fb
commit
5091c4a730
|
|
@ -1,275 +1,17 @@
|
|||
const fs = require('fs');
|
||||
const { relative, resolve } = require('path');
|
||||
const t = require('@babel/types');
|
||||
const assert = require('assert');
|
||||
const { parse } = require('path');
|
||||
const { injectGetRender } = require('../utils/injectGetRender');
|
||||
|
||||
module.exports = (babel) => {
|
||||
return {
|
||||
visitor: {
|
||||
Program(path, state) {
|
||||
CallExpression(path, state) {
|
||||
const { cwd, filename } = state;
|
||||
const rel = relative(cwd, filename).replace(/\\/g, '/');
|
||||
const tsPage = /(pages|components|namespaces)[\\/][\w|\W]+[\\/]index\.ts$/.test(rel);
|
||||
const jsPage = /(pages|components|namespaces)[\\/][\w|\W]+[\\/]index\.js$/.test(rel);
|
||||
if (tsPage || jsPage) {
|
||||
const tsxFile = filename.replace(
|
||||
/index\.(ts|js)$/,
|
||||
tsPage ? 'web.tsx' : 'web.jsx'
|
||||
);
|
||||
const jsFile = filename.replace(
|
||||
/index\.(ts|js)$/,
|
||||
'web.js'
|
||||
);
|
||||
const xmlFile = filename.replace(
|
||||
/index\.(ts|js)$/,
|
||||
'index.xml'
|
||||
);
|
||||
const xmlFileExists = fs.existsSync(xmlFile);
|
||||
|
||||
const tsxFileExists = fs.existsSync(tsxFile);
|
||||
const jsFileExists = fs.existsSync(jsFile);
|
||||
const pcTsxFile = filename.replace(
|
||||
/index\.(ts|js)$/,
|
||||
tsPage ? 'web.pc.tsx' : 'web.pc.jsx'
|
||||
);
|
||||
const pcJsFile = filename.replace(
|
||||
/index\.(ts|js)$/,
|
||||
'web.pc.js'
|
||||
);
|
||||
const pcTsxFileExists = fs.existsSync(pcTsxFile);
|
||||
const pcJsFileExists = fs.existsSync(pcJsFile);
|
||||
|
||||
|
||||
/** 根据tsx文件存在的情况,注入如下的render代码
|
||||
* if (this.props.width === 'xs') {
|
||||
const renderMobile = require('./web.tsx').default;
|
||||
return renderMobile.call(this);
|
||||
}
|
||||
else {
|
||||
const renderScreen = require('./web.pc.tsx').default;
|
||||
return renderScreen.call(this);
|
||||
}
|
||||
*/
|
||||
const renderTsxStatements = [
|
||||
t.variableDeclaration('const', [
|
||||
t.variableDeclarator(
|
||||
t.identifier('render'),
|
||||
t.memberExpression(
|
||||
t.callExpression(t.identifier('require'), [
|
||||
t.stringLiteral(
|
||||
`./web.${tsPage ? 'tsx' : 'jsx'}`
|
||||
),
|
||||
]),
|
||||
t.identifier('default')
|
||||
)
|
||||
),
|
||||
]),
|
||||
t.returnStatement(
|
||||
t.identifier('render')
|
||||
),
|
||||
];
|
||||
const renderJsStatements = [
|
||||
t.variableDeclaration('const', [
|
||||
t.variableDeclarator(
|
||||
t.identifier('render'),
|
||||
t.memberExpression(
|
||||
t.callExpression(t.identifier('require'), [
|
||||
t.stringLiteral('./web.js'),
|
||||
]),
|
||||
t.identifier('default')
|
||||
)
|
||||
),
|
||||
]),
|
||||
t.returnStatement(
|
||||
t.identifier('render')
|
||||
),
|
||||
];
|
||||
const renderPcTsxStatements = [
|
||||
t.variableDeclaration('const', [
|
||||
t.variableDeclarator(
|
||||
t.identifier('render'),
|
||||
t.memberExpression(
|
||||
t.callExpression(t.identifier('require'), [
|
||||
t.stringLiteral(
|
||||
`./web.pc.${tsPage ? 'tsx' : 'jsx'}`
|
||||
),
|
||||
]),
|
||||
t.identifier('default')
|
||||
)
|
||||
),
|
||||
]),
|
||||
t.returnStatement(
|
||||
t.identifier('render')
|
||||
),
|
||||
];
|
||||
const renderPcJsStatements = [
|
||||
t.variableDeclaration('const', [
|
||||
t.variableDeclarator(
|
||||
t.identifier('render'),
|
||||
t.memberExpression(
|
||||
t.callExpression(t.identifier('require'), [
|
||||
t.stringLiteral('./web.pc.js'),
|
||||
]),
|
||||
t.identifier('default')
|
||||
)
|
||||
),
|
||||
]),
|
||||
t.returnStatement(
|
||||
t.identifier('render')
|
||||
),
|
||||
];
|
||||
const getStatements = () => {
|
||||
const statements = [];
|
||||
if (tsxFileExists && pcTsxFileExists) {
|
||||
statements.push(
|
||||
t.ifStatement(
|
||||
t.binaryExpression(
|
||||
'===',
|
||||
t.memberExpression(
|
||||
t.memberExpression(
|
||||
t.thisExpression(),
|
||||
t.identifier('props')
|
||||
),
|
||||
t.identifier('width')
|
||||
),
|
||||
t.stringLiteral('xs')
|
||||
),
|
||||
t.blockStatement(renderTsxStatements),
|
||||
t.blockStatement(renderPcTsxStatements)
|
||||
)
|
||||
);
|
||||
} else if (jsFileExists && pcJsFileExists) {
|
||||
statements.push(
|
||||
t.ifStatement(
|
||||
t.binaryExpression(
|
||||
'===',
|
||||
t.memberExpression(
|
||||
t.memberExpression(
|
||||
t.thisExpression(),
|
||||
t.identifier('props')
|
||||
),
|
||||
t.identifier('width')
|
||||
),
|
||||
t.stringLiteral('xs')
|
||||
),
|
||||
t.blockStatement(renderJsStatements),
|
||||
t.blockStatement(renderPcJsStatements)
|
||||
)
|
||||
);
|
||||
} else if (jsFileExists && pcTsxFileExists) {
|
||||
statements.push(
|
||||
t.ifStatement(
|
||||
t.binaryExpression(
|
||||
'===',
|
||||
t.memberExpression(
|
||||
t.memberExpression(
|
||||
t.thisExpression(),
|
||||
t.identifier('props')
|
||||
),
|
||||
t.identifier('width')
|
||||
),
|
||||
t.stringLiteral('xs')
|
||||
),
|
||||
t.blockStatement(renderJsStatements),
|
||||
t.blockStatement(renderPcTsxStatements)
|
||||
)
|
||||
);
|
||||
} else if (tsxFileExists && pcJsFileExists) {
|
||||
statements.push(
|
||||
t.ifStatement(
|
||||
t.binaryExpression(
|
||||
'===',
|
||||
t.memberExpression(
|
||||
t.memberExpression(
|
||||
t.thisExpression(),
|
||||
t.identifier('props')
|
||||
),
|
||||
t.identifier('width')
|
||||
),
|
||||
t.stringLiteral('xs')
|
||||
),
|
||||
t.blockStatement(renderTsxStatements),
|
||||
t.blockStatement(renderPcJsStatements)
|
||||
)
|
||||
);
|
||||
} else if (tsxFileExists) {
|
||||
statements.push(...renderTsxStatements);
|
||||
} else if (pcTsxFileExists) {
|
||||
statements.push(...renderPcTsxStatements);
|
||||
} else if (jsFileExists) {
|
||||
statements.push(...renderJsStatements);
|
||||
} else if (pcJsFileExists) {
|
||||
statements.push(...renderPcJsStatements);
|
||||
} else if (!xmlFileExists) {
|
||||
assert(
|
||||
false,
|
||||
`${filename}文件中不存在web.tsx或者web.pc.tsx`
|
||||
);
|
||||
}
|
||||
return statements;
|
||||
};
|
||||
const node = path.node;
|
||||
const body = node.body;
|
||||
body.forEach((node2) => {
|
||||
// export default OakComponent({})
|
||||
if (t.isExportDefaultDeclaration(node2)) {
|
||||
let node3 = node2.declaration;
|
||||
if (node3) {
|
||||
if (t.isTSAsExpression(node3)) {
|
||||
// export default OakComponent({}) as ....
|
||||
node3 = node3.expression;
|
||||
}
|
||||
}
|
||||
|
||||
if (t.isCallExpression(node3) && node3.callee.name === 'OakComponent') {
|
||||
const statements = getStatements();
|
||||
node3.arguments.forEach((node4) => {
|
||||
if (t.isObjectExpression(node4)) {
|
||||
const propertyRender = t.objectProperty(
|
||||
t.identifier('getRender'),
|
||||
t.functionExpression(
|
||||
null,
|
||||
[],
|
||||
t.blockStatement(statements)
|
||||
)
|
||||
);
|
||||
node4.properties.unshift(propertyRender);
|
||||
}
|
||||
else {
|
||||
assert(false, `[${filename}]OakComponent调用参数不是ObjectExpression`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// exports.default = OakPage({})、exports.default = OakComponent({})
|
||||
else if (
|
||||
t.isExpressionStatement(node2) &&
|
||||
t.isAssignmentExpression(node2.expression) &&
|
||||
t.isCallExpression(node2.expression.right) &&
|
||||
t.isIdentifier(node2.expression.right.callee) &&
|
||||
node2.expression.right.callee.name ===
|
||||
'OakComponent'
|
||||
) {
|
||||
const statements = getStatements();
|
||||
node2.expression.right.arguments.forEach(
|
||||
(node3) => {
|
||||
if (t.isObjectExpression(node3)) {
|
||||
const propertyRender = t.objectProperty(
|
||||
t.identifier('getRender'),
|
||||
t.functionExpression(
|
||||
null,
|
||||
[],
|
||||
t.blockStatement(statements)
|
||||
)
|
||||
);
|
||||
node3.properties.unshift(
|
||||
propertyRender
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
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') {
|
||||
console.log(filename, base);
|
||||
injectGetRender(node, cwd, filename, 'web');
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
const { resolve } = require('path');
|
||||
const watchFolders = process.env.NODE_ENV === 'production' ? ['../src', '../node_modules'] : [
|
||||
'../src', '../node_modules', '../../oak-domain', '../../oak-common-aspect', '../../oak-external-sdk',
|
||||
'../../oak-frontend-base', '../../oak-general-business', '../../oak-memory-tree-store'
|
||||
];
|
||||
|
||||
const sourceExts = (process.env.NODE_ENV === 'production' || process.env.PROD === 'true') ?
|
||||
['prod.ts', 'ts', 'tsx', 'prod.js', 'js', 'jsx', 'less', 'json'] :
|
||||
['dev.ts', 'ts', 'tsx', 'dev.js', 'js', 'jsx', 'less', 'json'];
|
||||
|
||||
const NullModules = ['fs', 'url'];
|
||||
/**
|
||||
* Metro configuration
|
||||
* https://facebook.github.io/metro/docs/configuration
|
||||
*
|
||||
* @type {import('metro-config').MetroConfig}
|
||||
*/
|
||||
const config = {
|
||||
transformer: {
|
||||
babelTransformerPath: resolve(__dirname, 'transformer.js'),
|
||||
// hermesParser: true,
|
||||
},
|
||||
resolver: {
|
||||
sourceExts,
|
||||
resolveRequest: (context, moduleName, platform) => {
|
||||
if (NullModules.includes(moduleName)) {
|
||||
return {
|
||||
type: 'empty',
|
||||
};
|
||||
}
|
||||
return context.resolveRequest(context, moduleName, platform);
|
||||
},
|
||||
nodeModulesPaths: [resolve(process.cwd(), '..', 'node_modules')], // development模式下,oak的库是以文件方式链接,其自身的node_modules里可能会缺失一些库
|
||||
},
|
||||
watchFolders,
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
*
|
||||
* @format
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const traverse = require('@babel/traverse').default;
|
||||
const t = require('@babel/types');
|
||||
const path = require('path');
|
||||
const less = require('less');
|
||||
const css2rn = require("css-to-react-native-transform").default;
|
||||
const { parseSync, transformFromAstSync, transformSync: babelTransform } = require("@babel/core");
|
||||
const nullthrows = require("nullthrows");
|
||||
|
||||
const { injectGetRender } = require('../utils/injectGetRender');
|
||||
|
||||
async function renderToCSS({ src, filename, options = {} }) {
|
||||
const { lessOptions = {} } = options;
|
||||
const { css } = await less.render(src, { paths: [path.dirname(filename)], ...lessOptions });
|
||||
return css;
|
||||
}
|
||||
|
||||
function renderCSSToReactNative(css) {
|
||||
return css2rn(css, { parseMediaQueries: true });
|
||||
}
|
||||
|
||||
function transform({ filename, options, plugins, src }) {
|
||||
const OLD_BABEL_ENV = process.env.BABEL_ENV;
|
||||
process.env.BABEL_ENV = options.dev
|
||||
? "development"
|
||||
: process.env.BABEL_ENV || "production";
|
||||
try {
|
||||
const babelConfig = {
|
||||
caller: {
|
||||
name: "oak",
|
||||
bundler: "oak",
|
||||
platform: options.platform,
|
||||
},
|
||||
ast: true,
|
||||
babelrc: options.enableBabelRCLookup,
|
||||
code: false,
|
||||
cwd: options.projectRoot,
|
||||
highlightCode: true,
|
||||
filename,
|
||||
plugins,
|
||||
sourceType: "module",
|
||||
// NOTE(EvanBacon): We split the parse/transform steps up to accommodate
|
||||
// Hermes parsing, but this defaults to cloning the AST which increases
|
||||
// the transformation time by a fair amount.
|
||||
// You get this behavior by default when using Babel's `transform` method directly.
|
||||
cloneInputAst: false,
|
||||
};
|
||||
|
||||
const transInner = (src) => {
|
||||
const sourceAst = options.hermesParser
|
||||
? require("hermes-parser").parse(src, {
|
||||
babel: true,
|
||||
sourceType: babelConfig.sourceType,
|
||||
})
|
||||
: parseSync(src, babelConfig);
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// injectGetRender(transformResult.ast.program.body, path.resolve(process.cwd(), '..'), filename, 'native');
|
||||
return {
|
||||
ast: nullthrows(transformResult.ast),
|
||||
metadata: transformResult.metadata,
|
||||
};
|
||||
};
|
||||
|
||||
if (filename.endsWith('less')) {
|
||||
return renderToCSS({ src, filename, options }).then((css) => {
|
||||
const cssObject = renderCSSToReactNative(css);
|
||||
const newSrc = `module.exports = ${JSON.stringify(cssObject)}`;
|
||||
return transInner(newSrc);
|
||||
});
|
||||
}
|
||||
|
||||
return transInner(src);
|
||||
} finally {
|
||||
if (OLD_BABEL_ENV) {
|
||||
process.env.BABEL_ENV = OLD_BABEL_ENV;
|
||||
}
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
transform,
|
||||
};
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
const { relative, dirname, join } = require('path');
|
||||
const fs = require('fs');
|
||||
const t = require('@babel/types');
|
||||
const traverse = require('@babel/traverse').default;
|
||||
const assert = require('assert');
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} node
|
||||
* @param {*} projectRoot
|
||||
* @param {*} filename
|
||||
* @param {*} env 'web' | 'native'
|
||||
*/
|
||||
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();
|
||||
node.arguments.forEach((node4) => {
|
||||
if (t.isObjectExpression(node4)) {
|
||||
const propertyRender = t.objectProperty(
|
||||
t.identifier('getRender'),
|
||||
t.functionExpression(
|
||||
null,
|
||||
[],
|
||||
t.blockStatement(statements)
|
||||
)
|
||||
);
|
||||
node4.properties.unshift(propertyRender);
|
||||
}
|
||||
else {
|
||||
assert(false, `[${filename}]OakComponent调用参数不是ObjectExpression`);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
assert(env === 'native');
|
||||
/** native不用检测(react-native会自动检测render.native或render.ios/android),直接注入
|
||||
* OakComponent({
|
||||
* getRender() {
|
||||
* const oakRenderFn = require('./render').default;
|
||||
* return oakRenderFn;
|
||||
* },
|
||||
* })
|
||||
*/
|
||||
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')
|
||||
]
|
||||
),
|
||||
t.identifier('default')
|
||||
),
|
||||
)
|
||||
]),
|
||||
t.returnStatement(
|
||||
t.identifier('oakRenderFn')
|
||||
)
|
||||
]
|
||||
))
|
||||
);
|
||||
arg.properties.unshift(propertyRender);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
injectGetRender
|
||||
};
|
||||
42
lib/build.js
42
lib/build.js
|
|
@ -3,10 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||
const tslib_1 = require("tslib");
|
||||
const tip_style_1 = require("./tip-style");
|
||||
const cross_spawn_1 = tslib_1.__importDefault(require("cross-spawn"));
|
||||
const path_1 = require("path");
|
||||
const makeLocale_1 = tslib_1.__importDefault(require("./makeLocale"));
|
||||
const fs_1 = require("fs");
|
||||
async function build(cmd) {
|
||||
if (!cmd.target) {
|
||||
(0, tip_style_1.Error)(`${(0, tip_style_1.error)(`Please add --target web or --target mp or --target wechatMp to he command`)}`);
|
||||
(0, tip_style_1.Error)(`${(0, tip_style_1.error)(`Please add --target web or --target mp(wechatMp) or --target rn(native) to run the project in Web/WechatMp/ReactNative environment`)}`);
|
||||
return;
|
||||
}
|
||||
// 先makeLocale
|
||||
|
|
@ -19,7 +21,7 @@ async function build(cmd) {
|
|||
: ''} ${cmd.target !== 'web' && cmd.mode !== 'production'
|
||||
? `split:${!!cmd.split}`
|
||||
: ''}`)}`);
|
||||
if (cmd.target === 'mp' || cmd.target === 'wechatMp') {
|
||||
if (['mp', 'wechatMp'].includes(cmd.target)) {
|
||||
const result = cross_spawn_1.default.sync(`cross-env`, [
|
||||
`NODE_ENV=${cmd.mode}`,
|
||||
`NODE_TARGET=${cmd.target}`,
|
||||
|
|
@ -72,5 +74,41 @@ async function build(cmd) {
|
|||
(0, tip_style_1.Error)(`${(0, tip_style_1.error)(`执行失败`)}`);
|
||||
}
|
||||
}
|
||||
else if (['native', 'rn'].includes(cmd.target)) {
|
||||
const prjDir = process.cwd();
|
||||
const cwd = (0, path_1.resolve)(prjDir, cmd.subDir || 'native');
|
||||
(0, fs_1.copyFileSync)((0, path_1.resolve)(prjDir, 'package.json'), (0, path_1.resolve)(cwd, 'package.json'));
|
||||
// rn不支持注入NODE_ENVIRONMENT这样的环境变量,cross-env没有用
|
||||
/* const result = spawn.sync(
|
||||
'react-native',
|
||||
[
|
||||
'start',
|
||||
],
|
||||
{
|
||||
cwd,
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
}
|
||||
); */
|
||||
const result = cross_spawn_1.default.sync(`cross-env`, [
|
||||
`NODE_ENV=${cmd.mode}`,
|
||||
'OAK_PLATFORM=native',
|
||||
'react-native',
|
||||
'start'
|
||||
].filter(Boolean), {
|
||||
cwd,
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
});
|
||||
if (result.status === 0) {
|
||||
(0, tip_style_1.Success)(`${(0, tip_style_1.success)(`执行完成`)}`);
|
||||
}
|
||||
else {
|
||||
(0, tip_style_1.Error)(`${(0, tip_style_1.error)(`执行失败`)}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
(0, tip_style_1.Error)(`${(0, tip_style_1.error)(`target could only be web or mp(wechatMp) or rn(native)`)}`);
|
||||
}
|
||||
}
|
||||
exports.default = build;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ function enhanceErrorMessages(methodName, log) {
|
|||
this.outputHelp();
|
||||
console.log(` ` + (0, tip_style_1.error)(log(...args)));
|
||||
console.log();
|
||||
process.exit(1);
|
||||
process.exit(-1);
|
||||
};
|
||||
}
|
||||
const currentNodeVersion = process.versions.node;
|
||||
|
|
@ -38,7 +38,7 @@ if (Number(major) < minNodeVersion) {
|
|||
minNodeVersion +
|
||||
' or higher. \n' +
|
||||
'Please update your version of Node.');
|
||||
process.exit(1);
|
||||
process.exit(-1);
|
||||
}
|
||||
commander_1.default.version(config_1.CLI_VERSION, '-v, --version').usage('<command> [options]');
|
||||
commander_1.default
|
||||
|
|
@ -87,8 +87,8 @@ commander_1.default
|
|||
.action(create_1.update);
|
||||
commander_1.default
|
||||
.command('run')
|
||||
.option('-i, --initialize', 'true')
|
||||
.option('-m, --mode <mode>', 'mode')
|
||||
.option('-p, --platform <platform>', 'platform')
|
||||
.option('-d, --subDir <subDirName>', 'subDirName')
|
||||
.description(`run backend server by ${config_1.CLI_NAME}`)
|
||||
.action(run_1.default);
|
||||
// output help information on unknown commands
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ async function make() {
|
|||
}
|
||||
else {
|
||||
(0, tip_style_1.Error)(`${(0, tip_style_1.error)(`make 执行失败`)}`);
|
||||
process.exit(1);
|
||||
process.exit(-1);
|
||||
}
|
||||
}
|
||||
exports.default = make;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ async function make(cmd, watch) {
|
|||
}
|
||||
else {
|
||||
(0, tip_style_1.Error)(`${(0, tip_style_1.error)(`make 执行失败`)}`);
|
||||
process.exit(1);
|
||||
process.exit(-1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
46
lib/run.js
46
lib/run.js
|
|
@ -3,36 +3,46 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||
const tslib_1 = require("tslib");
|
||||
const tip_style_1 = require("./tip-style");
|
||||
const cross_spawn_1 = tslib_1.__importDefault(require("cross-spawn"));
|
||||
const path_1 = require("path");
|
||||
const fs_1 = require("fs");
|
||||
async function run(options) {
|
||||
if (options.initialize) {
|
||||
(0, tip_style_1.Success)(`${(0, tip_style_1.success)('初始化数据库中……')}`);
|
||||
// ts-node scripts/build-app-domain & npm link ./app-domain
|
||||
const drop = options.args.includes('drop') || false;
|
||||
const result = cross_spawn_1.default.sync('ts-node', [require.resolve('../scripts/' + 'initialize-server.ts'), `${drop}`], {
|
||||
const prjDir = process.cwd();
|
||||
const cwd = (0, path_1.resolve)(process.cwd(), options.subDir || 'native');
|
||||
if (options.platform === 'ios') {
|
||||
(0, fs_1.copyFileSync)((0, path_1.resolve)(prjDir, 'package.json'), (0, path_1.resolve)(cwd, 'package.json'));
|
||||
(0, tip_style_1.Success)(`${(0, tip_style_1.primary)('run react-native run-ios')}`);
|
||||
const result = cross_spawn_1.default.sync('react-native', ['run-ios'], {
|
||||
cwd,
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
});
|
||||
if (result.status === 0) {
|
||||
(0, tip_style_1.Success)(`${(0, tip_style_1.success)(`初始化数据库完成`)}`);
|
||||
(0, tip_style_1.Success)(`${(0, tip_style_1.success)(`react-native run-ios success`)}`);
|
||||
}
|
||||
else {
|
||||
Error(`${(0, tip_style_1.error)(`初始化数据库失败`)}`);
|
||||
process.exit(1);
|
||||
Error(`${(0, tip_style_1.error)('react-native run-ios fail')}`);
|
||||
process.exit(-1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
(0, tip_style_1.Success)(`${(0, tip_style_1.success)('启动服务器……')}`);
|
||||
console.log(options.mode);
|
||||
// ts-node scripts/build-app-domain & npm link ./app-domain
|
||||
const result = cross_spawn_1.default.sync(`cross-env`, [
|
||||
`NODE_ENV=${options.mode}`,
|
||||
'OAK_PLATFORM=server',
|
||||
'ts-node',
|
||||
require.resolve('../scripts/' + 'start-server.js'),
|
||||
], {
|
||||
else if (options.platform === 'android') {
|
||||
(0, tip_style_1.Success)(`${(0, tip_style_1.primary)('run react-native run-android')}`);
|
||||
(0, fs_1.copyFileSync)((0, path_1.resolve)(prjDir, 'package.json'), (0, path_1.resolve)(cwd, 'package.json'));
|
||||
const result = cross_spawn_1.default.sync('react-native', ['run-android'], {
|
||||
cwd,
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
});
|
||||
if (result.status === 0) {
|
||||
(0, tip_style_1.Success)(`${(0, tip_style_1.success)(`react-native run-android success`)}`);
|
||||
}
|
||||
else {
|
||||
Error(`${(0, tip_style_1.error)('react-native run-android fail')}`);
|
||||
process.exit(-1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Error((0, tip_style_1.error)(`unrecoganized platfrom: ${options.platform}`));
|
||||
process.exit(-1);
|
||||
}
|
||||
}
|
||||
exports.default = run;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
"@types/node": "^20.6.0",
|
||||
"@types/shelljs": "^0.8.8",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"babel-plugin-module-resolver": "^5.0.0",
|
||||
"fork-ts-checker-webpack-plugin": "^8.0.0",
|
||||
"node-watch": "^0.7.4",
|
||||
"querystring-es3": "^0.2.1",
|
||||
|
|
@ -68,6 +69,7 @@
|
|||
"css": "^3.0.0",
|
||||
"css-loader": "^6.5.1",
|
||||
"css-minimizer-webpack-plugin": "^3.2.0",
|
||||
"css-to-react-native-transform": "^2.0.0",
|
||||
"dotenv": "^10.0.0",
|
||||
"dotenv-expand": "^5.1.0",
|
||||
"dotenv-webpack": "^7.1.0",
|
||||
|
|
@ -106,6 +108,7 @@
|
|||
"prompts": "^2.4.2",
|
||||
"react-app-polyfill": "^3.0.0",
|
||||
"react-dev-utils": "^12.0.1",
|
||||
"react-native": "^0.72.7",
|
||||
"react-refresh": "^0.11.0",
|
||||
"required-path": "^1.0.1",
|
||||
"resolve": "^1.20.0",
|
||||
|
|
|
|||
49
src/build.ts
49
src/build.ts
|
|
@ -8,13 +8,15 @@ import {
|
|||
Warn,
|
||||
} from './tip-style';
|
||||
import spawn from 'cross-spawn';
|
||||
import { resolve } from 'path';
|
||||
import makeLocale from './makeLocale';
|
||||
import { copyFileSync } from 'fs';
|
||||
|
||||
export default async function build(cmd: any) {
|
||||
if (!cmd.target) {
|
||||
Error(
|
||||
`${error(
|
||||
`Please add --target web or --target mp or --target wechatMp to he command`
|
||||
`Please add --target web or --target mp(wechatMp) or --target rn(native) to run the project in Web/WechatMp/ReactNative environment`
|
||||
)}`
|
||||
);
|
||||
return;
|
||||
|
|
@ -37,7 +39,7 @@ export default async function build(cmd: any) {
|
|||
}`
|
||||
)}`
|
||||
);
|
||||
if (cmd.target === 'mp' || cmd.target === 'wechatMp') {
|
||||
if (['mp', 'wechatMp'].includes(cmd.target)) {
|
||||
const result = spawn.sync(
|
||||
`cross-env`,
|
||||
[
|
||||
|
|
@ -103,4 +105,47 @@ export default async function build(cmd: any) {
|
|||
Error(`${error(`执行失败`)}`);
|
||||
}
|
||||
}
|
||||
else if (['native', 'rn'].includes(cmd.target)) {
|
||||
const prjDir = process.cwd();
|
||||
const cwd = resolve(prjDir, cmd.subDir || 'native');
|
||||
copyFileSync(resolve(prjDir, 'package.json'), resolve(cwd, 'package.json'));
|
||||
// rn不支持注入NODE_ENVIRONMENT这样的环境变量,cross-env没有用
|
||||
/* const result = spawn.sync(
|
||||
'react-native',
|
||||
[
|
||||
'start',
|
||||
],
|
||||
{
|
||||
cwd,
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
}
|
||||
); */
|
||||
const result = spawn.sync(
|
||||
`cross-env`,
|
||||
[
|
||||
`NODE_ENV=${cmd.mode}`,
|
||||
'OAK_PLATFORM=native',
|
||||
'react-native',
|
||||
'start'
|
||||
].filter(Boolean),
|
||||
{
|
||||
cwd,
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
}
|
||||
);
|
||||
if (result.status === 0) {
|
||||
Success(`${success(`执行完成`)}`);
|
||||
} else {
|
||||
Error(`${error(`执行失败`)}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Error(
|
||||
`${error(
|
||||
`target could only be web or mp(wechatMp) or rn(native)`
|
||||
)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ function enhanceErrorMessages(methodName: string, log: Function) {
|
|||
this.outputHelp();
|
||||
console.log(` ` + error(log(...args)));
|
||||
console.log();
|
||||
process.exit(1);
|
||||
process.exit(-1);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ if (Number(major) < minNodeVersion) {
|
|||
' or higher. \n' +
|
||||
'Please update your version of Node.'
|
||||
);
|
||||
process.exit(1);
|
||||
process.exit(-1);
|
||||
}
|
||||
|
||||
program.version(CLI_VERSION, '-v, --version').usage('<command> [options]');
|
||||
|
|
@ -93,10 +93,11 @@ program
|
|||
.action(update);
|
||||
program
|
||||
.command('run')
|
||||
.option('-i, --initialize', 'true')
|
||||
.option('-m, --mode <mode>', 'mode')
|
||||
.option('-p, --platform <platform>', 'platform')
|
||||
.option('-d, --subDir <subDirName>', 'subDirName')
|
||||
.description(`run backend server by ${CLI_NAME}`)
|
||||
.action(run);
|
||||
|
||||
// output help information on unknown commands
|
||||
program.arguments('<command>').action((cmd) => {
|
||||
program.outputHelp();
|
||||
|
|
|
|||
|
|
@ -26,6 +26,6 @@ export default async function make() {
|
|||
Success(`${success(`make 执行完成`)}`);
|
||||
} else {
|
||||
Error(`${error(`make 执行失败`)}`);
|
||||
process.exit(1);
|
||||
process.exit(-1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ export default async function make(cmd: any, watch?: boolean) {
|
|||
Success(`${success(`make 执行完成`)}`);
|
||||
} else {
|
||||
Error(`${error(`make 执行失败`)}`);
|
||||
process.exit(1);
|
||||
process.exit(-1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
64
src/run.ts
64
src/run.ts
|
|
@ -7,44 +7,54 @@ import {
|
|||
Warn,
|
||||
} from './tip-style';
|
||||
import spawn from 'cross-spawn';
|
||||
import { resolve } from 'path';
|
||||
import { copyFileSync, unlinkSync } from 'fs';
|
||||
|
||||
export default async function run(options: any): Promise<void> {
|
||||
if (options.initialize) {
|
||||
Success(`${success('初始化数据库中……')}`);
|
||||
// ts-node scripts/build-app-domain & npm link ./app-domain
|
||||
const drop = options.args.includes('drop') || false;
|
||||
export default async function run(options: any): Promise<void> {
|
||||
const prjDir = process.cwd();
|
||||
const cwd = resolve(process.cwd(), options.subDir || 'native');
|
||||
if (options.platform === 'ios') {
|
||||
copyFileSync(resolve(prjDir, 'package.json'), resolve(cwd, 'package.json'));
|
||||
Success(`${primary('run react-native run-ios')}`);
|
||||
const result = spawn.sync(
|
||||
'ts-node',
|
||||
[require.resolve('../scripts/' + 'initialize-server.ts'), `${drop}`],
|
||||
'react-native',
|
||||
['run-ios'],
|
||||
{
|
||||
cwd,
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
if (result.status === 0) {
|
||||
Success(`${success(`初始化数据库完成`)}`);
|
||||
Success(`${success(`react-native run-ios success`)}`);
|
||||
} else {
|
||||
Error(`${error(`初始化数据库失败`)}`);
|
||||
process.exit(1);
|
||||
Error(`${error('react-native run-ios fail')}`);
|
||||
process.exit(-1);
|
||||
}
|
||||
}
|
||||
else if (options.platform === 'android') {
|
||||
Success(`${primary('run react-native run-android')}`);
|
||||
copyFileSync(resolve(prjDir, 'package.json'), resolve(cwd, 'package.json'));
|
||||
const result = spawn.sync(
|
||||
'react-native',
|
||||
['run-android'],
|
||||
{
|
||||
cwd,
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
}
|
||||
);
|
||||
|
||||
if (result.status === 0) {
|
||||
Success(`${success(`react-native run-android success`)}`);
|
||||
} else {
|
||||
Error(`${error('react-native run-android fail')}`);
|
||||
process.exit(-1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Success(`${success('启动服务器……')}`);
|
||||
console.log(options.mode);
|
||||
// ts-node scripts/build-app-domain & npm link ./app-domain
|
||||
const result = spawn.sync(
|
||||
`cross-env`,
|
||||
[
|
||||
`NODE_ENV=${options.mode}`,
|
||||
'OAK_PLATFORM=server',
|
||||
'ts-node',
|
||||
require.resolve('../scripts/' + 'start-server.js'),
|
||||
],
|
||||
{
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
}
|
||||
);
|
||||
Error(error(`unrecoganized platfrom: ${options.platform}`));
|
||||
process.exit(-1);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue