npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@remobile/react-native-update

v1.1.6

Published

Update js version and app version for ios and android

Downloads

10

Readme

React Native Update (remobile)

Update js version and app version for ios and android

Installation

npm install @remobile/react-native-update --save

Installation (iOS)

  • Drag RCTUpdate.xcodeproj to your project on Xcode.
  • Click on your main project file (the one that represents the .xcodeproj) select Build Phases and drag libRCTUpdate.a from the Products folder inside the RCTUpdate.xcodeproj.
  • Look for Header Search Paths and make sure it contains both $(SRCROOT)/../../../react-native/React as recursive.

Installation (Android)

...
include ':react-native-update'
project(':react-native-update').projectDir = new File(settingsDir, '../node_modules/@remobile/react-native-update/android')
  • In android/app/build.gradle
...
dependencies {
    ...
    compile project(':react-native-update')
}
  • register module (in MainActivity.java)
......
import com.remobile.update.RCTUpdateMgr;  // <--- import

......
public class MainApplication extends Application implements ReactApplication {
    private RCTUpdateMgr mUpdateMgr; // <------ add here

    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
        ......
        @Override
        protected String getJSBundleFile() {
            return mUpdateMgr.getBundleUrl();   // <------ change here
        }

        @Override
        protected List<ReactPackage> getPackages() {
            mUpdateMgr = new RCTUpdateMgr(MainActivity.activity);

            return Arrays.<ReactPackage>asList(
            ......
            mUpdateMgr.getReactPackage(),       // <------ add here
            ......
            );
        }
    };
    ......
}

Usage

Example

UpdatePage.js

'use strict';
var React = require('react');
var ReactNative = require('react-native');
var {
    StyleSheet,
    View,
    Text,
    Image,
} = ReactNative;

var Update = require('@remobile/react-native-update');

var
STATUS_GET_VERSION = 0,
STATUS_HAS_VEW_VERSION = 1,
STATUS_HAS_NOT_VEW_VERSION = 2,
STATUS_DOWNLOAD_APK_PROGESS = 3,
STATUS_DOWNLOAD_JS_PROGESS = 4,
STATUS_UNZIP_JS_PROGESS = 5,
STATUS_GET_VERSION_ERROR = 6,
STATUS_DOWNKOAD_APK_ERROR = 7,
STATUS_DOWNKOAD_JS_ERROR = 8,
STATUS_UNZIP_JS_ERROR = 9,
STATUS_FAILED_INSTALL_ERROR = 10,
STATUS_UPDATE_END = 11;

var
ERROR_NULL = 0,
ERROR_DOWNKOAD_APK = 1,
ERROR_DOWNKOAD_JS = 2,
ERROR_FAILED_INSTALL = 3,
ERROR_UNZIP_JS = 4;

var PROGRESS_WIDTH = sr.tw*0.7;
var {Button, ProgressBar} = COMPONENTS;

var ProgressInfo = React.createClass({
    render() {
        const { progress } = this.props;
        if (progress < 1000) {
            return (
                <View>
                    <Text>{this.props.title} [{progress}%]</Text>
                    <ProgressBar
                        fillStyle={{}}
                        backgroundStyle={{backgroundColor: '#cccccc', borderRadius: 2}}
                        style={{marginTop: 10, width:PROGRESS_WIDTH}}
                        progress={progress/100.0}
                        />
                    <View style={styles.progressText}>
                        <Text>0</Text>
                        <Text>100</Text>
                    </View>
                </View>
            );
        } else {
            let size = progress/1000/1024/1024;
            return (
                <View style={{flex: 1, alignItems: 'center'}}>
                    <Text>{this.props.title} [{size.toFixed(2)} M]</Text>
                </View>
            );
        }
    }
});

