Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ionic PWA get version number from config.xml

I want to show the version number from config.xml in an Ionic PWA.

It is easy to get it done for ios/android builds using ionic native app version plugin.

But what is a good approach for a PWA build (npm run build --release --prod)?

like image 650
chris08002 Avatar asked Jan 28 '23 21:01

chris08002


2 Answers

Ok, so if cordova-plugin-app-version is not available on PWA, an alternative way to access to config.xml file is using a grunt task that copy the version to your templates (As you know, on Ionic the config.xml file is not placed on a "servable" location, so there is no way to read the version on execution time from config.xml).

For example, if we control the app version in package.json, we can config a grunt task that copy the version both to config.xml and src/index.html.

  1. On package.json set the app version.

    {
    "name": "my-app",
    "version": "1.0.7",
    ...
    
  2. Install grunt on your project.

    $> npm install grunt --save-dev
    $> npm install grunt-string-replace --save-dev
    
  3. Set version on config.xml and index.html, and create the gruntfile.js that replace the version number each time you release a version.

Config.xml

<?xml version='1.0' encoding='utf-8'?>
<widget version="1.0.7" id="...

src/index.html

<head>
      <meta charset="UTF-8">
      <title>Ionic App</title>
      <meta name="version" content="1.0.7">
      ...

gruntfile.js

    module.exports = function(grunt) {
    // Project configuration.
    grunt.initConfig({
      pkg: grunt.file.readJSON('package.json'),
      // replace version to config.xml
      'string-replace': {
        inline:{
          files: {
             'config.xml': 'config.xml',
          },
          options: {
            replacements: [{
              pattern: /widget version="([\d\D]*?)"/ig,
              replacement: 'widget version="' + '<%= pkg.version %>"'
            }]
          }
        }
      },
      // replace version to index.html
      'string-replace': {
        inline:{
          files: {
            'src/index.html': 'src/index.html',
          },
          options: {
            replacements: [{
              pattern: /name="version" content="([\d\D]*?)"/ig,
              replacement: 'name="version" content="' + '<%= pkg.version %>"'
            }]
          }
        }
      },
    });

    grunt.loadNpmTasks('grunt-string-replace');

    // Default task(s).
    grunt.registerTask('default', ['string-replace']);

    };
  1. Using Meta component, read version from index.html if plugins are not available.

    import { AppVersion } from '@ionic-native/app-version';
    import { Platform } from 'ionic-angular';
    import { Meta } from '@angular/platform-browser';
    ...
    @IonicPage({
      name: 'main'
    })
    @Component({
      selector: 'page-main',
      templateUrl: 'main.html',
    })
    export class MainPage {
      protected versionNumber: string;
      constructor(private app: AppVersion, private meta: Meta) {
        if (this.platform.is('cordova')) {
          this.appVersion.getVersionNumber().then(
            (v) => { this.versionNumber = v;},
            (err) => { 
              // PWA
              const viewport = this.meta.getTag('name=version');
              this.versionNumber = viewport.content;
            }
          );
        }else{
          // Debug
          const viewport = this.meta.getTag('name=version');
          this.versionNumber = viewport.content;
        }
      }
      ...
    
  2. Print the app version number on your html template.

    <div  class="app-version" text-center>version {{ versionNumber }}</div>
    
like image 191
pablo.nunez Avatar answered Feb 23 '23 11:02

pablo.nunez


Found proper way to do all that with using custom webpack configuration and webpack.DefinePlugin. It's working everywhere, during ionic serve as well (as I needed because I send that to API), and not only on real devices as cordova-plugin-app-version. Only place where it's not working is when you do ionic serve --devapp (issue in @ionic/angular-toolkit)

Everything below is for Ionic 4 (Angular 7):

  • add @angular-builders/custom-webpack@7 @angular-builders/dev-server@7 dev packages with yarn add @angular-builders/custom-webpack@7 @angular-builders/dev-server@7 --dev
  • need to replace architect.build and architect.serve builders in angular.json with new ones:
...
      "architect": {
        "build": {
          "builder": "@angular-builders/custom-webpack:browser",
          "options": {
            "customWebpackConfig": {
              "path": "./custom.webpack.config.js"
            },
...
...
        "serve": {
          "builder": "@angular-builders/dev-server:generic",
          "options": {
            "browserTarget": "app:build"
          },
...
  • create custom.webpack.config.js with next content:
const webpack = require('webpack');
console.log('[WEBPACK] custom.webpack.config.js is loaded');

function getAppVersion() {
  const fs = require('fs');
  const DOMParser = require('xmldom').DOMParser;

  const content = fs.readFileSync('./config.xml').toString('utf-8');
  const config = new DOMParser().parseFromString(content, 'text/xml');
  return config.getElementsByTagName('widget')[0].getAttribute('version');
}


module.exports = (config, options) => {
  config.plugins.push(
    new webpack.DefinePlugin({
      'APP_VERSION': JSON.stringify(getAppVersion()),
    }),
  );

  return config;
};
  • if all done correctly, you will see [WEBPACK] custom.webpack.config.js is loaded in terminal when running the app.
  • now global variable APP_VERSION will be injected and should be available in any place of the app. console.log('APP_VERSION', APP_VERSION);. With that you can inject other variables like that which known only during build time or adding other custom Webpack plugins.
  • you may need to add APP_VERSION definition for TypeScript into your custom-typings.d.ts as next:
// Variables injected by webpack DefinePlugin
declare const APP_VERSION: string;
like image 38
Vladimir Tolstikov Avatar answered Feb 23 '23 09:02

Vladimir Tolstikov