rn打包bundle程序

  1. 首先, 下载相关依赖插件

yarn add  compressing

  1. 修改package.json
    package.json
    将下面的内容放到scripts里面;
    "rn_modules": "node webpackHooks/deleteNodeModules.js",
    "bundle-ios": "node node_modules/react-native/local-cli/cli.js bundle --entry-file index.js --platform ios --dev false --bundle-output ./dist/ios/index.ios.bundle --assets-dest ./dist/ios", 
    "bundle-android": "node node_modules/react-native/local-cli/cli.js bundle --entry-file index.js --platform android --dev false --bundle-output ./dist/android/index.android.bundle --assets-dest ./dist/android",
    "zip": "node webpackHooks/commder.js",
    "bundle-all": "npm run update-version && npm run bundle-ios && npm run bundle-android && npm run updateMd5 && npm run zip",
    "update-version": "node webpackHooks/index.js",
    "bundle-tow": "npm run bundle-ios && npm run bundle-android",
    "InspectZip": "node webpackHooks/InspectZip.js",
    "inspectFileSize": "node webpackHooks/inspectFileSize.js",
    "inspect-all": "npm run inspectFileSize && npm run InspectZip",
    "rn-dist": "node webpackHooks/rnDist.js",
    "createDirIfNotExists": "node webpackHooks/createDirIfNotExists.js",
    "updateMd5": "node webpackHooks/updateMd5.js",
    "init-bundle": "npm run createDirIfNotExists && npm run rn-dist && npm run bundle",
    "bundle": "npm run bundle-all && npm run inspect-all",
    "bundle-ios-zip": "react-native bundle --entry-file index.js --bundle-output ./dist/ios/ios/index.ios.bundle --platform ios --assets-dest ./dist/ios/ios --dev false&&node commder ios",
    "bundle-android-zip": "react-native bundle --platform android --dev false --entry-file index.js --bundle-output ./dist/android/android/index.android.bundle --assets-dest ./dist/android/android --verbose&&node commder android",

解释说明:

bundle-ios: 打包ios的bundle包

bundle-android: 打包安卓的bundle包

zip: 将dist/ios 或dist/android 打包成zip , zip目录结构如下
ios: 版本号/ios/相关bundle和资源文件 0.1.1/ios//index.ios.bundle(和assets等文件)

安卓: android_版本号/andorid/相关bundle和资源文件 android_0.1.1/android//index.android.bundle(和assets等文件)

update-version: 更新package.json文件内的version的值,从dist/iso/version.json获取,并自动向上升级一个小版本, 必须要存在才能更新,如不存在,请不要执行该命令

bundle-tow: 同时执行 bundle-ios 和Budnle-android 命令

bundle-all: 先执行更新版本号,然后打包,然后生成md5,最后生成zip

InspectZip: 判断压缩包大小,是否超过最大限值;

inspectFileSize: 检测每个文件的大小,并再控制台打印;

"inspect-all": InspectZip 和 inspectFileSize 的集合;

"rn-dist": 删除dist目录

“createDirIfNotExists”: 创建dist目录和dist/ios dist/android目录

“updateMd5”: 更新version.json里面的md5

“init-bundle”: 第一次拉代码后执行的打包命令,这时候你可能没有dist文件,这会帮你自动创建。注意: 第一次创建打包可能会卡死在打包ios时, 这时候如果卡死了,请停止重新执行npm run bundle即可

bundle: 打包并且检测包大小, ** 平时打包就是使用这个命令即可 **

  1. 新建下面的目录webpackHooks和目录下面的文件, 代码都在下面; 将webpackHooks放到项目根目录;

webpackHooks/commder.js
压缩程zip包

const PackageJSON = require('../package.json');
const compressing = require('compressing');

compressing.zip.compressDir('./dist/ios', './dist/'+PackageJSON.version+'.zip').then(res => {
    console.log("asdadres",res);
  }).catch(err => {
    console.log("asdaderr",err);
  })


  compressing.zip.compressDir('./dist/android', './dist/android_'+PackageJSON.version+'.zip').then(res => {
    console.log("asdadres",res);
  }).catch(err => {
    console.log("asdaderr",err);
  })

webpackHooks/createDirIfNotExists.js
检查文件dist目录是否存在,不存在就创建

const fs = require('fs');
const path = require('path');

const sep = '/'

function createDirIfNotExists(dirPath) {
    console.log('检查文件是否存在,开始检查:', dirPath)
    dirPath.split(sep).reduce((prevPath, folder) => {
        const currentPath = path.join(prevPath, folder, sep);
        if (!fs.existsSync(currentPath)){
            fs.mkdirSync(currentPath);
        }
        return currentPath;
    }, '');
    console.log('检查文件是否存在,结束检查:', dirPath)
}