module.exports = React.createClass({
    getInitialState() {
        const {options} = this.props;
        return {
            options,
            status: !options ? STATUS_GET_VERSION : options.newVersion ? STATUS_HAS_VEW_VERSION : STATUS_HAS_NOT_VEW_VERSION,
            progress: 0,
        };
    },
    componentWillMount() {
        if (!this.state.options) {
            Update.checkVersion({
                versionUrl: app.route.ROUTE_VERSION_INFO_URL,
                iosAppId: CONSTANTS.IOS_APPID,
            }).then((options)=>{
                this.setState({options, status: !options ? STATUS_GET_VERSION_ERROR : options.newVersion ? STATUS_HAS_VEW_VERSION : STATUS_HAS_NOT_VEW_VERSION});
            })
        }
    },
    onError(errCode) {
        if (errCode == ERROR_DOWNKOAD_APK) {
            this.setState({status: STATUS_DOWNKOAD_APK_ERROR});
        } else if (errCode == ERROR_DOWNKOAD_JS) {
            this.setState({status: STATUS_DOWNKOAD_JS_ERROR});
        } else if (errCode == ERROR_FAILED_INSTALL) {
            this.setState({status: STATUS_FAILED_INSTALL_ERROR});
        } else if (errCode == ERROR_UNZIP_JS) {
            this.setState({status: STATUS_UNZIP_JS_ERROR});
        }
    },
    doUpdate() {
        const {jsVersionCode, trackViewUrl} = this.state.options;
        if (jsVersionCode !== undefined) {
            Update.updateJS({
                jsVersionCode,
                jsbundleUrl: app.isandroid?app.route.ROUTE_JS_ANDROID_URL:app.route.ROUTE_JS_IOS_URL,
                onDownloadJSProgress:(progress)=>{this.setState({status: STATUS_DOWNLOAD_JS_PROGESS,progress})},
                onUnzipJSProgress:(progress)=>{this.setState({status: STATUS_UNZIP_JS_PROGESS,progress})},
                onUnzipJSEnd:()=>{this.setState({status: STATUS_UPDATE_END})},
                onError:(errCode)=>{this.onError(errCode)},
            });
        } else {
            Update.updateApp({
                trackViewUrl,
                androidApkUrl:app.route.ROUTE_APK_URL,
                androidApkDownloadDestPath:'/sdcard/yxjqd.apk',
                onDownloadAPKProgress:(progress)=>{this.setState({status: STATUS_DOWNLOAD_APK_PROGESS,progress})},
                onError:(errCode)=>{this.onError(errCode)},
            });
        }
    },
    render() {
        var components = {};
        const {currentVersion, newVersion, description} = this.state.options||{currentVersion:Update.getVersion()};
        components[STATUS_GET_VERSION] = (
            <Text style={styles.textInfo}>正在获取版本号</Text>
        );
        components[STATUS_HAS_NOT_VEW_VERSION] = (
            <Text style={styles.textInfo}>当前版本已经是最新版本</Text>
        );
        components[STATUS_GET_VERSION_ERROR] = (
            <Text style={styles.textInfo}>获取版本信息失败,请稍后再试</Text>
        );
        components[STATUS_DOWNKOAD_APK_ERROR] = (
            <Text style={styles.textInfo}>下载apk文件失败,请稍后再试</Text>
        );
        components[STATUS_DOWNKOAD_JS_ERROR] = (
            <Text style={styles.textInfo}>下载js bundle失败,请稍后再试</Text>
        );
        components[STATUS_UNZIP_JS_ERROR] = (
            <Text style={styles.textInfo}>解压js bundle失败,请稍后再试</Text>
        );
        components[STATUS_FAILED_INSTALL_ERROR] = (
            <Text style={styles.textInfo}>你放弃了安装</Text>
        );
        components[STATUS_HAS_VEW_VERSION] = (
            <View style={styles.textInfoContainer}>
                <Text style={styles.textInfo}>发现新版本{newVersion}</Text>
                <View style={styles.descriptionContainer}>
                    {
                        description && description.map((item, i)=>{
                            return (
                                <Text style={styles.textInfo} key={i}>{(i+1)+'. '+item}</Text>
                            )
                        })
                    }
                </View>
                <Button onPress={this.doUpdate} style={styles.button_layer} textStyle={styles.button_text}>立即更新</Button>
            </View>
        );
        components[STATUS_DOWNLOAD_APK_PROGESS] = (
            <ProgressInfo
                title="正在下载APK"
                progress={this.state.progress} />
        );
        components[STATUS_DOWNLOAD_JS_PROGESS] = (
            <ProgressInfo
                title="正在下载Bundle文件"
                progress={this.state.progress} />
        );
        components[STATUS_UNZIP_JS_PROGESS] = (
            <ProgressInfo
                title="正在解压Bundle文件"
                progress={this.state.progress} />
        );
        components[STATUS_UPDATE_END] = (
            <Text>正在重启...</Text>
        );
        return (
            <View style={styles.container}>
                <View style={styles.logoContainer}>
                    <Image
                        resizeMode='stretch'
                        source={app.img.personal_logo}
                        style={styles.logo}
                        />
                    <Text style={styles.app_name}>赢销截拳道 V{currentVersion}</Text>
                </View>
                <View style={styles.functionContainer}>
                    {components[this.state.status]}
                </View>
            </View>
        );
    },
});


