mirror of
https://gitcode.com/github-mirrors/react-native-update-cli.git
synced 2025-09-16 09:41:38 +08:00
support taro
This commit is contained in:
9
cli.json
9
cli.json
@@ -145,6 +145,15 @@
|
|||||||
},
|
},
|
||||||
"sourcemap": {
|
"sourcemap": {
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"taro": {
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"expo": {
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"rncli": {
|
||||||
|
"default": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
285
src/bundle.ts
285
src/bundle.ts
@@ -22,16 +22,29 @@ try {
|
|||||||
hdiff = require('node-hdiffpatch').diff;
|
hdiff = require('node-hdiffpatch').diff;
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|
||||||
|
async function runReactNativeBundleCommand({
|
||||||
async function runReactNativeBundleCommand(
|
bundleName,
|
||||||
bundleName: string,
|
dev,
|
||||||
development: string,
|
entryFile,
|
||||||
entryFile: string,
|
outputFolder,
|
||||||
outputFolder: string,
|
platform,
|
||||||
platform: string,
|
sourcemapOutput,
|
||||||
sourcemapOutput: string,
|
config,
|
||||||
config: string,
|
cli,
|
||||||
) {
|
}: {
|
||||||
|
bundleName: string;
|
||||||
|
dev: string;
|
||||||
|
entryFile: string;
|
||||||
|
outputFolder: string;
|
||||||
|
platform: string;
|
||||||
|
sourcemapOutput: string;
|
||||||
|
config?: string;
|
||||||
|
cli: {
|
||||||
|
taro?: boolean;
|
||||||
|
expo?: boolean;
|
||||||
|
rncli?: boolean;
|
||||||
|
};
|
||||||
|
}) {
|
||||||
let gradleConfig: {
|
let gradleConfig: {
|
||||||
crunchPngs?: boolean;
|
crunchPngs?: boolean;
|
||||||
enableHermes?: boolean;
|
enableHermes?: boolean;
|
||||||
@@ -58,26 +71,31 @@ async function runReactNativeBundleCommand(
|
|||||||
|
|
||||||
fs.emptyDirSync(outputFolder);
|
fs.emptyDirSync(outputFolder);
|
||||||
|
|
||||||
let cliPath;
|
let cliPath: string | undefined;
|
||||||
|
|
||||||
let usingExpo = false;
|
let usingExpo = false;
|
||||||
try {
|
|
||||||
cliPath = require.resolve('@expo/cli', {
|
const getExpoCli = () => {
|
||||||
paths: [process.cwd()],
|
try {
|
||||||
});
|
cliPath = require.resolve('@expo/cli', {
|
||||||
const expoCliVersion = JSON.parse(
|
paths: [process.cwd()],
|
||||||
fs.readFileSync(
|
});
|
||||||
require.resolve('@expo/cli/package.json', {
|
const expoCliVersion = JSON.parse(
|
||||||
paths: [process.cwd()],
|
fs.readFileSync(
|
||||||
}),
|
require.resolve('@expo/cli/package.json', {
|
||||||
),
|
paths: [process.cwd()],
|
||||||
).version;
|
}),
|
||||||
// expo cli 0.10.17 (expo 49) 开始支持 bundle:embed
|
),
|
||||||
if (semverSatisfies(expoCliVersion, '>= 0.10.17')) {
|
).version;
|
||||||
usingExpo = true;
|
// expo cli 0.10.17 (expo 49) 开始支持 bundle:embed
|
||||||
}
|
if (semverSatisfies(expoCliVersion, '>= 0.10.17')) {
|
||||||
} catch (e) {}
|
usingExpo = true;
|
||||||
if (!usingExpo) {
|
} else {
|
||||||
|
cliPath = undefined;
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getRnCli = () => {
|
||||||
try {
|
try {
|
||||||
// rn >= 0.75
|
// rn >= 0.75
|
||||||
cliPath = require.resolve('@react-native-community/cli/build/bin.js', {
|
cliPath = require.resolve('@react-native-community/cli/build/bin.js', {
|
||||||
@@ -89,20 +107,49 @@ async function runReactNativeBundleCommand(
|
|||||||
paths: [process.cwd()],
|
paths: [process.cwd()],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getTaroCli = () => {
|
||||||
|
try {
|
||||||
|
cliPath = require.resolve('@tarojs/cli/bin/taro.js', {
|
||||||
|
paths: [process.cwd()],
|
||||||
|
});
|
||||||
|
} catch (e) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (cli.expo) {
|
||||||
|
getExpoCli();
|
||||||
|
} else if (cli.taro) {
|
||||||
|
getTaroCli();
|
||||||
|
} else if (cli.rncli) {
|
||||||
|
getRnCli();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!cliPath) {
|
||||||
|
getExpoCli();
|
||||||
|
if (!usingExpo) {
|
||||||
|
getRnCli();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const bundleParams = await checkPlugins();
|
const bundleParams = await checkPlugins();
|
||||||
const isSentry = bundleParams.sentry;
|
const isSentry = bundleParams.sentry;
|
||||||
const bundleCommand = usingExpo
|
|
||||||
? 'export:embed'
|
let bundleCommand = 'bundle';
|
||||||
: platform === 'harmony'
|
if (usingExpo) {
|
||||||
? 'bundle-harmony'
|
bundleCommand = 'export:embed';
|
||||||
: 'bundle';
|
} else if (platform === 'harmony') {
|
||||||
|
bundleCommand = 'bundle-harmony';
|
||||||
|
} else if (cli.taro) {
|
||||||
|
bundleCommand = 'build';
|
||||||
|
}
|
||||||
|
|
||||||
if (platform === 'harmony') {
|
if (platform === 'harmony') {
|
||||||
Array.prototype.push.apply(reactNativeBundleArgs, [
|
Array.prototype.push.apply(reactNativeBundleArgs, [
|
||||||
cliPath,
|
cliPath,
|
||||||
bundleCommand,
|
bundleCommand,
|
||||||
'--dev',
|
'--dev',
|
||||||
development,
|
dev,
|
||||||
'--entry-file',
|
'--entry-file',
|
||||||
entryFile,
|
entryFile,
|
||||||
]);
|
]);
|
||||||
@@ -122,14 +169,24 @@ async function runReactNativeBundleCommand(
|
|||||||
outputFolder,
|
outputFolder,
|
||||||
'--bundle-output',
|
'--bundle-output',
|
||||||
path.join(outputFolder, bundleName),
|
path.join(outputFolder, bundleName),
|
||||||
'--dev',
|
|
||||||
development,
|
|
||||||
'--entry-file',
|
|
||||||
entryFile,
|
|
||||||
'--platform',
|
'--platform',
|
||||||
platform,
|
platform,
|
||||||
'--reset-cache',
|
'--reset-cache',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (cli.taro) {
|
||||||
|
reactNativeBundleArgs.push(...[
|
||||||
|
'--type',
|
||||||
|
'rn',
|
||||||
|
])
|
||||||
|
} else {
|
||||||
|
reactNativeBundleArgs.push(...[
|
||||||
|
'--dev',
|
||||||
|
dev,
|
||||||
|
'--entry-file',
|
||||||
|
entryFile,
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
if (sourcemapOutput) {
|
if (sourcemapOutput) {
|
||||||
reactNativeBundleArgs.push('--sourcemap-output', sourcemapOutput);
|
reactNativeBundleArgs.push('--sourcemap-output', sourcemapOutput);
|
||||||
@@ -165,7 +222,9 @@ async function runReactNativeBundleCommand(
|
|||||||
let hermesEnabled: boolean | undefined = false;
|
let hermesEnabled: boolean | undefined = false;
|
||||||
|
|
||||||
if (platform === 'android') {
|
if (platform === 'android') {
|
||||||
const gradlePropeties = await new Promise<{ hermesEnabled?: boolean }>((resolve) => {
|
const gradlePropeties = await new Promise<{
|
||||||
|
hermesEnabled?: boolean;
|
||||||
|
}>((resolve) => {
|
||||||
properties.parse(
|
properties.parse(
|
||||||
'./android/gradle.properties',
|
'./android/gradle.properties',
|
||||||
{ path: true },
|
{ path: true },
|
||||||
@@ -322,7 +381,11 @@ async function compileHermesByteCode(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function copyDebugidForSentry(bundleName: string, outputFolder: string, sourcemapOutput: string) {
|
async function copyDebugidForSentry(
|
||||||
|
bundleName: string,
|
||||||
|
outputFolder: string,
|
||||||
|
sourcemapOutput: string,
|
||||||
|
) {
|
||||||
if (sourcemapOutput) {
|
if (sourcemapOutput) {
|
||||||
let copyDebugidPath;
|
let copyDebugidPath;
|
||||||
try {
|
try {
|
||||||
@@ -423,7 +486,10 @@ async function pack(dir: string, output: string) {
|
|||||||
}
|
}
|
||||||
const childs = fs.readdirSync(root);
|
const childs = fs.readdirSync(root);
|
||||||
for (const name of childs) {
|
for (const name of childs) {
|
||||||
if (ignorePackingFileNames.includes(name) || ignorePackingExtensions.some(ext => name.endsWith(`.${ext}`))) {
|
if (
|
||||||
|
ignorePackingFileNames.includes(name) ||
|
||||||
|
ignorePackingExtensions.some((ext) => name.endsWith(`.${ext}`))
|
||||||
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const fullPath = path.join(root, name);
|
const fullPath = path.join(root, name);
|
||||||
@@ -723,55 +789,66 @@ async function diffFromPackage(
|
|||||||
await writePromise;
|
await writePromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function enumZipEntries(zipFn: string, callback: (entry: any, zipFile: any) => void, nestedPath = '') {
|
export async function enumZipEntries(
|
||||||
|
zipFn: string,
|
||||||
|
callback: (entry: any, zipFile: any) => void,
|
||||||
|
nestedPath = '',
|
||||||
|
) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
openZipFile(zipFn, { lazyEntries: true }, async (err: any, zipfile: ZipFile) => {
|
openZipFile(
|
||||||
if (err) {
|
zipFn,
|
||||||
return reject(err);
|
{ lazyEntries: true },
|
||||||
}
|
async (err: any, zipfile: ZipFile) => {
|
||||||
|
if (err) {
|
||||||
zipfile.on('end', resolve);
|
return reject(err);
|
||||||
zipfile.on('error', reject);
|
|
||||||
zipfile.on('entry', async (entry) => {
|
|
||||||
const fullPath = nestedPath + entry.fileName;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (
|
|
||||||
!entry.fileName.endsWith('/') &&
|
|
||||||
entry.fileName.toLowerCase().endsWith('.hap')
|
|
||||||
) {
|
|
||||||
const tempDir = path.join(os.tmpdir(), `nested_zip_${Date.now()}`);
|
|
||||||
await fs.ensureDir(tempDir);
|
|
||||||
const tempZipPath = path.join(tempDir, 'temp.zip');
|
|
||||||
|
|
||||||
await new Promise((res, rej) => {
|
|
||||||
zipfile.openReadStream(entry, async (err, readStream) => {
|
|
||||||
if (err) return rej(err);
|
|
||||||
const writeStream = fs.createWriteStream(tempZipPath);
|
|
||||||
readStream.pipe(writeStream);
|
|
||||||
writeStream.on('finish', res);
|
|
||||||
writeStream.on('error', rej);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
await enumZipEntries(tempZipPath, callback, `${fullPath}/`);
|
|
||||||
|
|
||||||
await fs.remove(tempDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = callback(entry, zipfile, fullPath);
|
|
||||||
if (result && typeof result.then === 'function') {
|
|
||||||
await result;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('处理文件时出错:', error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
zipfile.readEntry();
|
zipfile.on('end', resolve);
|
||||||
});
|
zipfile.on('error', reject);
|
||||||
|
zipfile.on('entry', async (entry) => {
|
||||||
|
const fullPath = nestedPath + entry.fileName;
|
||||||
|
|
||||||
zipfile.readEntry();
|
try {
|
||||||
});
|
if (
|
||||||
|
!entry.fileName.endsWith('/') &&
|
||||||
|
entry.fileName.toLowerCase().endsWith('.hap')
|
||||||
|
) {
|
||||||
|
const tempDir = path.join(
|
||||||
|
os.tmpdir(),
|
||||||
|
`nested_zip_${Date.now()}`,
|
||||||
|
);
|
||||||
|
await fs.ensureDir(tempDir);
|
||||||
|
const tempZipPath = path.join(tempDir, 'temp.zip');
|
||||||
|
|
||||||
|
await new Promise((res, rej) => {
|
||||||
|
zipfile.openReadStream(entry, async (err, readStream) => {
|
||||||
|
if (err) return rej(err);
|
||||||
|
const writeStream = fs.createWriteStream(tempZipPath);
|
||||||
|
readStream.pipe(writeStream);
|
||||||
|
writeStream.on('finish', res);
|
||||||
|
writeStream.on('error', rej);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
await enumZipEntries(tempZipPath, callback, `${fullPath}/`);
|
||||||
|
|
||||||
|
await fs.remove(tempDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = callback(entry, zipfile, fullPath);
|
||||||
|
if (result && typeof result.then === 'function') {
|
||||||
|
await result;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('处理文件时出错:', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
zipfile.readEntry();
|
||||||
|
});
|
||||||
|
|
||||||
|
zipfile.readEntry();
|
||||||
|
},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -817,11 +894,20 @@ export const commands = {
|
|||||||
options.platform || (await question('平台(ios/android/harmony):')),
|
options.platform || (await question('平台(ios/android/harmony):')),
|
||||||
);
|
);
|
||||||
|
|
||||||
const { bundleName, entryFile, intermediaDir, output, dev, sourcemap } =
|
const {
|
||||||
translateOptions({
|
bundleName,
|
||||||
...options,
|
entryFile,
|
||||||
platform,
|
intermediaDir,
|
||||||
});
|
output,
|
||||||
|
dev,
|
||||||
|
sourcemap,
|
||||||
|
taro,
|
||||||
|
expo,
|
||||||
|
rncli,
|
||||||
|
} = translateOptions({
|
||||||
|
...options,
|
||||||
|
platform,
|
||||||
|
});
|
||||||
|
|
||||||
const bundleParams = await checkPlugins();
|
const bundleParams = await checkPlugins();
|
||||||
const sourcemapPlugin = bundleParams.sourcemap;
|
const sourcemapPlugin = bundleParams.sourcemap;
|
||||||
@@ -839,20 +925,25 @@ export const commands = {
|
|||||||
|
|
||||||
console.log(`Bundling with react-native: ${version}`);
|
console.log(`Bundling with react-native: ${version}`);
|
||||||
|
|
||||||
await runReactNativeBundleCommand(
|
await runReactNativeBundleCommand({
|
||||||
bundleName,
|
bundleName,
|
||||||
dev,
|
dev,
|
||||||
entryFile,
|
entryFile,
|
||||||
intermediaDir,
|
outputFolder: intermediaDir,
|
||||||
platform,
|
platform,
|
||||||
sourcemap || sourcemapPlugin ? sourcemapOutput : '',
|
sourcemapOutput: sourcemap || sourcemapPlugin ? sourcemapOutput : '',
|
||||||
);
|
cli: {
|
||||||
|
taro,
|
||||||
|
expo,
|
||||||
|
rncli,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
await pack(path.resolve(intermediaDir), realOutput);
|
await pack(path.resolve(intermediaDir), realOutput);
|
||||||
|
|
||||||
const v = await question('是否现在上传此热更包?(Y/N)');
|
const v = await question('是否现在上传此热更包?(Y/N)');
|
||||||
if (v.toLowerCase() === 'y') {
|
if (v.toLowerCase() === 'y') {
|
||||||
const versionName = await this.publish({
|
const versionName = await this.publish({
|
||||||
args: [realOutput],
|
args: [realOutput],
|
||||||
options: {
|
options: {
|
||||||
platform,
|
platform,
|
||||||
|
Reference in New Issue
Block a user