const iosVersionPath = './dist/ios';
const androidVersionPath = './dist/android';
// 使用方法
createDirIfNotExists(iosVersionPath);
createDirIfNotExists(androidVersionPath);

webpackHooks/deleteNodeModules.js
递归删除node_modules目录和包

const fs = require('fs');
const path = require('path');
 
// 递归删除目录
function deleteDirectoryRecursive(directoryPath) {
    console.log(`fs.existsSync(directoryPath)`, fs.existsSync(directoryPath))
  if (fs.existsSync(directoryPath)) {
    fs.readdirSync(directoryPath).forEach(function(file, index) {
      var curPath = path.join(directoryPath, file);
      if (fs.lstatSync(curPath).isDirectory()) {
        // 递归删除子目录
        deleteDirectoryRecursive(curPath);
      } else {
        // 删除文件
        fs.unlinkSync(curPath);
      }
    });
    // 删除目录
    fs.rmdirSync(directoryPath);
  }
}
 
// 调用函数删除指定的文件夹
const folderPath = './node_modules'; // 替换为您要删除的文件夹路径
deleteDirectoryRecursive(folderPath);

webpackHooks/deleteRmFile.js
删除指定路径内的文件

const fs = require('fs');
const path = require('path');

function deleteFilesInDirectory(dirPath) {
    console.log('开始删除文件路径内文件:', dirPath)
    if (fs.existsSync(dirPath)) {
        fs.readdirSync(dirPath).forEach((file) => {
            const filePath = path.join(dirPath, file);
            if (fs.lstatSync(filePath).isDirectory()) {
                // 递归删除子文件夹
                deleteFilesInDirectory(filePath);
                fs.rmdirSync(filePath); // 删除空文件夹
            } else {
                // 删除文件
                fs.unlinkSync(filePath);
            }
        });
    } else {
        console.log(`Directory ${dirPath} does not exist.`);
    }
    console.log('结束删除文件路径内文件:', dirPath)
}

module.exports = deleteFilesInDirectory;

webpackHooks/index.js
打包入口


var updateVersionFn = require('./updateVersionFn.js')
// var updateAllMd5 = require('./updateMd5.js')

console.log('------------执行更新version.json更新版本号程序------------')
updateVersionFn()
// updateAllMd5()

webpackHooks/inspectFileSize.js
读取文件并打印文件大小

//引入内置模块
const path = require('path')
const fs = require('fs')

const iosOriginPath = 'dist/ios'
const andoridOriginPath = 'dist/android'

const fileList = []

var inspectFileSize = function(srcPath, cb) {
    const iosFile = fs.statSync(srcPath);
    // console.log(`iosFile`, iosFile)
    // console.log(`文件名称:`, srcPath, `大小: `, Math.ceil(iosFile.size/1024), 'kb')
    fileList.push({
        filePath: srcPath,
        fullSize:iosFile.size,
        fileSize:  Math.ceil(iosFile.size/1024),
        fileSizeStr: Math.ceil(iosFile.size/1024) + 'kb'
    })
    cb()
  }

var copyFolder = function(srcDir, cb) {
    fs.readdir(srcDir, function(err, files) {
        // console.log(`err`, err)
        // console.log(`files`, files)
      var count = 0
      var checkEnd = function() {
        ++count == files.length && cb && cb()
      }
  
      if (err) {
        checkEnd()
        return
      }
  
      files.forEach(function(file) {
        var srcPath = path.join(srcDir, file)
  
        fs.stat(srcPath, function(err, stats) {
          if (stats.isDirectory()) {
            copyFolder(srcPath, checkEnd)
          } else {
            inspectFileSize(srcPath, checkEnd)
          }
        })
      })
  
      //为空时直接回调
      files.length === 0 && cb && cb()
    })
  }


  function inspectFileSizeInit() {
    copyFolder(iosOriginPath, function(err) {
        if (err) {
      
          return
        }
    
        // fileList.sort((a, b) => b.fullSize - a.fullSize).forEach(v => {
        //     console.log(`文件名称:`, v.filePath, `大小: `, v.fileSize, 'kb')
        // })

        copyFolder(andoridOriginPath, function(err) {
          if (err) {
        
            return
          }
      
          fileList.sort((a, b) => a.fullSize - b.fullSize).forEach(v => {
              console.log(`文件名称:`, v.filePath, `大小: `, v.fileSize, 'kb')
          })
        })
      })
  }
  inspectFileSizeInit()