var styles = StyleSheet.create({
    container: {
        flex:1,
    },
    logoContainer: {
        alignItems:'center',
        marginTop: 52,
    },
    logo: {
        width: 83,
        height: 83,
    },
    app_name: {
        marginTop: 13,
        fontSize: 16,
        color: '#727272',
    },
    functionContainer: {
        flex: 1,
        width: sr.w,
        marginTop: 51,
        alignItems:'center',
    },
    button_layer: {
        width:178,
        height:49,
        borderRadius: 4,
        left: (sr.w-178)/2,
        position: 'absolute',
        bottom: 120,
        backgroundColor: '#DE3031',
    },
    button_text: {
        fontSize: 18,
        fontWeight: '400',
        color: '#FFFFFF',
        alignSelf: 'center',
        fontFamily: 'STHeitiSC-Medium',
    },
    progressText: {
        flexDirection:'row',
        justifyContent:'space-between',
        width: sr.w*0.7,
    },
    textInfoContainer: {
        flex: 1,
        width: sr.w,
    },
    textInfo: {
        color: '#000000',
        fontSize: 18,
        marginBottom: 6,
        textAlign: 'center',
    },
});

UpdateInfoBox.js

'use strict';
var React = require('react');
var ReactNative = require('react-native');
var {
    StyleSheet,
    View,
    Text,
    Image,
    TouchableOpacity,
} = ReactNative;

var Update = require('@remobile/react-native-update');

var
STATUS_HAS_VEW_VERSION = 0,
STATUS_DOWNLOAD_APK_PROGESS = 1,
STATUS_DOWNLOAD_JS_PROGESS = 2,
STATUS_UNZIP_JS_PROGESS = 3,
STATUS_DOWNKOAD_APK_ERROR = 4,
STATUS_DOWNKOAD_JS_ERROR = 5,
STATUS_UNZIP_JS_ERROR = 6,
STATUS_FAILED_INSTALL_ERROR = 7,
STATUS_UPDATE_END = 8;

var
ERROR_NULL = 0,
ERROR_DOWNKOAD_APK = 1,
ERROR_DOWNKOAD_JS = 2,
ERROR_FAILED_INSTALL = 3,
ERROR_UNZIP_JS = 4;

var PROGRESS_WIDTH = sr.tw*0.7;
var {Button, ProgressBar} = COMPONENTS;

