Skip to content

Commit 6bc0236

Browse files
authored
Merge pull request #73 from saseungmin/feat/expo-support-for-code-push
feat(cli): add expo framework support to bundle command
2 parents 932410b + 22acced commit 6bc0236

File tree

6 files changed

+99
-13
lines changed

6 files changed

+99
-13
lines changed

README.md

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ Create a new release history for a specific binary app version.
330330
**Example:**
331331
- Create a new release history for the binary app version `1.0.0`.
332332

333-
```
333+
```bash
334334
npx code-push create-history --binary-version 1.0.0 --platform ios --identifier staging
335335
```
336336

@@ -342,7 +342,7 @@ Display the release history for a specific binary app version.
342342
**Example:**
343343
- Show the release history for the binary app version `1.0.0`.
344344

345-
```
345+
```bash
346346
npx code-push show-history --binary-version 1.0.0 --platform ios --identifier staging
347347
```
348348

@@ -354,11 +354,15 @@ Release a CodePush update for a specific binary app version.
354354
**Example:**
355355
- Release a CodePush update `1.0.1` targeting the binary app version `1.0.0`.
356356

357-
```
357+
```bash
358358
npx code-push release --binary-version 1.0.0 --app-version 1.0.1 \
359359
--platform ios --identifier staging --entry-file index.js \
360360
--mandatory true
361+
362+
# Expo project
363+
npx code-push release --framework expo --binary-version 1.0.0 --app-version 1.0.1 --platform ios
361364
```
365+
- `--framework`(`-f`) : Framework type (expo)
362366
- `--binary-version`: The version of the binary app that the CodePush update is targeting.
363367
- `--app-version`: The version of the CodePush update itself.
364368

@@ -375,7 +379,7 @@ Update the release history for a specific CodePush update.
375379
**Example:**
376380
- Rollback the CodePush update `1.0.1` (targeting the binary app version `1.0.0`).
377381

378-
```
382+
```bash
379383
npx code-push update-history --binary-version 1.0.0 --app-version 1.0.1 \
380384
--platform ios --identifier staging \
381385
--enable false
@@ -386,10 +390,17 @@ npx code-push update-history --binary-version 1.0.0 --app-version 1.0.1 \
386390
Create a CodePush bundle file.
387391

388392
**Example:**
389-
```
393+
```bash
390394
npx code-push bundle --platform android --entry-file index.js
395+
396+
# Expo project
397+
npx code-push bundle --framework expo --platform android --entry-file index.js
391398
```
399+
- `--framework`(`-f`): Framework type (expo)
392400

393401
By default, the bundle file is created in the `/build/bundleOutput` directory.
394402

403+
> [!NOTE]
404+
> For Expo projects, the CLI uses `expo export:embed` command for bundling instead of React Native's bundle command.
405+
395406
(The file name represents a hash value of the bundle content.)

cli/commands/bundleCommand/bundleCodePush.js

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
const fs = require('fs');
22
const { prepareToBundleJS } = require('../../functions/prepareToBundleJS');
33
const { runReactNativeBundleCommand } = require('../../functions/runReactNativeBundleCommand');
4+
const { runExpoBundleCommand } = require('../../functions/runExpoBundleCommand');
45
const { getReactTempDir } = require('../../functions/getReactTempDir');
56
const { runHermesEmitBinaryCommand } = require('../../functions/runHermesEmitBinaryCommand');
67
const { makeCodePushBundle } = require('../../functions/makeCodePushBundle');
78
const { ROOT_OUTPUT_DIR, ENTRY_FILE } = require('../../constant');
89