webpackHooks/InspectZip.js
检查dist内每个文件的大小,和总的压缩大小


const packageJsonVersionPath = './package.json'
const fs = require('fs');

const maxSize = 3*1024*1024  // 最大限制 3m

function getPackageVersionFn() {
    const isExit = fs.existsSync(packageJsonVersionPath);
    console.log('是否存在package.json', isExit ? '存在' : '不存在');
    // 当存在文件时;
    if (isExit) {
      const dataJsonStringify = fs.readFileSync(packageJsonVersionPath, 'utf8');
      const dataJsonParse = JSON.parse(dataJsonStringify);
     return dataJsonParse.version
    }
  }

  function InspectSizeLog(iosPath){
    const iosFile = fs.statSync(iosPath);
      // console.log(`dataJsonStringify`, iosFile)
      // console.log('%c在这个符号后的信息是绿色','color: #529b2e')
      console.log(`检查到${iosPath}文件,大小为:`, iosFile.size/1024 > maxSize ? iosFile.size/1024 : `${iosFile.size/1024}` , `KB`)
      if (maxSize < iosFile.size) {
          console.log(`-----------------------------------start   重要的事情说四次-------------------------------------------------------------`)
          console.info(`警告: ${iosPath}文件最大为`, maxSize/1024, 'kb', `当前大小为`, iosFile.size/1024, `kb,请优化代码到合理大小;`)
          console.info(`警告: ${iosPath}文件最大为`, maxSize/1024, 'kb', `当前大小为`, iosFile.size/1024, `kb,请优化代码到合理大小;`)
          console.info(`警告: ${iosPath}文件最大为`, maxSize/1024, 'kb', `当前大小为`, iosFile.size/1024, `kb,请优化代码到合理大小;`)
          console.info(`警告: ${iosPath}文件最大为`, maxSize/1024, 'kb', `当前大小为`, iosFile.size/1024, `kb,请优化代码到合理大小;`)
          console.log(`-----------------------------------end-------------------------------------------------------------`)
      }

  }

  function InspectSizeFn() {
    const pageVersion = getPackageVersionFn()
    const iosPath = `dist/${pageVersion}.zip`
    const androidPath = `dist/android_${pageVersion}.zip`
    const isIosExit = fs.existsSync(iosPath);
    const isAndoridExit = fs.existsSync(androidPath);
    console.log(`是否存在ios的zip文件:  ${iosPath}是否存在:`, isIosExit ? '存在' : '不存在');
    console.log(`是否存在andorid的zip文件:  ${androidPath}是否存在:`, isAndoridExit ? '存在' : '不存在');
    // 默认升级小版本
    // 当存在文件时;
    if (isIosExit) {
      console.log(`正在读取${iosPath}文件,请稍后...`);
      InspectSizeLog(iosPath)
    }
    if (isAndoridExit) {
        console.log(`正在读取${iosPath}文件,请稍后...`);
          InspectSizeLog(androidPath)
    }
  }
  InspectSizeFn()

webpackHooks/rnDist.js
删除dist目录文件


var deleteFilesInDirectory = require('./deleteRmFile.js')

const iosVersionPath = './dist/ios';
const androidVersionPath = './dist/android';
deleteFilesInDirectory(iosVersionPath)
deleteFilesInDirectory(androidVersionPath)

webpackHooks/updateMd5.js
更新md5


const fs = require('fs');
const crypto = require('crypto');

const iosBundlePath = './dist/ios/index.ios.bundle';
const androidBundlePath = './dist/android/index.android.bundle';
const iosVersionPath = './dist/ios/version.json';
const androidVersionPath = './dist/android/version.json';
function updateMd5(path){
  const isExit = fs.existsSync(path);
  if (isExit) {
    const bundleStr = fs.readFileSync(path, 'utf8');
    // 创建hash对象并指定算法为md5
    const hash = crypto.createHash('md5');
    // 更新hash对象的内容
    hash.update(bundleStr);
    const md5Value = hash.digest('hex');
    console.log(`MD5 value of xxx is ${md5Value}`);

    return md5Value
  }

  return ''
}