var ProgressInfo = React.createClass({
    render() {
        const { progress } = this.props;
        if (progress < 1000) {
            return (
                <View style={[styles.functionContainer, {alignItems: 'center', paddingVertical: 30}]}>
                    <Text>{this.props.title} [{progress}%]</Text>
                    <ProgressBar
                        fillStyle={{}}
                        backgroundStyle={{backgroundColor: '#cccccc', borderRadius: 2}}
                        style={{marginTop: 10, width:PROGRESS_WIDTH}}
                        progress={progress/100.0}
                        />
                    <View style={styles.progressText}>
                        <Text>0</Text>
                        <Text>100</Text>
                    </View>
                </View>
            );
        } else {
            let size = progress/1000/1024/1024;
            return (
                <View style={[styles.functionContainer, {alignItems: 'center', paddingVertical: 30}]}>
                    <Text>{this.props.title} [ {size.toFixed(2)} M ]</Text>
                </View>
            );
        }
    }
});

module.exports = React.createClass({
    getInitialState() {
        return {
            status:STATUS_HAS_VEW_VERSION,
            progress: 0,
        };
    },
    onError(errCode) {
        if (errCode == ERROR_DOWNKOAD_APK) {
            this.setState({status: STATUS_DOWNKOAD_APK_ERROR});
        } else if (errCode == ERROR_DOWNKOAD_JS) {
            this.setState({status: STATUS_DOWNKOAD_JS_ERROR});
        } else if (errCode == ERROR_FAILED_INSTALL) {
            this.setState({status: STATUS_FAILED_INSTALL_ERROR});
        } else if (errCode == ERROR_UNZIP_JS) {
            this.setState({status: STATUS_UNZIP_JS_ERROR});
        }
    },
    doUpdate() {
        const {jsVersionCode, trackViewUrl} = this.props.options;
        if (jsVersionCode !== undefined) {
            Update.updateJS({
                jsVersionCode,
                jsbundleUrl: app.isandroid?app.route.ROUTE_JS_ANDROID_URL:app.route.ROUTE_JS_IOS_URL,
                onDownloadJSProgress:(progress)=>{this.setState({status: STATUS_DOWNLOAD_JS_PROGESS,progress})},
                onUnzipJSProgress:(progress)=>{this.setState({status: STATUS_UNZIP_JS_PROGESS,progress})},
                onUnzipJSEnd:()=>{this.setState({status: STATUS_UPDATE_END})},
                onError:(errCode)=>{this.onError(errCode)},
            });
        } else {
            Update.updateApp({
                trackViewUrl,
                androidApkUrl:app.route.ROUTE_APK_URL,
                androidApkDownloadDestPath:'/sdcard/yxjqd.apk',
                onDownloadAPKProgress:(progress)=>{this.setState({status: STATUS_DOWNLOAD_APK_PROGESS,progress})},
                onError:(errCode)=>{this.onError(errCode)},
            });
        }
    },
    render() {
        const components = {};
        const {newVersion, description} = this.props.options;
        components[STATUS_HAS_VEW_VERSION] = (
            <View style={styles.functionContainer}>
                <Text style={styles.title}>{`发现新版本(${newVersion})`}</Text>
                <Text style={styles.redLine}>
                </Text>
                <Text style={styles.content}>
                    {"更新内容:"}
                </Text>
                {
                    description.map((item, i)=>{
                        return (
                            <Text style={styles.contentItem} key={i}>{'- '+item}</Text>
                        )
                    })
                }
                <View style={styles.buttonViewStyle}>
                    <TouchableOpacity
                        onPress={app.closeModal}
                        style={styles.buttonStyleContainCannel}>
                        <Text style={styles.buttonStyleCannel}>以后再说</Text>
                    </TouchableOpacity>
                    <TouchableOpacity
                        onPress={this.doUpdate}
                        style={styles.buttonStyleContain}>
                        <Text style={styles.buttonStyle} >立即更新</Text>
                    </TouchableOpacity>
                </View>
            </View>
        );
        components[STATUS_DOWNKOAD_APK_ERROR] = (
            <View style={[styles.functionContainer, {alignItems: 'center', paddingVertical: 30}]}>
                <Text style={styles.textInfo}>下载apk文件失败,请在设置里重新更新</Text>
                <TouchableOpacity
                    onPress={app.closeModal}
                    style={styles.buttonStyleContainCannel}>
                    <Text style={styles.buttonStyleCannel}>我知道了</Text>
                </TouchableOpacity>
            </View>
        );
        components[STATUS_DOWNKOAD_JS_ERROR] = (
            <View style={[styles.functionContainer, {alignItems: 'center', paddingVertical: 30}]}>
                <Text style={styles.textInfo}>下载js bundle失败,请在设置里重新更新</Text>
                <TouchableOpacity
                    onPress={app.closeModal}
                    style={styles.buttonStyleContainCannel}>
                    <Text style={styles.buttonStyleCannel}>我知道了</Text>
                </TouchableOpacity>
            </View>
        );
        components[STATUS_UNZIP_JS_ERROR] = (
            <View style={[styles.functionContainer, {alignItems: 'center', paddingVertical: 30}]}>
                <Text style={styles.textInfo}>解压js bundle失败,请在设置里重新更新</Text>
                <TouchableOpacity
                    onPress={app.closeModal}
                    style={styles.buttonStyleContainCannel}>
                    <Text style={styles.buttonStyleCannel}>我知道了</Text>
                </TouchableOpacity>
            </View>
        );
        components[STATUS_FAILED_INSTALL_ERROR] = (
            <View style={[styles.functionContainer, {alignItems: 'center', paddingVertical: 30}]}>
                <Text style={styles.textInfo}>你放弃了安装</Text>
                <TouchableOpacity
                    onPress={app.closeModal}
                    style={styles.buttonStyleContainCannel}>
                    <Text style={styles.buttonStyleCannel}>我知道了</Text>
                </TouchableOpacity>
            </View>
        );
        components[STATUS_DOWNLOAD_APK_PROGESS] = (
            <ProgressInfo
                title="正在下载APK"
                progress={this.state.progress} />
        );
        components[STATUS_DOWNLOAD_JS_PROGESS] = (
            <ProgressInfo
                title="正在下载Bundle文件"
                progress={this.state.progress} />
        );
        components[STATUS_UNZIP_JS_PROGESS] = (
            <ProgressInfo
                title="正在解压Bundle文件"
                progress={this.state.progress} />
        );
        components[STATUS_UPDATE_END] = (
            <Text>即将重启...</Text>
        );
        return (
            <View style={styles.container}>
                {components[this.state.status]}
            </View>
        );
    },
});


var styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
    },
    functionContainer: {
        width:sr.w-60,
        backgroundColor:'#FFFFFF',
    },
    progressText: {
        flexDirection:'row',
        justifyContent:'space-between',
        width: sr.w*0.7,
    },
    textInfo: {
        color: '#000000',
        fontSize: 14,
        marginBottom: 20,
        textAlign: 'center',
    },
    buttonViewStyle: {
        flexDirection: 'row',
        width: sr.w-40,
        height: 60,
        justifyContent: 'center',
    },
    redLine: {
        marginTop: 15,
        width: sr.w-60,
        height: 1,
        backgroundColor: '#DE3031'
    },
    buttonStyleContain: {
        width: 120,
        height: 35,
        marginLeft: 30,
        justifyContent:'center',
        alignItems:'center',
        backgroundColor: '#DE3031',
    },
    buttonStyleContainCannel: {
        width: 120,
        height: 35,
        justifyContent:'center',
        alignItems:'center',
        backgroundColor: 'white',
        borderWidth: 1,
        borderColor: '#DE3031',
    },
    buttonStyle: {
        fontSize: 16,
        color: 'white',
        fontFamily: 'STHeitiSC-Medium',
    },
    buttonStyleCannel: {
        fontSize: 16,
        color: '#DE3031',
        fontFamily: 'STHeitiSC-Medium',
    },
    title: {
        color: '#DE3031',
        fontSize: 18,
        textAlign: 'center',
        overflow: 'hidden',
        marginTop: 15,
        fontFamily: 'STHeitiSC-Medium',
    },
    content: {
        color:'#000000',
        marginTop: 10,
        marginBottom: 10,
        marginHorizontal: 20,
        fontSize:16,
        fontFamily: 'STHeitiSC-Medium',
    },
    contentItem: {
        color:'#000000',
        marginBottom: 10,
        marginHorizontal: 20,
        fontSize:12,
    },
});

