Skip to content
This repository has been archived by the owner on May 1, 2020. It is now read-only.

Commit

Permalink
feat(fonts): remove used fonts for cordova builds
Browse files Browse the repository at this point in the history
  • Loading branch information
adamdbradley committed Feb 8, 2017
1 parent efc4039 commit 967f784
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 10 deletions.
91 changes: 91 additions & 0 deletions src/optimization/remove-unused-fonts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { BuildContext } from '../util/interfaces';
import { join } from 'path';
import { Logger } from '../logger/logger';
import { unlinkAsync } from '../util/helpers';
import * as glob from 'glob';


export function removeUnusedFonts(context: BuildContext) {
// For webapps, we pretty much need all fonts to be available because
// the web server deployment never knows which browser/platform is
// opening the app. Additionally, webapps will request fonts on-demand,
// so having them all sit in the www/assets/fonts directory doesn’t
// hurt anything if it’s never being requested.

// However, with Cordova, the entire directory gets bundled and
// shipped in the ipa/apk, but we also know exactly which platform
// is opening the webapp. For this reason we can safely delete font
// files we know would never be opened by the platform. So app-scripts
// will continue to copy all font files over, but the cordova build
// process would delete those we know are useless and just taking up
// space. End goal is that the Cordova ipa/apk filesize is smaller.

// Font Format Support:
// ttf: http://caniuse.com/#feat=ttf
// woff: http://caniuse.com/#feat=woff
// woff2: http://caniuse.com/#feat=woff2

if (context.target === 'cordova') {
const fontsRemoved: string[] = [];
// all cordova builds should remove .eot, .svg, .ttf, and .scss files
fontsRemoved.push('*.eot');
fontsRemoved.push('*.ttf');
fontsRemoved.push('*.svg');
fontsRemoved.push('*.scss');

// all cordova builds should remove Noto-Sans
// Only windows would use Noto-Sans, and it already comes with
// a system font so it wouldn't need our own copy.
fontsRemoved.push('noto-sans*');

if (context.platform === 'android') {
// Remove all Roboto fonts. Android already comes with Roboto system
// fonts so shipping our own is unnecessary. Including roboto fonts
// is only useful for PWAs and during development.
fontsRemoved.push('roboto*');

} else if (context.platform === 'ios') {
// Keep Roboto for now. Apps built for iOS may still use Material Design,
// so in that case Roboto should be available. Later we can improve the
// CLI to be smarter and read the user’s ionic config. Also, the roboto
// fonts themselves are pretty small.
}

let filesToDelete: string[] = [];

let promises = fontsRemoved.map(pattern => {
return new Promise(resolve => {
let searchPattern = join(context.wwwDir, 'assets', 'fonts', pattern);

glob(searchPattern, (err, files) => {
if (err) {
Logger.error(`removeUnusedFonts: ${err}`);

} else {
files.forEach(f => {
if (filesToDelete.indexOf(f) === -1) {
filesToDelete.push(f);
}
});
}

resolve();
});

});
});

return Promise.all(promises).then(() => {
return unlinkAsync(filesToDelete).then(() => {
if (filesToDelete.length) {
Logger.info(`removed unused font files`);
return true;
}
return false;
});
});
}

// nothing to do here, carry on
return Promise.resolve();
}
6 changes: 5 additions & 1 deletion src/postprocess.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Logger } from './logger/logger';
import { BuildContext } from './util/interfaces';
import { purgeSourceMapsIfNeeded } from './util/source-maps';
import { removeUnusedFonts } from './optimization/remove-unused-fonts';


