Ionic PWA get version number from config.xml

不问归期 提交于 2020-01-03 17:03:07

问题


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)?


回答1:


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>
    



回答2:


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;



回答3:


I think @pablo.nunez give the right solution but for me i have to make a small modification in the Gruntfile.js to successfully change both index.html and config.xml files in the same time.

here is my modified Gruntfile.js:

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

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

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

I also integrate the fact that in IONIC 4 (Angular) project, the project id is automatically replaced before the version number in the config.xml file.




回答4:


An easier way, for those who only have a PWA in ionic 4

1. src/index.html

  <head>
  <meta charset="utf-8"/>
  <title>title App</title>
  <meta name="version" content="0.0.1">
  ....

2. page.ts

  ...
  ionViewWillEnter() {
    console.log('ionViewWillEnter');
    const aux: any = document.getElementsByTagName('META');
    // tslint:disable-next-line:prefer-for-of
    for (let i = 0; i < aux.length; i++) {
     if (aux[i].name === 'version') {
       this.versionNumber = aux[i].content;
      }
    }
  }
  ....

3. page.html

  ....
  <div *ngIf="versionNumber">
    <ion-text color="dark">
      <p>{{versionNumber}}</p>
    </ion-text>
  </div>
  ....



回答5:


Using https://github.com/whiteoctober/cordova-plugin-app-version you can access your config.xml version, from your controller or template.

Using Ionic 4, add the Cordova plugin and Ionic Native wrapper:

$ ionic cordova plugin add cordova-plugin-app-version
$ npm install @ionic-native/app-version

And add AppVersion as a provider inside of your page main.ts

import { AppVersion } from '@ionic-native/app-version';
import { Platform } from 'ionic-angular';
...
@IonicPage({
  name: 'main'
})
@Component({
  selector: 'page-main',
  templateUrl: 'main.html',
})
export class MainPage {
   protected versionNumber: string;
   constructor(private app: AppVersion) {
      if (this.platform.is('cordova')) {
         this.appVersion.getVersionNumber().then(
            (v) => { this.versionNumber = v;}
         );
      }else{
         this.versionNumber = '???';
      }
   }
   ...

Then on your .html template main.html you can print the app version number:

<div  class="app-version" text-center>version {{ versionNumber }}</div>

Also (read official doc), you can access to appName, appPackageName, appVersionCode and appVersionNumber.



来源:https://stackoverflow.com/questions/48231990/ionic-pwa-get-version-number-from-config-xml

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!