drejohnson
drejohnson

Reputation: 69

Passing environment variables in Webpack 2

Can someone help me figure out how to pass environment variables in Webpack 2 configuration? Trying to pass environment variables by using from the CONFIG function and using ./node_modules/.bin/webpack --env.ENV development set them. When using options.ENV etc. I get a TypeError: Cannot read property 'ENV' of undefined.

const fs      = require('fs');
const path    = require('path');
const webpack = require('webpack');
const assign  = require('object.assign');

// Webpack Plugins
const CopyWebpackPlugin = require('copy-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
const ForkCheckerPlugin = require('awesome-typescript-loader').ForkCheckerPlugin;

// Constants
const constants = require('./constants');

const ROOT_DIR   = constants.ROOT_DIR;   // './'
const SRC_DIR    = constants.SRC_DIR;    // './src'
const CLIENT_DIR = constants.CLIENT_DIR; // './dist/client'
const SERVER_DIR = constants.SERVER_DIR; // './dist/server'

const VENDOR_NAME = constants.VENDOR_NAME; // 'vendor'
const SERVER_NAME = constants.SERVER_NAME; // 'server'
const CLIENT_NAME = constants.CLIENT_NAME; // 'main.browser'

const SERVER_SOURCE_PATH = constants.SERVER_SOURCE_PATH; // './src/server/app.ts'
const VENDOR_SOURCE_PATH = constants.VENDOR_SOURCE_PATH; // './src/vendor.ts'
const CLIENT_SOURCE_PATH = constants.CLIENT_SOURCE_PATH; // './src/main.browser.ts'

function CONFIG(options) {
  // Webpack Constants
  const NODE_MODULES = fs.readdirSync(ROOT_DIR + '/node_modules').filter((name) => {
    return name != '.bin';
  });
  const LOADERS = [{
    test: /\.ts$/,
    loader: 'awesome-typescript',
    exclude: [
      /\.(spec|e2e)\.ts$/,
      /node_modules/
    ]
  }, {
    test: /\.html$/,
    loader: 'raw'
  }, {
    test: /\.json$/,
    loader: 'json'
  }, {
    test: /\.css$/,
    loader: 'to-string!css!postcss'
  }, {
    test: /\.(png|jpg|jpeg|gif|svg|woff|woff2)$/,
    loader: 'url',
    query: { limit: 10000 }
  }];
  const AUTOPREFIXER_BROWSERS = [
    'last 2 versions'
  ];
  const POSTCSS = function() {
    return [
      require('postcss-partial-import'),
      require('postcss-nested'),
      require('postcss-mixins'),
      require('lost')(),
      require('postcss-cssnext')({
        browsers: AUTOPREFIXER_BROWSERS
      })
    ]
  }
  const COMMOM_PLUGINS = [
    new ForkCheckerPlugin(),
    // new webpack.DefinePlugin({
    //   ENV: JSON.stringify(options.ENV),
    //   NODE_ENV: JSON.stringify(options.ENV)
    // }),
    // ...options.development ? [] : [
    //     // production
    //     new webpack.LoaderOptionsPlugin({
    //     minimize: true,
    //     debug: false
    //   }),
    //   new webpack.optimize.UglifyJsPlugin({
    //     beautify: false,
    //     mangle: {
    //       screw_ie8 : true,
    //       keep_fnames: true
    //     },
    //     compress: {
    //       screw_ie8: true,
    //       warnings: false
    //     },
    //     output: {
    //       comments: false
    //     },
    //     sourceMap: false
    //   }),
    //   new CompressionPlugin({
    //     regExp: /\.css$|\.html$|\.js$|\.map$/,
    //     threshold: 2 * 1024
    //   })
    // ]
  ];
  // Webpack Common config
  const COMMON = {
    // devtool: options.development ? "cheap-module-eval-source-map" : false,
    // cache: options.development,
    // debug: options.development,
    resolve: {
      // cache: options.development,
      root: SRC_DIR,
      extensions: ['', '.ts', '.js']
    },
    module: {
      noParse: [
        path.join(__dirname, 'zone.js', 'dist'),
        path.join(__dirname, 'angular2', 'bundles')
      ],
      loaders: LOADERS
    },
    postcss: POSTCSS,
    node: {
      global: true,
      __dirname: true,
      __filename: true,
      process: true,
      // Buffer: options.development ? false : true
    }
  };
  // Webpack Client config
  const CLIENT = {
    target: 'web',
    entry: {
      [VENDOR_NAME]: VENDOR_SOURCE_PATH,
      [CLIENT_NAME]: CLIENT_SOURCE_PATH
    },
    output: {
      path: CLIENT_DIR,
      filename: '[name].js',
      sourceMapFilename: '[name].map',
      chunkFilename: '[id].chunk.js'
    },
    plugins: [
      ...COMMOM_PLUGINS,
      new CopyWebpackPlugin([{
        from: `${SRC_DIR}/assets`,
        to: 'common/assets'
      }])
    ]
  };
  // Webpack Server config
  const SERVER = {
    target: 'node',
    entry: {
      [SERVER_NAME]: SERVER_SOURCE_PATH
    },
    output: {
      path: SERVER_DIR,
      filename: '[name].js',
      chunkFilename: '[id].' + SERVER_NAME + '.js'
    },
    plugins: [
      ...COMMOM_PLUGINS
    ],
    externals: [
      NODE_MODULES.map(function(name) { return new RegExp('^' + name) }),
    ]
  };

  const _CLIENT_CONFIG = assign(CLIENT, COMMON);
  const _SERVER_CONFIG = assign(SERVER, COMMON);
  return {
    _CLIENT_CONFIG,
    _SERVER_CONFIG
  }
}

const CLIENT_CONFIG = CONFIG()._CLIENT_CONFIG
const SERVER_CONFIG = CONFIG()._SERVER_CONFIG

// Export
module.exports = [CLIENT_CONFIG, SERVER_CONFIG];

Upvotes: 2

Views: 3033

Answers (2)

nvllkwng
nvllkwng

Reputation: 21

You need to export your config as a function for --env to work.

https://webpack.js.org/configuration/configuration-types/

In your last couple lines e.g: const CLIENT_CONFIG = CONFIG()._CLIENT_CONFIG

You're executing the CONFIG function with no params, which means you're passing "undefined" as your "options".

i.e. You need to export the function itself and let webpack execute it for you.

Upvotes: 1

Timathon
Timathon

Reputation: 298

You'll need a d.ts file under /src folder.

In your webpack.config.js:

const DefinePlugin = require('webpack/lib/DefinePlugin');

uncomment the new webpack.DefinePlugin part.

In your src folder or its sub folder, create a custome.typings.d.ts (or with other name ending with .d.ts), add a line:

declare var ENV: string;

Then you're ready to go.

Got this at line 105 in this file of angular2-webpack-starter.

Upvotes: 2

Related Questions