function updateVersionFn(verPath, bundlePath, keyName) {
    const isExit = fs.existsSync(verPath);
    console.log('是否存在version.json', isExit ? '存在' : '不存在');
    // 默认升级小版本
    // 当存在文件时;
    if (isExit) {
      console.log(keyName+'正在更新version.json文件md5,请稍后...');
      const dataJsonStringify = fs.readFileSync(verPath, 'utf8');
      const dataJsonParse = JSON.parse(dataJsonStringify);
      const Md5 = updateMd5(bundlePath)
      dataJsonParse[keyName] = Md5
    
      fs.writeFileSync(verPath, JSON.stringify(dataJsonParse));
    }
  }

  function updateAllMd5(){
    console.log(`开始更新md5`)
    const verPathList = [iosVersionPath, androidVersionPath]
    const bundlePathList = [iosBundlePath, androidBundlePath]
    const keyNameList = ['iosMd5', 'androidMd5']
    keyNameList.forEach((v, i) => {
        updateVersionFn(verPathList[i], bundlePathList[i], keyNameList[i])
    })
    console.log(`结束更新md5`)
  }

  updateAllMd5();
module.exports = updateAllMd5;

webpackHooks/updateVersionFn.js
更新版本号

const AppJSON = require('../app.json');
const {name} = AppJSON;
const AppName = name;
const fs = require('fs');
const versionPath = './dist/ios/version.json';
const androidVersionPath = './dist/android/version.json';
const packageJsonVersionPath = './package.json';
const upgradeBigVersion = false; // 是否升级大版本
const upgradeMiddleVersion = false; // 是否升级中版本, 大版本更新优先, 当大版本更新时,重置中/小版本=0, 当中版本更新时,重置小版本=0

function getUpdateVersion(version){
    let bigVersion = parseInt(version.split('.')[0]);
    let middleVersion = parseInt(version.split('.')[1]);
    let smallVersion = parseInt(version.split('.')[2]);

    if (upgradeBigVersion) {
      bigVersion += 1;
      middleVersion = 0;
      smallVersion = 0;
    } else if (upgradeMiddleVersion) {
      middleVersion += 1;
      smallVersion = 0;
    } else {
      smallVersion += 1;
    }
    return  `${bigVersion}.${middleVersion}.${smallVersion}`;
}

function updateVersionFn() {
  const isExit = fs.existsSync(versionPath);
  const pageVersion = getPackageVersionFn()
  console.log('是否存在version.json', isExit ? '存在' : '不存在');
  // 默认升级小版本
  // 当存在文件时;
  if (isExit) {
    console.log('正在更新version.json文件版本号,请稍后...');
    const dataJsonStringify = fs.readFileSync(versionPath, 'utf8');
    const dataJsonParse = JSON.parse(dataJsonStringify);
   
    let endVersion = pageVersion || dataJsonParse.version

    if (endVersion) {
      dataJsonParse.version = getUpdateVersion(endVersion)
      dataJsonParse.name = AppName
      console.log('当前版本号:', dataJsonParse.version);
    } else {
      dataJsonParse.version = `0.0.1`;
      dataJsonParse.name = AppName
      console.log('当前版本号:', dataJsonParse.version);
    }
    updatePackageVersionFn(dataJsonParse.version)
    fs.writeFileSync(versionPath, JSON.stringify(dataJsonParse));
    fs.writeFileSync(androidVersionPath, JSON.stringify(dataJsonParse));
  } else {
    console.log('新建version.json文件中,请稍后...');
    const obj = {
      name: AppName,
      version: pageVersion ? getUpdateVersion(pageVersion) : '0.0.1',
    };
    fs.writeFileSync(versionPath, JSON.stringify(obj));
    fs.writeFileSync(androidVersionPath, JSON.stringify(obj));
    console.log('当前版本号:', obj.version);
    updatePackageVersionFn(obj.version)
  }
}

function getPackageVersionFn() {
    const isExit = fs.existsSync(packageJsonVersionPath);
    console.log('是否存在package.json', isExit ? '存在' : '不存在');
    // 当存在文件时;
    if (isExit) {
      const dataJsonStringify = fs.readFileSync(packageJsonVersionPath, 'utf8');
      const dataJsonParse = JSON.parse(dataJsonStringify);
     return dataJsonParse.version
    }
  }
function updatePackageVersionFn(version) {
    const isExit = fs.existsSync(packageJsonVersionPath);
    console.log('是否存在package.json', isExit ? '存在' : '不存在');
    // 当存在文件时;
    if (isExit) {
      console.log('正在更新package.json文件版本号,请稍后...');
      const dataJsonStringify = fs.readFileSync(packageJsonVersionPath, 'utf8');
      const dataJsonParse = JSON.parse(dataJsonStringify);
      dataJsonParse.version = version
      fs.writeFileSync(packageJsonVersionPath, JSON.stringify(dataJsonParse, null, 2));
    }
  }


module.exports = updateVersionFn;

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容