Method

  • Update.getVersion - get current version
    • return value is x.x.x
  • Update.checkVersion - check server version
  • Update.updateApp - update apk or ios appstore
  • Update.updateJS - update js bundle file

Check Version And Show Update Dialog

const Update = require('@remobile/react-native-update');
const UpdateInfoBox = require('../modules/update/UpdateInfoBox');
Update.checkVersion({
    versionUrl: app.route.ROUTE_VERSION_INFO_URL,
    iosAppId: CONSTANTS.IOS_APPID,
}).then((options)=>{
    if (options && options.newVersion) {
        app.showModal(<UpdateInfoBox options={options} />, {backgroundColor:'rgba(0, 0, 0, 0.6)'})
    }
})

Check Version And Show Update Page

const Update = require('@remobile/react-native-update');
const UpdatePage = require('../modules/update/UpdatePage');

Update.checkVersion({
    versionUrl: app.route.ROUTE_VERSION_INFO_URL,
    iosAppId: CONSTANTS.IOS_APPID,
}).then((options)=>{
    app.navigator.push({
        title: '在线更新',
        component: UpdatePage,
        passProps: {options},
    });
})

Options

* versionUrl:the url of verison on server:
    * format: { "versionCode":1, "versionName":"1.0", "jsVersionCode":2, "description":"hello"}
    * this structor will pass to needUpdateApp and needUpdateJS if your set them, so you can customize the format, but versionCode and jsVersionCode  keep.
* iosAppId:the appid on app Store

Update App Or JS

doUpdate() {
    const {jsVersionCode, trackViewUrl} = this.props.options;
    if (jsVersionCode !== undefined) {
        Update.updateJS({
            jsVersionCode,
            jsbundleUrl: app.isandroid?app.route.ROUTE_JS_ANDROID_URL:app.route.ROUTE_JS_IOS_URL,
            onDownloadJSProgress:(progress)=>{this.setState({status: STATUS_DOWNLOAD_JS_PROGESS,progress})},
            onUnzipJSProgress:(progress)=>{this.setState({status: STATUS_UNZIP_JS_PROGESS,progress})},
            onUnzipJSEnd:()=>{this.setState({status: STATUS_UPDATE_END})},
            onError:(errCode)=>{this.onError(errCode)},
        });
    } else {
        Update.updateApp({
            trackViewUrl,
            androidApkUrl:app.route.ROUTE_APK_URL,
            androidApkDownloadDestPath:'/sdcard/yxjqd.apk',
            onDownloadAPKProgress:(progress)=>{this.setState({status: STATUS_DOWNLOAD_APK_PROGESS,progress})},
            onError:(errCode)=>{this.onError(errCode)},
        });
    }
},

Options

* jsbundleUrl:the js bundle url
    * only js code changed or images resource changed, I wish you publish jsbundle, called Minor version
    * include www/index.android.bundle or www/index.ios.bundle
    * include image dir on android, and assets dir on ios
    * on android, image dir include some dynamic image(the new images this version add)
    * publish Minor version you should increase jsVersionCode
* androidApkUrl:this apk url
    * only the native code changed, you need to publish apk on android or ipa on ios, called Marjor version
    * publish Marjor version you should increase versionCode and set jsVersionCode to 0
