Can I pass version from package.json to the built project?

Every time I build the project for iOS, its version resets to 1.0.0

Strange, but I just tried to build project for Android and everything goes fine. Did you bump version in /cordova/config.xml? Package.json don’t affect on Cordova project version, you should use config.xml for that. Every time before releasing to Store it should be incremented. Also, you could write Cordova hook which will take your package.json version and insert in to config.xml automatically.

1 Like

Got you, thx
Now I’m trying to create a hook, which will update config.xml.
But I dont know what hook I should use. Already tried ‘before_build’, ‘before_prepare’, ‘before_compile’. It updates config.xml, but doesn’t affect version of ios project.

Are there F7 hooks may be? Shouldn’t I use it?

My hook is pretty simple and I tested it on production. (Project wasn’t created with Framework7-CLI, but that doesnt matter).

config.xml

<widget>
   <hook src="hooks/bumpversion.js" type="before_prepare"/>
</widget>

bumpversion.js

const path = require("path");
const fs = require("fs");
const file = path.resolve(__dirname, "../config.xml");
const config = path.resolve(__dirname, "../package.json");

const packageJson = require(config);

function readConfig(file) {
  return new Promise((resolve, reject) => {
    fs.readFile(file, "utf8", (err, data) => {
      if (err) {
        reject(err);
      } else {
        resolve(data);
      }
    });
  });
}

function transformContent(data) {
  const rows = data.split("\n");
  let transformedContent = [];

  rows.forEach(row => {
    if (row.match("<widget")) {
      row = row.replace(/version=".+?"/, `version="${packageJson.version}"`);
    }

    transformedContent.push(row);
  });

  return Promise.resolve(transformedContent.join("\n"));
}

function updateConfig(file, content) {
  return new Promise((resolve, reject) => {
    fs.writeFile(file, content, err => {
      if (err) {
        reject(err);
      } else {
        resolve();
      }
    });
  });
}

readConfig(file)
  .then(transformContent)
  .then(transformedContent => {
    setTimeout(() => {
      updateConfig(file, transformedContent);
    });
  });

This approach is quite ugly, but it work. You could use sed command in bash for that, but I didn’t find quick solution and switched to NodeJS.

1 Like

If your project built with F7-CLI and you use webpack, i have the following in my projects.

In main package.json i have 2 additional fields:

"appVersion": "1.0.1",
"appBuild": "200",

In cordova/config.xml i have the following main widget tag:

<widget id="..." version="1.0.1" ios-CFBundleVersion="200" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">

And in build/build.js i have the following:

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

const webpack = require('webpack');
const ora = require('ora');
const rm = require('rimraf');
const chalk = require('chalk');
const config = require('./webpack.config.js');
const pkg = require('../package.json');

const env = process.env.NODE_ENV || 'development';
const target = process.env.TARGET || 'web';
const isCordova = target === 'cordova'
const cordovaFolder = 'cordova';

const spinner = ora(env === 'production' ? 'building for production...' : 'building development version...');
spinner.start();

// this part will update config.xml's version and ios-CFBundleVersion attributes
if (isCordova) {
  let configXmlContent = fs.readFileSync(path.resolve(__dirname, `../${cordovaFolder}/config.xml`), 'utf8');
  configXmlContent = configXmlContent
    .replace(/version="([^"]*)"/, `version="${pkg.appVersion}"`)
    .replace(/ios-CFBundleVersion="([^"]*)"/, `ios-CFBundleVersion="${pkg.appBuild}"`);
  fs.writeFileSync(path.resolve(__dirname, `../${cordovaFolder}/config.xml`), configXmlContent);
}
// end of config.xml fixes

rm(isCordova ? './cordova/www' : './www/', (removeErr) => {
  if (removeErr) throw removeErr;

  webpack(config, (err, stats) => {
    if (err) throw err;
    spinner.stop();

    process.stdout.write(`${stats.toString({
      colors: true,
      modules: false,
      children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
      chunks: false,
      chunkModules: false,
    })}\n\n`);

    if (stats.hasErrors()) {
      console.log(chalk.red('Build failed with errors.\n'));
      process.exit(1);
    }

    console.log(chalk.cyan('Build complete.\n'));
  });
});

And everytime i run npm run build-cordova-... commands, it updates config.xml as well

1 Like

Same here. It updates config.xml but project file takes previous version from package.json. But thx for the script :slight_smile:

Works like a charm, thx!

Updated a bit:

if (isCordova) {
  let configXmlContent = fs.readFileSync(path.resolve(__dirname, `../${cordovaFolder}/config.xml`), 'utf8');
  let [version, build] = (pkg.version+'-1').split('-');
  configXmlContent = configXmlContent
    // .replace(/version="([^"]*)"/, `version="${pkg.appVersion}"`)
    // .replace(/ios-CFBundleVersion="([^"]*)"/, `ios-CFBundleVersion="${pkg.appBuild}"`);
    .replace(/(widget.*?)version="([^"]*)"/, `$1version="${version}"`)
    .replace(/ios-CFBundleVersion="([^"]*)"/, `ios-CFBundleVersion="${build}"`);
  fs.writeFileSync(path.resolve(__dirname, `../${cordovaFolder}/config.xml`), configXmlContent);
}

And added
npm version prerelease --force &&
to every build script

Не понятно в чем реальный профит, какая разница где менять версию: в config.xml или package.json Что действительно было бы удобно - так это увеличивать номер билда при каждой сборке.

У меня в некоторых приложениях выводится версия в настройках (давайте только не будем полемизировать на тему зачем это нужно),а так же используется в фоновом процессе для определения наличия апдейта и последующего уведомления пользователя через диалоговое окно (пользователи очень неохотно иногда обновляются). Она берется из package.json. Но есть еще версия приложения в сторе, которая выводится в магазине, которая берется из config.xml. Приходится эти версии синхронизировать, чтобы не вводить пользователя в заблуждение. Для увеличения версии я использую стандартные средства типа npm version patch, что гораздо удобнее чем ручками что-то править в config.xml. В итоге я имею единственный “источник” версии и меняю его в одном месте.

Это неверное утверждение

Опровержение то будет? (Я в курсе, что в App Store это руками ввести можно, меня интересует как это можно сделать в Google Play).

Так и сделано. В каждом скрипте есть
npm version prerelease --force
А потом при билде это летит в config.xml