Skip to content

Commit

Permalink
feat(stark-build): add support for environment variables at runtime (…
Browse files Browse the repository at this point in the history
…importing environment.ts file) and at compilation time (using webpack Define plugin)

ISSUES CLOSED: #50
  • Loading branch information
christophercr committed Jun 21, 2018
1 parent d93d64b commit 8ff7e35
Show file tree
Hide file tree
Showing 41 changed files with 229 additions and 247 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@
"update:starter": "npm run clean:starter && npm run install:starter"
},
"lint-staged": {
"*.{css,js,json,pcss,scss,ts}": [
"*.{css,js,json,md,pcss,scss,ts}": [
"prettier --write",
"git add"
]
Expand Down
45 changes: 13 additions & 32 deletions packages/stark-build/config/build-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,24 @@ const fs = require("fs");
const helpers = require("./helpers");
const ngCliUtils = require("./ng-cli-utils");

const _getAngularCliAppConfig = getAngularCliAppConfig();
const angularCliAppConfig = ngCliUtils.getAngularCliAppConfig(helpers.root("angular.json"));
const ANGULAR_APP_CONFIG = {
config: _getAngularCliAppConfig,
deployUrl: _getAngularCliAppConfig.architect.build.options.deployUrl || "",
baseHref: _getAngularCliAppConfig.architect.build.options.baseHref || "/",
sourceRoot: _getAngularCliAppConfig.sourceRoot,
outputPath: _getAngularCliAppConfig.architect.build.options.outputPath
config: angularCliAppConfig,
deployUrl: angularCliAppConfig.architect.build.options.deployUrl || "",
baseHref: angularCliAppConfig.architect.build.options.baseHref || "/",
sourceRoot: angularCliAppConfig.sourceRoot,
outputPath: angularCliAppConfig.architect.build.options.outputPath
};

const DEFAULT_METADATA = {
title: "Stark Application by @NationalBankBelgium",
baseUrl: "/",
isDevServer: helpers.isWebpackDevServer(),
TITLE: "Stark Application by @NationalBankBelgium",
BASE_URL: "/",
IS_DEV_SERVER: helpers.isWebpackDevServer(),
HMR: helpers.hasProcessFlag("hot"),
AOT: process.env.BUILD_AOT || helpers.hasNpmFlag("aot"),
E2E: !!process.env.BUILD_E2E,
WATCH: helpers.hasProcessFlag("watch"),
tsConfigPath: ANGULAR_APP_CONFIG.config.architect.build.options.tsConfig,
TS_CONFIG_PATH: ANGULAR_APP_CONFIG.config.architect.build.options.tsConfig,
environment: ""
};

Expand Down Expand Up @@ -76,11 +76,11 @@ function getEnvironmentFile(environment) {
* Read the tsconfig to determine if we should prefer ES2015 modules.
* Load rxjs path aliases.
* https://github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md#build-and-treeshaking
* @param supportES2015 Set to true when the output of typescript is >= ES6
* @param shouldSupportES2015 Set to true when the output of typescript is >= ES6
*/
function rxjsAlias(supportES2015) {
function rxjsAlias(shouldSupportES2015) {
try {
const rxjsPathMappingImport = supportES2015 ? "rxjs/_esm2015/path-mapping" : "rxjs/_esm5/path-mapping";
const rxjsPathMappingImport = shouldSupportES2015 ? "rxjs/_esm2015/path-mapping" : "rxjs/_esm5/path-mapping";
const rxPaths = require(rxjsPathMappingImport);
return rxPaths();
} catch (e) {
Expand Down Expand Up @@ -143,25 +143,6 @@ function getApplicationAssetsConfig() {
return [];
}

function getAngularCliAppConfig() {
const applicationAngularCliConfigPath = helpers.root("angular.json");
if (fs.existsSync(applicationAngularCliConfigPath)) {
const angularCliConfig = require(applicationAngularCliConfigPath);
const cliConfig = ngCliUtils.validateAngularCLIConfig(angularCliConfig);
if (cliConfig) {
if (cliConfig.defaultProject && cliConfig.projects[cliConfig.defaultProject]) {
return cliConfig.projects[cliConfig.defaultProject];
} else {
throw new Error("Angular-cli config apps is wrong. Please adapt it to follow Angular CLI way.");
}
} else {
throw new Error("Parsing " + applicationAngularCliConfigPath + " failed. Ensure the file is valid JSON.");
}
} else {
throw new Error("angular.json is not present. Please add this at the root your project because stark-build needs this.");
}
}

/**
* Return copyWebpack config based on angular cli assets declaration
*
Expand Down
27 changes: 24 additions & 3 deletions packages/stark-build/config/ng-cli-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ const fs = require("fs");
const cliUtilConfig = require("@angular/cli/utilities/config");
const { formatDiagnostics } = require("@angular/compiler-cli/ngtools2");

function isDirectory(path) {
function isDirectory(pathToCheck) {
try {
return fs.statSync(path).isDirectory();
return fs.statSync(pathToCheck).isDirectory();
} catch (_) {
return false;
}
Expand All @@ -15,6 +15,26 @@ function getDirectoriesNames(source) {
return fs.readdirSync(source).filter(name => isDirectory(path.join(source, name)));
}

function getAngularCliAppConfig(angularCliAppConfigPath) {
if (fs.existsSync(angularCliAppConfigPath)) {
const angularCliConfig = require(angularCliAppConfigPath);
const cliConfig = validateAngularCLIConfig(angularCliConfig);
if (cliConfig) {
if (cliConfig.defaultProject && cliConfig.projects[cliConfig.defaultProject]) {
return cliConfig.projects[cliConfig.defaultProject];
} else {
throw new Error(
"The configuration of the default project in angular.json is wrong. Please adapt it to follow Angular CLI guidelines."
);
}
} else {
throw new Error("Parsing " + angularCliAppConfigPath + " failed. Please make sure that the file is valid JSON.");
}
} else {
throw new Error("angular.json is not present. Please add this at the root your project because stark-build needs this.");
}
}

/**
* Validate passed angular cli config based on schema: @angular/cli/lib/config/schema.json
* If the serialized file is equal to the passed json, return the serialized config.
Expand Down Expand Up @@ -43,7 +63,8 @@ function getWorkspace() {
return cliUtilConfig.getWorkspace();
}

exports.getAngularCliAppConfig = getAngularCliAppConfig;
exports.getDirectoriesNames = getDirectoriesNames;
exports.getWorkspace = getWorkspace;
exports.isDirectory = isDirectory;
exports.validateAngularCLIConfig = validateAngularCLIConfig;
exports.getWorkspace = getWorkspace;
47 changes: 25 additions & 22 deletions packages/stark-build/config/webpack.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const commonData = require("./webpack.common-data.js"); // common configuration
const CopyWebpackPlugin = require("copy-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const BaseHrefWebpackPlugin = require("base-href-webpack-plugin").BaseHrefWebpackPlugin;
const DefinePlugin = require("webpack/lib/DefinePlugin");
// const InlineManifestWebpackPlugin = require("inline-manifest-webpack-plugin");
// const ScriptExtHtmlWebpackPlugin = require("script-ext-html-webpack-plugin");
const { AngularCompilerPlugin } = require("@ngtools/webpack");
Expand All @@ -30,14 +31,14 @@ const buildUtils = require("./build-utils");
module.exports = options => {
const isProd = options.ENV === "production";
const METADATA = Object.assign({}, buildUtils.DEFAULT_METADATA, options.metadata || {});
const supportES2015 = buildUtils.supportES2015(METADATA.tsConfigPath);
const supportES2015 = buildUtils.supportES2015(METADATA.TS_CONFIG_PATH);

const entry = {
polyfills: "./src/polyfills.browser.ts",
main: "./src/main.browser.ts"
};

const tsConfigApp = buildUtils.readTsConfig(helpers.root(METADATA.tsConfigPath));
const tsConfigApp = buildUtils.readTsConfig(helpers.root(METADATA.TS_CONFIG_PATH));

const defaultNgcOptions = {
generateCodeForLibraries: true,
Expand Down Expand Up @@ -342,24 +343,26 @@ module.exports = options => {
* See: http://webpack.github.io/docs/configuration.html#plugins
*/
plugins: [
// /**
// * Plugin: DefinePlugin
// * Description: Define free variables.
// * Useful for having development builds with debug logging or adding global constants.
// *
// * Environment helpers
// *
// * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin
// */
// // NOTE: when adding more properties make sure you include them in custom-typings.d.ts
// new DefinePlugin({
// 'ENV': JSON.stringify(METADATA.ENV),
// 'HMR': METADATA.HMR,
// 'AOT': METADATA.AOT,
// 'process.env.ENV': JSON.stringify(METADATA.ENV),
// 'process.env.NODE_ENV': JSON.stringify(METADATA.ENV),
// 'process.env.HMR': METADATA.HMR
// }),
/**
* Plugin: DefinePlugin
* Description: Define free variables.
* Useful for having development builds with debug logging or adding global constants.
*
* Environment helpers
* IMPORTANT: when adding more properties make sure you include them in typings/environment.d.ts
*
* See: https://webpack.js.org/plugins/define-plugin
*/
new DefinePlugin({
ENV: JSON.stringify(METADATA.ENV),
HMR: METADATA.HMR,
AOT: METADATA.AOT, // TODO: is this needed?
"process.env": {
ENV: JSON.stringify(METADATA.ENV),
NODE_ENV: JSON.stringify(METADATA.ENV),
HMR: METADATA.HMR
}
}),

/**
* Plugin: AngularNamedLazyChunksWebpackPlugin
Expand Down Expand Up @@ -441,7 +444,7 @@ module.exports = options => {
*/
new HtmlWebpackPlugin({
template: "src/index.html",
title: METADATA.title,
title: METADATA.TITLE,
chunksSortMode: function(a, b) {
const entryPoints = ["inline", "polyfills", "sw-register", "styles", "vendor", "main"];
return entryPoints.indexOf(a.names[0]) - entryPoints.indexOf(b.names[0]);
Expand Down Expand Up @@ -493,7 +496,7 @@ module.exports = options => {
},
platform: 0, // 0 = browser, 1 = server
compilerOptions: appNgcOptions,
tsConfigPath: METADATA.tsConfigPath
tsConfigPath: METADATA.TS_CONFIG_PATH
})

/**
Expand Down
8 changes: 3 additions & 5 deletions packages/stark-build/config/webpack.dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,16 @@ const WebpackMonitor = require("webpack-monitor");
* See: https://webpack.js.org/configuration/
*/
module.exports = function(env) {
// for the content of the env parameter see here : https://webpack.js.org/api/cli/#environment-options
const ENV = (process.env.ENV = process.env.NODE_ENV = "development");
const HOST = process.env.HOST || "localhost";
const PORT = process.env.PORT || 3000;
let MONITOR = false;
// for the content of the env parameter see here : https://webpack.js.org/api/cli/#environment-options
if (env && typeof env.monitor !== "undefined") {
MONITOR = env.monitor;
}

const METADATA = Object.assign({}, buildUtils.DEFAULT_METADATA, {
HOST: HOST,
PORT: PORT,
HOST: process.env.HOST || "localhost",
PORT: process.env.PORT || 3000,
ENV: ENV,
HMR: helpers.hasProcessFlag("hot"),
environment: helpers.hasProcessFlag("hot") ? "hmr" : "dev"
Expand Down
11 changes: 5 additions & 6 deletions packages/stark-build/config/webpack.prod.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,14 @@ function getUglifyOptions(supportES2015) {

module.exports = function() {
const ENV = (process.env.NODE_ENV = process.env.ENV = "production");
const supportES2015 = buildUtils.supportES2015(buildUtils.DEFAULT_METADATA.tsConfigPath);
const METADATA = Object.assign({}, buildUtils.DEFAULT_METADATA, {
host: process.env.HOST || "localhost",
port: process.env.PORT || 8080,
HOST: process.env.HOST || "localhost",
PORT: process.env.PORT || 8080,
ENV: ENV,
HMR: false
HMR: false,
environment: buildUtils.DEFAULT_METADATA.E2E ? "e2e.prod" : "prod"
});

METADATA.environment = METADATA.E2E ? "e2e.prod" : "prod";
const supportES2015 = buildUtils.supportES2015(METADATA.TS_CONFIG_PATH);

return webpackMerge(commonConfig({ ENV: ENV, metadata: METADATA }), {
/**
Expand Down
1 change: 1 addition & 0 deletions packages/stark-build/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"node": ">=6.11.0",
"npm": ">=5.3.0"
},
"types": "typings/index.d.ts",
"dependencies": {
"@angular-devkit/build-angular": "0.6.8",
"@angular-devkit/build-optimizer": "0.6.8",
Expand Down
2 changes: 1 addition & 1 deletion packages/stark-build/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"target": "es5",
"outDir": "./dist",
"baseUrl": "./src",
"rootDirs": ["./src", "./config"],
"rootDirs": ["./src", "./config", "./typings"],
"lib": ["dom", "dom.iterable", "es2017"],
"typeRoots": ["./node_modules/@types"],
"paths": {},
Expand Down
3 changes: 3 additions & 0 deletions packages/stark-build/typings/environment/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Extra variables that live on Global that will be replaced by webpack DefinePlugin
declare let ENV: "development" | "production";
declare let HMR: boolean;
3 changes: 3 additions & 0 deletions packages/stark-build/typings/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/* tslint:disable:no-import-side-effect */
import "./environment";
/* tslint:enable */
1 change: 1 addition & 0 deletions packages/stark-core/src/common.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./common/environment";
export * from "./common/error";
export * from "./common/routes";
export * from "./common/store";
Expand Down
31 changes: 31 additions & 0 deletions packages/stark-core/src/common/environment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { NgModuleRef } from "@angular/core";

/**
* Interface to be implemented by all environments
*/
export interface StarkEnvironment {
/**
* Whether the current environment is production
*/
production: boolean;
/**
* Whether the current environment has Hot Module Replacement enabled
*/
hmr: boolean;
/**
* Array of providers to be included in this environment
*/
ENV_PROVIDERS: any[];
/**
* Function to modify/decorate the NgModule Instance created by Angular for a given platform.
* Useful to enable/disable some Angular specifics such as the debug tools.
*/
decorateModuleRef(modRef: NgModuleRef<any>): NgModuleRef<any>;
}

// create an empty dummy environment constant (the actual values will be defined in the client app)
const dummyEnv: Partial<StarkEnvironment> = {};

// export the dummy constant as "environment" to be able to mimic the way it should be imported in the client app
// like this: import { environment } from "environments/environment";
export const environment: StarkEnvironment = <StarkEnvironment>dummyEnv;
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,13 @@ export class StarkApplicationConfigImpl implements StarkApplicationConfig {

public constructor() {
// Default values
// FIXME: DEVELOPMENT env variable?
/*if (DEVELOPMENT) {
if (ENV === "development") {
this.loggingFlushPersistSize = 500;
} else {*/
this.loggingFlushPersistSize = 15;
// }
console.log("CCR==========> this line should be kept only in DEV");
} else {
this.loggingFlushPersistSize = 15;
console.log("CCR==========> this line should be kept only in PROD");
}

this.loggingFlushDisabled = false;
this.loggingFlushResourceName = "logging";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,10 @@ export class StarkHttpRequestBuilderImpl<T extends StarkResource> implements Sta

// Add custom QueryParameter so json-server can add collection metadata to the mock response
// See: https://jira.prd.nbb/browse/NG-1335
// FIXME: DEVELOPMENT env variable?
// if (DEVELOPMENT) {
builder.addQueryParameter("mockCollectionRequest", "true");
// }
if (ENV === "development") {
builder.addQueryParameter("mockCollectionRequest", "true");
console.log("CCR==========> this line should be kept only in DEV");
}

return builder;
}
Expand Down Expand Up @@ -200,10 +200,10 @@ export class StarkHttpRequestBuilderImpl<T extends StarkResource> implements Sta

// Add custom QueryParameter so json-server can add collection metadata to the mock response
// See: https://jira.prd.nbb/browse/NG-1335
// FIXME: DEVELOPMENT env variable?
// if (DEVELOPMENT) {
builder.addQueryParameter("mockCollectionRequest", "true");
// }
if (ENV === "development") {
builder.addQueryParameter("mockCollectionRequest", "true");
console.log("CCR==========> this line should be kept only in DEV");
}

return builder;
}
Expand Down
8 changes: 4 additions & 4 deletions packages/stark-core/src/modules/http/services/http.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ export class StarkHttpServiceImpl<P extends StarkResource> implements StarkHttpS
request = this.removeETagFromRequestItem(request);

// NG-1346: fake pre-authentication support
// FIXME: DEVELOPMENT env variable?
if (/*DEVELOPMENT &&*/ request.backend.fakePreAuthenticationEnabled) {
if (ENV === "development" && request.backend.fakePreAuthenticationEnabled) {
request = this.addFakePreAuthenticationHeaders(request);
console.log("CCR==========> this line should be kept only in DEV");
}

// NG-117: add correlation identifier
Expand Down Expand Up @@ -97,9 +97,9 @@ export class StarkHttpServiceImpl<P extends StarkResource> implements StarkHttpS

public executeCollectionRequest(request: StarkHttpRequest<P>): Observable<StarkCollectionResponseWrapper<P>> {
// NG-1346: fake pre-authentication support
// FIXME: DEVELOPMENT env variable?
if (/*DEVELOPMENT &&*/ request.backend.fakePreAuthenticationEnabled) {
if (ENV === "development" && request.backend.fakePreAuthenticationEnabled) {
request = this.addFakePreAuthenticationHeaders(request);
console.log("CCR==========> this line should be kept only in DEV");
}

// NG-117: add correlation identifier
Expand Down
Loading

0 comments on commit 8ff7e35

Please sign in to comment.