webpack-config icon indicating copy to clipboard operation
webpack-config copied to clipboard

[Help Needed] Override environment variables when multiple webpack files are derived.

Open aga5tya opened this issue 8 years ago • 0 comments

I have an issue in way we reuse environment variables per config. Let me explain below

  1. There is a base.webpack.js which holds my basic config
// base.webpack.js
...
context: '[appContext]',
...
  1. I have an helper function, which sets the appContext based on if its server or client code, since they live in two separate packages.

// webpack.helper.js
import Config, { environment } from 'webpack-config'

/*  Basic helper that fetches respective config based on the path and configName.

     localWebpackPath -> e.g. /path/to/server/webpack,
     localContextPath -> e.g. /path/to/server/src
     localConfigName -> e.g. server.webpack.js
*/
export function fetchConfig(
	localWebpackPath,
	localContextPath,
	localConfigName = ''
) {

// based on who invoked set the environment variables.
environment.setAll({
		root: () => 'path/to/common/webpack/files',   // root has base.js, prod.js, dev.js
		appContext: localContextPath  // source of the target webpack to resolve modules
	})

const toExport = []

//based on the name and location fetch the config.
toExport.push(...load(localConfigName, localWebpackPath)

if (!toExport.length) {
		// if no config could be constructed throw error.
		console.error('Error: WEBPACK_CONFIG files not given')
		process.exit()
	}

return toExport

}

// Helper to require the webpack file and merge them to one incase they exported arrays.
function load(file, localpath = '') {
	try {
		wp = require(path.resolve(localpath, file)).default
	} catch (e) {
		console.error(`Error: ${file}.js not found or has errors:`) // eslint-disable-line no-console
		console.error(e) // eslint-disable-line no-console
		process.exit()
	}

	// If the config isn't already an array, add it to a new one, map over each
	// `webpack-config`, and create a 'regular' Webpack-compatible object
	return (Array.isArray(wp) ? wp : [wp]).map(config =>
		new Config().merge(config).toObject()
	)
}
...
  1. webpack.config.babel.js that invokes server.webpack.js
// client/webpack.config.babel.j
import { fetchConfig } from 'path/to/common/helpers/webpack.helper'
import path from 'path'

const localWebpackPath = path.join(__dirname, 'webpack')
const localContextPath = path.join(__dirname, 'src')
let localConfigName = 'client.webpack.js'

// just feed the path, based on the environment, helper will pick the corresponding webpack file.
export default fetchConfig(localWebpackPath, localContextPath, localConfigName)
------------------------------------------------------------------------------------------------
// server/webpack.config.babel.j
import { fetchConfig } from 'path/to/common/helpers/webpack.helper'
import path from 'path'

const localWebpackPath = path.join(__dirname, 'webpack')
const localContextPath = path.join(__dirname, 'src')
let localConfigName = 'server.webpack.js'

// just feed the path, based on the environment, helper will pick the corresponding webpack file.
export default fetchConfig(localWebpackPath, localContextPath, localConfigName)

Now i can invoke and get the files merged, but the context got from base.js to server/client webpack files always have the one injected when client webpack was invoked.

Not sure what i'm missing out here or if the recommended way to inject the environment/reusable variable is wrong. Please let me know if there is way to achieve this.

aga5tya avatar Jul 26 '17 08:07 aga5tya