* androidApkDownloadDestPath:where apk file download, e.g:/sdcard/download, make sure it exists
* onDownloadAPKStart:function
    * callback when apk start download
* onDownloadAPKProgress:function
    * callback when apk is downloading,
    * will be pass {total:xx, loaded:xx} 1 parameter
* onDownloadAPKEnd:function
    * callback when apk download end
* onDownloadJSStart:function
* onDownloadJSProgress:function
    * callback when apk is downloading,
    * will be pass {total:xx, loaded:xx} 1 parameter
* onDownloadJSEnd:function
* onUnzipJSStart:function
* onUnzipJSProgress:function
    * callback when unzip jsbundle is downloading,
    * will be pass {total:xx, loaded:xx} 1 parameter
* onUnzipJSEnd:function
* onError:function
    * will be pass errorCode
    * var ERROR_NULL = 0, ERROR_DOWNKOAD_APK = 1, ERROR_DOWNKOAD_JS = 2, ERROR_GET_VERSION = 3, ERROR_UNZIP_JS = 4;

Generate Bundle

#!/bin/bash

distpath=../../localServer/public/download

function genIOSBundle() {
    react-native bundle \
        --platform ios \
        --reset-cache \
        --verbose \
        --entry-file index.ios.js \
        --bundle-output ./tools/www/index.ios.bundle \
        --assets-dest ./tools/www/ \
        --dev false
}

function genAndroidBundle() {
    react-native bundle \
        --platform android \
        --reset-cache \
        --verbose \
        --entry-file index.android.js \
        --bundle-output ./tools/www/index.android.bundle \
        --assets-dest ./tools/www/ \
        --dev false
}

function zipWWW() {
    node -e "!function(){function i(e,r){var o=n.readdirSync(e);o.forEach(function(o){var s=e+'/'+o;n.statSync(s).isDirectory()?i(s,r+'/'+o):c.folder(r).file(o,n.readFileSync(s))})}function e(e,r,o){r=r||'',o=o||e+'.zip',i(e,r);var s=c.generate({base64:!1,compression:'DEFLATE'});n.writeFile(o,s,'binary',function(){console.log('success')})}var r=require('jszip'),n=require('fs'),c=new r,o=process.argv.splice(1);e.apply(null,o)}();"  www _www www.zip
}

function genMd5List() {
    cd ./tools
    # git co head ${distpath}/${1}_md5.json
    node -e "var o=process.argv;require('./getMd5List')(o[1],o[2])" ${1} ${distpath}
}

function zipFile() {
    zipWWW
    mv ./www.zip ${distpath}/js${1}.zip
    rm -fr www
    mv ./${1}_md5.json ${distpath}/${1}_md5.json
    echo "${distpath}"
}

function buildAndroid() {
    rm -fr www
    mkdir www
    cd ..
    genAndroidBundle
    genMd5List android
    zipFile android
}

function buildIos() {
    rm -fr www
    mkdir www
    cd ..
    genIOSBundle
    genMd5List ios
    zipFile ios
}

function main() {
    if [ "$1" = "android" ];then
        buildAndroid
    elif [ "$1" = "ios" ];then
        buildIos
    elif [ "$1" = "all" ];then
        buildAndroid
        buildIos
    else
        echo "Usage: ./genbundle ios|android|all"
    fi
}

main $@
  • make sure install jszip use npm in global, we use it zip

server side version.json

{
    "iosPassed": true,
    "iosJsVersionCode":0,
    "iosDescription":["修正bug", "添加新功能"],
    "androidPassed": {
        "baidu": false,
        "default": true
    },
    "versionName":"1.0",
    "versionCode": 1048576,
    "androidJsVersionCode":0,
    "androidDescription": ["修改bug", "添加新功能"]
}

see detail use

  • https://github.com/remobile/react-native-template

tools at

useful tools

example in react-native-template

Update