问题
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.
On package.json set the app version.
{ "name": "my-app", "version": "1.0.7", ...
Install grunt on your project.
$> npm install grunt --save-dev $> npm install grunt-string-replace --save-dev
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']);
};
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; } } ...
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