910
/**
11+
* @param framework {string|undefined} 'expo'
1012
* @param platform {string} 'ios' | 'android'
1113
* @param outputRootPath {string}
1214
* @param entryFile {string}
@@ -15,6 +17,7 @@ const { ROOT_OUTPUT_DIR, ENTRY_FILE } = require('../../constant');
1517
* @return {Promise<string>} CodePush bundle file name (equals to packageHash)
1618
*/
1719
async function bundleCodePush(
20+
framework,
1821
platform = 'ios',
1922
outputRootPath = ROOT_OUTPUT_DIR,
2023
entryFile = ENTRY_FILE,
@@ -32,13 +35,24 @@ async function bundleCodePush(
3235

3336
prepareToBundleJS({ deleteDirs: [outputRootPath, getReactTempDir()], makeDir: OUTPUT_CONTENT_PATH });
3437

35-
runReactNativeBundleCommand(
36-
_jsBundleName,
37-
OUTPUT_CONTENT_PATH,
38-
platform,
39-
SOURCEMAP_OUTPUT,
40-
entryFile,
41-
);
38+
if (framework === 'expo') {
39+
runExpoBundleCommand(
40+
_jsBundleName,
41+
OUTPUT_CONTENT_PATH,
42+
platform,
43+
SOURCEMAP_OUTPUT,
44+
entryFile,
45+
);
46+
} else {
47+
runReactNativeBundleCommand(
48+
_jsBundleName,
49+
OUTPUT_CONTENT_PATH,
50+
platform,
51+
SOURCEMAP_OUTPUT,
52+
entryFile,
53+
);
54+
}
55+
4256
console.log('log: JS bundling complete');
4357

4458
await runHermesEmitBinaryCommand(

cli/commands/bundleCommand/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ const { OUTPUT_BUNDLE_DIR, ROOT_OUTPUT_DIR, ENTRY_FILE } = require('../../consta
44

55
program.command('bundle')
66
.description('Creates a CodePush bundle file (assumes Hermes is enabled).')
7+
.addOption(new Option('-f, --framework <type>', 'framework type (expo)').choices(['expo']))
78
.addOption(new Option('-p, --platform <type>', 'platform').choices(['ios', 'android']).default('ios'))
89
.option('-o, --output-path <string>', 'path to output root directory', ROOT_OUTPUT_DIR)
910
.option('-e, --entry-file <string>', 'path to JS/TS entry file', ENTRY_FILE)
1011
.option('-b, --bundle-name <string>', 'bundle file name (default-ios: "main.jsbundle" / default-android: "index.android.bundle")')
1112
.option('--output-bundle-dir <string>', 'name of directory containing the bundle file created by the "bundle" command', OUTPUT_BUNDLE_DIR)
1213
/**
1314
* @param {Object} options
15+
* @param {string} options.framework
1416
* @param {string} options.platform
1517
* @param {string} options.outputPath
1618
* @param {string} options.entryFile
@@ -20,6 +22,7 @@ program.command('bundle')
2022
*/
2123
.action((options) => {
2224
bundleCodePush(
25+
options.framework,
2326
options.platform,
2427
options.outputPath,
2528
options.entryFile,

cli/commands/releaseCommand/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ program.command('release')
77
.description('Deploys a new CodePush update for a target binary app.\nAfter creating the CodePush bundle, it uploads the file and updates the ReleaseHistory information.\n`bundleUploader`, `getReleaseHistory`, and `setReleaseHistory` functions should be implemented in the config file.')
88
.requiredOption('-b, --binary-version <string>', '(Required) The target binary version')
99
.requiredOption('-v, --app-version <string>', '(Required) The app version to be released. It must be greater than the binary version.')
10+
.addOption(new Option('-f, --framework <type>', 'framework type (expo)').choices(['expo']))
1011
.addOption(new Option('-p, --platform <type>', 'platform').choices(['ios', 'android']).default('ios'))
1112
.option('-i, --identifier <string>', 'reserved characters to distinguish the release.')
1213
.option('-c, --config <path>', 'set config file name (JS/TS)', CONFIG_FILE_NAME)
@@ -22,6 +23,7 @@ program.command('release')
2223
* @param {Object} options
2324
* @param {string} options.binaryVersion
2425
* @param {string} options.appVersion
26+
* @param {string} options.framework
2527
* @param {string} options.platform
2628
* @param {string} options.identifier
2729
* @param {string} options.config
@@ -44,6 +46,7 @@ program.command('release')
4446
config.setReleaseHistory,
4547
options.binaryVersion,
4648
options.appVersion,
49+
options.framework,
4750
options.platform,
4851
options.identifier,
4952
options.outputPath,

cli/commands/releaseCommand/release.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const { addToReleaseHistory } = require("./addToReleaseHistory");
2525
* ): Promise<void>}
2626
* @param binaryVersion {string}
2727
* @param appVersion {string}
28+
* @param framework {string|undefined} 'expo'
2829
* @param platform {"ios" | "android"}
2930
* @param identifier {string?}
3031
* @param outputPath {string}
@@ -43,6 +44,7 @@ async function release(
4344
setReleaseHistory,
4445
binaryVersion,
4546
appVersion,
47+
framework,
4648
platform,
4749
identifier,
4850
outputPath,
@@ -56,7 +58,7 @@ async function release(
5658
) {
5759
const bundleFileName = skipBundle
5860
? readBundleFileNameFrom(bundleDirectory)
59-
: await bundleCodePush(platform, outputPath, entryFile, jsBundleName, bundleDirectory);
61+
: await bundleCodePush(framework, platform, outputPath, entryFile, jsBundleName, bundleDirectory);
6062
const bundleFilePath = `${bundleDirectory}/${bundleFileName}`;
6163

6264
const downloadUrl = await (async () => {
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
const path = require('path');
2+
const shell = require('shelljs');
3+
4+
/**
5+
* Run `expo bundle` CLI command
6+
*
7+
* @param bundleName {string} JS bundle file name
8+
* @param entryFile {string} App code entry file name (default: index.ts)
9+
* @param outputPath {string} Path to output JS bundle file and assets
10+
* @param platform {string} Platform (ios | android)
11+
* @param sourcemapOutput {string} Path to output sourcemap file (Warning: if sourcemapOutput points to the outputPath, the sourcemap will be included in the CodePush bundle and increase the deployment size)
12+
* @return {void}
13+
*/
14+
function runExpoBundleCommand(
15+
bundleName,
16+
outputPath,
17+
platform,
18+
sourcemapOutput,
19+
entryFile,
20+
) {
21+
/**
22+
* @return {string}
23+
*/
24+
function getCliPath() {
25+
return path.join('node_modules', '.bin', 'expo');
26+
}
27+
28+
/**
29+
* @type {string[]}
30+
*/
31+
const expoBundleArgs = [
32+
'export:embed',
33+
'--assets-dest',
34+
outputPath,
35+
'--bundle-output',
36+
path.join(outputPath, bundleName),
37+
'--dev',
38+
'false',
39+
'--entry-file',
40+
entryFile,
41+
'--platform',
42+
platform,
43+
'--sourcemap-output',
44+
sourcemapOutput,
45+
'--reset-cache',
46+
];
47+
48+
console.log('Running "expo export:embed" command:\n');
49+
50+
shell.exec(`${getCliPath()} ${expoBundleArgs.join(' ')}`);
51+
}
52+
53+
module.exports = { runExpoBundleCommand };

0 commit comments

Comments
 (0)