export function postprocess(context: BuildContext) {
Expand All @@ -15,5 +16,8 @@ export function postprocess(context: BuildContext) {


function postprocessWorker(context: BuildContext) {
return purgeSourceMapsIfNeeded(context);
return Promise.all([
purgeSourceMapsIfNeeded(context),
removeUnusedFonts(context)
]);
}
6 changes: 6 additions & 0 deletions src/util/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ export function generateContext(context?: BuildContext): BuildContext {
context.ionicAngularDir = resolve(context.ionicAngularDir || getConfigValue(context, '--ionicAngularDir', null, Constants.ENV_VAR_IONIC_ANGULAR_DIR, Constants.ENV_VAR_IONIC_ANGULAR_DIR.toLowerCase(), join(context.nodeModulesDir, Constants.IONIC_ANGULAR)));
setProcessEnvVar(Constants.ENV_VAR_IONIC_ANGULAR_DIR, context.ionicAngularDir);

context.platform = getConfigValue(context, '--platform', null, Constants.ENV_VAR_PLATFORM, null, null);
setProcessEnvVar(Constants.ENV_VAR_PLATFORM, context.platform);

context.target = getConfigValue(context, '--target', null, Constants.ENV_VAR_TARGET, null, null);
setProcessEnvVar(Constants.ENV_VAR_TARGET, context.target);

const ionicAngularEntryPoint = resolve(getConfigValue(context, '--ionicAngularEntryPoint', null, Constants.ENV_VAR_IONIC_ANGULAR_ENTRY_POINT, Constants.ENV_VAR_IONIC_ANGULAR_ENTRY_POINT.toLowerCase(), join(context.ionicAngularDir, 'index.js')));
setProcessEnvVar(Constants.ENV_VAR_IONIC_ANGULAR_ENTRY_POINT, ionicAngularEntryPoint);

Expand Down
2 changes: 2 additions & 0 deletions src/util/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export const ENV_VAR_WWW_DIR = 'IONIC_WWW_DIR';
export const ENV_VAR_BUILD_DIR = 'IONIC_BUILD_DIR';
export const ENV_VAR_NODE_MODULES_DIR = 'IONIC_NODE_MODULES_DIR';
export const ENV_VAR_IONIC_ANGULAR_DIR = 'IONIC_ANGULAR_DIR';
export const ENV_VAR_TARGET = 'IONIC_TARGET';
export const ENV_VAR_PLATFORM = 'IONIC_PLATFORM';
export const ENV_VAR_IONIC_ANGULAR_ENTRY_POINT = 'IONIC_ANGULAR_ENTRY_POINT';
export const ENV_VAR_APP_SCRIPTS_DIR = 'IONIC_APP_SCRIPTS_DIR';
export const ENV_VAR_GENERATE_SOURCE_MAP = 'IONIC_GENERATE_SOURCE_MAP';
Expand Down
28 changes: 21 additions & 7 deletions src/util/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,15 +128,29 @@ export function readAndCacheFile(filePath: string, purge: boolean = false): Prom
});
}

export function unlinkAsync(filePath: string): Promise<any> {
return new Promise((resolve, reject) => {
unlink(filePath, (err: Error) => {
if (err) {
return reject(err);
}
return resolve();
export function unlinkAsync(filePath: string|string[]): Promise<any> {
let filePaths: string[];

if (typeof filePath === 'string') {
filePaths = [filePath];
} else if (Array.isArray(filePath)) {
filePaths = filePath;
} else {
return Promise.reject('unlinkAsync, invalid filePath type');
}

let promises = filePaths.map(filePath => {
return new Promise((resolve, reject) => {
unlink(filePath, (err: Error) => {
if (err) {
return reject(err);
}
return resolve();
});
});
});

return Promise.all(promises);
}

export function rimRafAsync(directoryPath: string): Promise<null> {
Expand Down
7 changes: 6 additions & 1 deletion src/util/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ export interface BuildContext {
transpileState?: BuildState;
templateState?: BuildState;
bundleState?: BuildState;
cordova?: any;

// target examples: cordova, browser, electron
target?: string;

// platform examples: ios, android, windows
platform?: string;
}


Expand Down
2 changes: 1 addition & 1 deletion src/util/source-maps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as Constants from './constants';
import { getBooleanPropertyValue, readDirAsync, unlinkAsync } from './helpers';
import { BuildContext } from './interfaces';

export function purgeSourceMapsIfNeeded(context: BuildContext) {
export function purgeSourceMapsIfNeeded(context: BuildContext): Promise<any> {
if (getBooleanPropertyValue(Constants.ENV_VAR_GENERATE_SOURCE_MAP)) {
// keep the source maps and just return
return Promise.resolve();
Expand Down

0 comments on commit 967f784

Please sign in to comment.