3

I am currently working on a project in React and I use Typescript as language. In my project I have Webpack installed. Everything works fine but now, since we are going to production, I would like to have an easy way to store/retrieve config settings such as server URL (which is usually different between development, testing and production phases) and I got stuck. I tried to use the webpack.config.js file by adding the "externals" key:

externals: {
  'config': JSON.stringify(process.env.ENV === 'production' ? {
    serviceUrl: "https://prod.myserver.com"
  } : {
    serviceUrl: "http://localhost:8000"
  })
} 

and then try to reference the file from my tsx component files as such (take into account that the webpack.config.js is in the root folder and my components in /ClientApp/components):

import config from '../../webpack.config.js';

or

import {externals} from '../../webpack.config.js';

but I get the following error message:

'webpack.config.js' was resolved to '[PROJECT_DIR]/webpack.config.js', but '--allowJs' is not set.

Any solution/alternative to solve this issue? Thanks

1
  • Did you try this solution? If you're using typescript, just rename the file extension to .ts instead of .js. (foo.ts) . Then when you import, do not use the file extension: import ( Foo ) from '../node_modules/foo/foo'; (from coffeenexus in typescript Github issue) Commented Mar 21, 2018 at 13:36

2 Answers 2

3

My favorite way of solving the problem you're describing is to use Webpack's DefinePlugin:

The DefinePlugin allows you to create global constants which can be configured at compile time. This can be useful for allowing different behavior between development builds and release builds.

In your webpack.config.js, you can create a global constant that you can access in your application code like this:

new webpack.DefinePlugin({
    ENVIRONMENT: 'prod'
})

Then, in your TypeScript code, you can access this constant like this:

declare const ENVIRONMENT: 'prod' | 'test' | 'dev' | 'etc...';
if (ENVIRONMENT === 'prod') {
    serverUrl = 'https://example.com';
} else {
    .... 
}

Note that this method requires that you build your application separately for each environment. If instead you build your application once, and then deploy the output to multiple environments, you might consider putting this kind of configuration in a JSON file that you can swap out on a per-environment basis.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for this solution. However your last sentence means that for each environment I should change the webpack.config.js file value for ENVIRONMENT and then rebuild, right? How would you define such file?
You don't necessarily need a file - it depends a bit on how you trigger your builds. In our application, we pass a command-line argument to our build command, i.e. build --dev. We can access this value in our webpack.config.js file and change the value of the ENVIRONMENT constant appropriately.
Does it mean that everytime I need to change some config for prod I need to rebuild the whole project?
1

import config from '../../webpack.config.js' shouldn't be used in the application itself, it will cause ill effects (it is supposed to be used by Webpack) and won't provide necessary export.

externals: { 'config': ... } means that non-existing config module export is mapped to specified value.

It is supposed to be used like:

import * as config from 'config';

A more conventional approach is to provide environment constant as a global and use it in real config.ts module.

4 Comments

Thanks for your reply. I am a bit confused here, may you please provide an example? In the documentation they set process.env.NODE_ENV: JSON.Stringify('production') in the config file and then they state 'Thus, conditionals like process.env.NODE_ENV === 'production' ? '[name].[hash].bundle.js' : '[name].bundle.js' within webpack configurations do not work as expected.'
This depends on how you set process.env.NODE_ENV . Docs mean that webpack -p doesn't automatically set NODE_ENV to 'production'. You have to do this manually like webpack -p --env production, see webpack.js.org/guides/environment-variables . See github.com/webpack/webpack/issues/2537 for more details, it's quite extensive. I usually don't have this problem because I use different config files for dev and prod that don't depend on NODE_ENV and set ENV global by hand, similarly to how another answer suggests.
Thanks, may you explain how you use different configs for dev and prod? I come from ASP.NET background and I am more familiar to this approach, even for maintenance purpose, since it is quite unconveniente to rebuild the whole project everytime I need to change some config, such as service url
@CiccioMiami I use them like shown here, stackoverflow.com/a/49408284/3731501 . Some parts that depend on environment should be done at build time, like enableProdMode(). If you want to be able to change some parts dynamically, you can request them through API. But generally, this is how Angular works. If you want to change a single HTML line, you need to rebuild the project.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.