Skip to content

Instantly share code, notes, and snippets.

@tristanidoux
Last active July 25, 2024 12:08
Show Gist options
  • Save tristanidoux/892469f2c345bd6c6551eb19c705a016 to your computer and use it in GitHub Desktop.
Save tristanidoux/892469f2c345bd6c6551eb19c705a016 to your computer and use it in GitHub Desktop.
Enable ifdef-loader preprocessing with webpack 7+
Since @ngtools/webpack doesn't support preprocess chain loader, see (here)[https://github.com/nippur72/ifdef-loader/issues/4].
We use process.env to pass the ifdef loader options and patch the compiler (webpack) to read the env and parse the files.
We use a prefix 'IFDEF_' to filter the environment variables.
This is more a fix than anything else for now. A better fix would have been a PR to enable webpack to use any preprocessor
but I don't have the time right now.
diff --git a/node_modules/@ngtools/webpack/src/compiler_host.js b/node_modules/@ngtools/webpack/src/compiler_host.js
index 58d942c..a7db0be 100644
--- a/node_modules/@ngtools/webpack/src/compiler_host.js
+++ b/node_modules/@ngtools/webpack/src/compiler_host.js
@@ -11,10 +11,35 @@ const core_1 = require("@angular-devkit/core");
const fs_1 = require("fs");
const ts = require("typescript");
const utils_1 = require("./utils");
+const { parse } = require("ifdef-loader/preprocessor");
+const dotenvParseVariables = require('dotenv-parse-variables');
const dev = Math.floor(Math.random() * 10000);
+
+
+class IfdefLoaderOptions {
+ constructor(options){
+ this._options = options;
+ }
+
+ get(){
+ return this._options;
+ }
+
+ static fromProcessEnv(parsedEnv, prefix='IFDEF_'){
+ let options = {}
+ for(let k in parsedEnv){
+ if(k.startsWith(prefix)){
+ options[k.replace(prefix, '')] = parsedEnv[k]
+ }
+ }
+ return new IfdefLoaderOptions(options)
+ }
+}
+
class WebpackCompilerHost {
constructor(_options, basePath, host, cacheSourceFiles, directTemplateLoading = false, ngccProcessor, moduleResolutionCache) {
this._options = _options;
+ this._ifdefLoaderOptions = IfdefLoaderOptions.fromProcessEnv(dotenvParseVariables(process.env)).get()
this.cacheSourceFiles = cacheSourceFiles;
this.directTemplateLoading = directTemplateLoading;
this.ngccProcessor = ngccProcessor;
@@ -258,8 +283,10 @@ class WebpackCompilerHost {
if (cached) {
return cached;
}
- const content = this.readFile(fileName);
+
+ let content = this.readFile(fileName);
if (content !== undefined) {
+ if(this._ifdefLoaderOptions) content = parse(content, this._ifdefLoaderOptions, this._ifdefLoaderOptions['ifdef-verbose'] ? this._ifdefLoaderOptions['ifdef-verbose'] : true, this._ifdefLoaderOptions['ifdef-triple-slash'] ? this._ifdefLoaderOptions['ifdef-triple-slash'] : true, fileName.replace(`${this.getCurrentDirectory()}/`, ''))
const sf = ts.createSourceFile(utils_1.workaroundResolve(fileName), content, languageVersion, true);
if (this.cacheSourceFiles) {
this._sourceFileCache.set(p, sf);
/*
We pass the options to ifdef-loader using the process.env variables.
We use a prefix 'IFDEF_' to differentiate the ones for ifdef-loader
(must be the same as the one used by the webpack compiler).
*/
let opts = {
RUN_ENV: process.env.RUN_ENV,
ENABLE_XXX: process.env.ENABLE_XXX
};
for(let k in opts) process.env[`IFDEF_${k.trim()}`] = opts[k];
/*
The patch is generated & applied using patch-package.
*/
{
"scripts": {
"postinstall": "patch-package"
},
"devDependencies": {
"patch-package": "^6.2.2",
"dotenv-parse-variables": "^1.0.1"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment