diff --git a/packages/@angular/cli/models/webpack-configs/common.ts b/packages/@angular/cli/models/webpack-configs/common.ts index 3bb619876df6..4a75f21e7703 100644 --- a/packages/@angular/cli/models/webpack-configs/common.ts +++ b/packages/@angular/cli/models/webpack-configs/common.ts @@ -10,7 +10,6 @@ const autoprefixer = require('autoprefixer'); const ProgressPlugin = require('webpack/lib/ProgressPlugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const ExtractTextPlugin = require('extract-text-webpack-plugin'); -const SilentError = require('silent-error'); /** * Enumerate loaders and their dependencies from this file to let the dependency validator @@ -71,25 +70,6 @@ export function getCommonConfig(wco: WebpackConfigOptions) { })); } - // process environment file replacement - if (appConfig.environments) { - if (!('source' in appConfig.environments)) { - throw new SilentError(`Environment configuration does not contain "source" entry.`); - } - if (!(buildOptions.environment in appConfig.environments)) { - throw new SilentError(`Environment "${buildOptions.environment}" does not exist.`); - } - - extraPlugins.push(new webpack.NormalModuleReplacementPlugin( - // This plugin is responsible for swapping the environment files. - // Since it takes a RegExp as first parameter, we need to escape the path. - // See https://webpack.github.io/docs/list-of-plugins.html#normalmodulereplacementplugin - new RegExp(path.resolve(appRoot, appConfig.environments['source']) - .replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&')), - path.resolve(appRoot, appConfig.environments[buildOptions.environment]) - )); - } - // process asset entries if (appConfig.assets) { extraPlugins.push(new GlobCopyWebpackPlugin({ diff --git a/packages/@angular/cli/models/webpack-configs/typescript.ts b/packages/@angular/cli/models/webpack-configs/typescript.ts index cba5a918b719..8f3b241d196b 100644 --- a/packages/@angular/cli/models/webpack-configs/typescript.ts +++ b/packages/@angular/cli/models/webpack-configs/typescript.ts @@ -1,7 +1,10 @@ +import * as fs from 'fs'; import * as path from 'path'; -import {AotPlugin} from '@ngtools/webpack'; +import {AotPlugin, AotPluginOptions} from '@ngtools/webpack'; import { WebpackConfigOptions } from '../webpack-config'; +const SilentError = require('silent-error'); + const g: any = global; const webpackLoader: string = g['angularCliIsLocal'] @@ -9,6 +12,39 @@ const webpackLoader: string = g['angularCliIsLocal'] : '@ngtools/webpack'; +function _createAotPlugin(wco: WebpackConfigOptions, options: any) { + const { appConfig, projectRoot, buildOptions } = wco; + + // Read the environment, and set it in the compiler host. + let hostOverrideFileSystem: any = {}; + // process environment file replacement + if (appConfig.environments) { + if (!('source' in appConfig.environments)) { + throw new SilentError(`Environment configuration does not contain "source" entry.`); + } + if (!(buildOptions.environment in appConfig.environments)) { + throw new SilentError(`Environment "${buildOptions.environment}" does not exist.`); + } + + const appRoot = path.resolve(projectRoot, appConfig.root); + const sourcePath = appConfig.environments['source']; + const envFile = appConfig.environments[buildOptions.environment]; + const environmentContent = fs.readFileSync(path.join(appRoot, envFile)).toString(); + + hostOverrideFileSystem = { [path.join(appRoot, sourcePath)]: environmentContent }; + } + + return new AotPlugin(Object.assign({}, { + tsConfigPath: path.resolve(projectRoot, appConfig.root, appConfig.tsconfig), + mainPath: path.join(projectRoot, appConfig.root, appConfig.main), + i18nFile: buildOptions.i18nFile, + i18nFormat: buildOptions.i18nFormat, + locale: buildOptions.locale, + hostOverrideFileSystem + }, options)); +} + + export const getNonAotConfig = function(wco: WebpackConfigOptions) { const { projectRoot, appConfig } = wco; let exclude = [ '**/*.spec.ts' ]; @@ -24,18 +60,13 @@ export const getNonAotConfig = function(wco: WebpackConfigOptions) { ] }, plugins: [ - new AotPlugin({ - tsConfigPath: path.resolve(projectRoot, appConfig.root, appConfig.tsconfig), - mainPath: path.join(projectRoot, appConfig.root, appConfig.main), - exclude: exclude, - skipCodeGeneration: true - }), + _createAotPlugin(wco, { exclude, skipCodeGeneration: true }), ] }; }; export const getAotConfig = function(wco: WebpackConfigOptions) { - const { projectRoot, buildOptions, appConfig } = wco; + const { projectRoot, appConfig } = wco; let exclude = [ '**/*.spec.ts' ]; if (appConfig.test) { exclude.push(path.join(projectRoot, appConfig.root, appConfig.test)); }; return { @@ -49,14 +80,7 @@ export const getAotConfig = function(wco: WebpackConfigOptions) { ] }, plugins: [ - new AotPlugin({ - tsConfigPath: path.resolve(projectRoot, appConfig.root, appConfig.tsconfig), - mainPath: path.join(projectRoot, appConfig.root, appConfig.main), - i18nFile: buildOptions.i18nFile, - i18nFormat: buildOptions.i18nFormat, - locale: buildOptions.locale, - exclude: exclude - }) + _createAotPlugin(wco, { exclude }) ] }; }; diff --git a/packages/@ngtools/webpack/src/plugin.ts b/packages/@ngtools/webpack/src/plugin.ts index acf7e2b2f629..8387e4c9536f 100644 --- a/packages/@ngtools/webpack/src/plugin.ts +++ b/packages/@ngtools/webpack/src/plugin.ts @@ -24,6 +24,7 @@ export interface AotPluginOptions { mainPath?: string; typeChecking?: boolean; skipCodeGeneration?: boolean; + hostOverrideFileSystem?: { [path: string]: string }; i18nFile?: string; i18nFormat?: string; locale?: string; @@ -167,6 +168,14 @@ export class AotPlugin implements Tapable { } this._compilerHost = new WebpackCompilerHost(this._compilerOptions, this._basePath); + + // Override some files in the FileSystem. + if (options.hasOwnProperty('hostOverrideFileSystem')) { + for (const filePath of Object.keys(options.hostOverrideFileSystem)) { + this._compilerHost.writeFile(filePath, options.hostOverrideFileSystem[filePath], false); + } + } + this._program = ts.createProgram( this._rootFilePath, this._compilerOptions, this._compilerHost);