angular-cli-envvars icon indicating copy to clipboard operation
angular-cli-envvars copied to clipboard

Angular 6 - cannot import require 'fs'

Open rmcsharry opened this issue 5 years ago • 3 comments

Thanks for the great article on medium, which I used for Angular 2 to 5....but now in Angular 6, you can no longer import 'fs'. You can read more about that here.

Note there are many posts that say you can still import 'fs' in a typescript file by changing your tsconfig.ts compiler options to the module setting of 'commonjs':

"compilerOptions": {
  "module": "commonjs",
  ...
}

So that does work, and if your use case is simple that is all you need to do.

However you might be doing other stuff that might not work - for me, I want to read the package.json and extract the app name and app version, which in theory should work since from Typescript v2.9 it now supports reading json files

I tried but could not get that to work.

However, you can just recode this idea using plain javascript. Here is my example (I have simplified so I am not using yargs here to process arguments).

const fs = require('fs'); // needed to use WriteFile
const colors = require('colors/safe') // to color the logging clearly

// get version and name from package.json
const appVer = require('./package.json').version;
const appName = require('./package.json').name;

// the file we will write the settings to
const targetPath = `./src/environments/environment.prod.ts`;

// This will load the env vars defined in the local .env file, which should
// be added to .gitignore. That means .env will not and should not be present 
// for other environments, it will use the env vars set on the OS 
// (or for Heroku, using Heroku env var settings)
require('dotenv').config();

const envConfigFile = `
export const environment = {
  version: "${appVer}",
  name: "${appName}",
  production: true,
  token_auth_config: {
    apiHost: "${process.env.API_HOST}",
    apiBase: "${process.env.API_BASE}",
    registerAccountCallback: "${process.env.REGISTER_ACCOUNT_CALLBACK}",
    resetPasswordCallback: "${process.env.RESET_PASSWORD_CALLBACK}",
    signInRedirect: "login"
  }
};
`
fs.writeFile(targetPath, envConfigFile, function (err) {
  if (err) console.log(colors.red(err));
  console.log(colors.green(`\nOutput generated at ${targetPath}`));
});

Then you can use node, no need for ts-node, to execute it:

node set-env.js

More info in the answer from Rzassar here.

If you have to manage multiple environments, this is also worth reading.

rmcsharry avatar Oct 09 '18 20:10 rmcsharry

Well I ran ts-node with your code in a set-env.ts file and this worked well. To avoid conflicts with Angular's TS config I would advise to put your tool (with its own tsconfig.json and package.json) in a separate cli directory sibling to src (so that Angular CLI won't try to compile your tool when compiling its src files).

As an extra step, you can ask your product package.json target to call your tool cli/package.json ones, like:

"scripts": {
  "build:production": "cd cli && npm run build:production",`
}

Javarome avatar Jan 25 '19 13:01 Javarome

Thanks thanks thanks for this, but... I have the same problem with 'fs' , I am not sure at all to try @Javarome 's idea because I have mi app deployed in heroku, Does somebody know another way to fix this... or if someone can explain me better the previous idea, plsss :(

JrogeT avatar Apr 28 '20 03:04 JrogeT

@JrogeT this is so long ago for me that I have forgotten it (and no longer have access to the code). Sorry, cannot help. :(

rmcsharry avatar Apr 28 '20 12:04 rmcsharry