17

I'm writing an isomorphic Key Value Store with webpack.

This is currently my approach to load the libraries, which obviously doesn't work, because webpack wants to resolve both require. Whats' the right approach?

var db = null;

if (typeof window === 'undefined') {
    // node context
    db = require('level');
} else {
    // browser context
    db = require('gazel');
}

I know, that you can provide a target to webpack. But I have no idea how to use that.

Thanks!

vardump
  • 658
  • 1
  • 10
  • 17
  • 1
    Check out this [SO question](http://stackoverflow.com/questions/28572380/conditional-build-based-on-environment-using-webpack) which deals with conditional build based on environment. – r0dney Jul 06 '15 at 15:54
  • Thanks, indeed this worked :) I set a __BROWSER__ plugin in webpack and now I'm using normal nodejs (node file.js) and webpack for the browser build – vardump Jul 13 '15 at 16:57

2 Answers2

16

I think resolve.alias would work for you. You would set db module to point at level or gazel depending on which build you are creating.

Juho Vepsäläinen
  • 26,573
  • 12
  • 79
  • 105
11

webpack.config.js

module.exports = {
plugins: [
    new webpack.DefinePlugin({
        "process.env": {
            BROWSER: JSON.stringify(true)
        }
    })
]}

your-universal.js

var db = null;
if (!process.env.BROWSER) {
    // node context
    db = require('level');
} else {
    // browser context
    db = require('gazel');
}
Lonelydatum
  • 1,148
  • 1
  • 13
  • 26
  • 5
    Just a minor point, but why do so many people have this JSON.stringify(true) crap? This is literally (literally) equivalent to "true"... – Jason Boyd Dec 10 '16 at 17:54
  • 3
    @JasonBoyd I wonder that myself, I think it started as a way to be make people pay attention because with string values people would easily misunderstand the need for the extra quotes in `'process.env.NODE_ENV': '"production"'`. They might mistakenly remove them, especially in the case of `"true"`. – Andy Dec 13 '16 at 08:52
  • 4
    The extra quotes are necessary because the value string is directly interpolated into the source code in place of the reference. With DefinePlugin configured to substitute `'process.env.NODE_ENV': '"production"'`, the code `if (process.env.NODE_ENV == "production") { ... }` becomes `if ("production" == "production") { ... }`. Without the extra quotes, it becomes `if (production == "production") { ... }`, which uses an undeclared variable. – pvande Mar 28 '17 at 16:55
  • 1
    Careful using this approach because if, for example, if 'level' is a purely nodeJS (server) module, webpack will fail to compile your code. Best to use the first answer to 'stub' any purely server side required modules. – GabiDi Apr 04 '17 at 18:18
  • 3
    Shouldn't this be `if(process.env.BROWSER === 'true') {}` ? – Danny R Apr 18 '17 at 18:22
  • Also I recommend *NOT* defining something in `process.env`. First of all - why? It's not an environment variable which is what `process.env` is for. And secondly it can screw with the actual environment variables (like, all of them). Just use a unique global variable name instead. – Timmmm Apr 30 '20 at 07:36
  • @Timmmm A major reason to use a .env that way is that you generally don't check them into VC, so they're a good way to add API keys and other secrets that don't belong in your vc. In production environments actual environment variables are often used to inject these values because it can be convenient for scripts and cloud systems. – theaceofthespade Dec 11 '20 at 00:00
  • @theaceofthespace In this case the variable is set in `webpack.config.js` which is checked in to version control so that is irrelevant. – Timmmm Dec 11 '20 at 13:49