Skip to content

Commit 43cb1f1

Browse files
authored
Environment Variables & NODE_PATH support (codesandbox#321)
* Add .env support and NODE_PATH * Support NODE_PATH for dynamic resolving * Only enable for CRA * Fix transpilation resolvement
1 parent f9ad7eb commit 43cb1f1

File tree

7 files changed

+51
-14
lines changed

7 files changed

+51
-14
lines changed

packages/app/src/sandbox/eval/loaders/eval.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,21 @@
22
import buildProcess from './utils/process';
33

44
/* eslint-disable no-unused-vars */
5-
export default function(code: string, require: Function, exports: Object) {
5+
export default function(
6+
code: string,
7+
require: Function,
8+
exports: Object,
9+
env: Object = {}
10+
) {
611
const module = { exports: {} };
712
const global = window;
8-
const process = buildProcess();
13+
const process = buildProcess(env);
914
window.global = global;
1015

1116
try {
12-
const newCode = `(function evaluate(require, module, exports, process, global) {${code}\n})`;
17+
const newCode = `(function evaluate(require, module, exports, process, global) {${
18+
code
19+
}\n})`;
1320
(0, eval)(newCode)(require, module, exports, process, global); // eslint-disable-line no-eval
1421

1522
// Choose either the export of __esModule or node

packages/app/src/sandbox/eval/loaders/utils/process.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ process.umask = function() {
3636
return 0;
3737
};
3838

39-
export default function build() {
39+
export default function build(env) {
40+
process.env = { NODE_ENV: 'development', ...env };
4041
return process;
4142
}

packages/app/src/sandbox/eval/manager.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export default class Manager {
5252
},
5353
},
5454
};
55+
envVariables: { [envName: string]: string } = {};
5556
preset: Preset;
5657
externals: Externals;
5758
modules: ModuleObject;
@@ -140,7 +141,6 @@ export default class Manager {
140141
this.transpiledModules[module.path].module = module;
141142

142143
const transpiledModule = new TranspiledModule(module, query);
143-
144144
this.transpiledModules[module.path].tModules[query] = transpiledModule;
145145

146146
return transpiledModule;
@@ -200,11 +200,29 @@ export default class Manager {
200200
delete this.transpiledModules[module.path];
201201
}
202202

203+
setEnvironmentVariables() {
204+
if (this.transpiledModules['/.env'] && this.preset.hasDotEnv) {
205+
const envCode = this.transpiledModules['/.env'].module.code;
206+
207+
this.envVariables = {};
208+
try {
209+
envCode.split('\n').forEach(envLine => {
210+
const [name, ...val] = envLine.split('=');
211+
212+
this.envVariables[name] = val.join('=');
213+
});
214+
} catch (e) {
215+
console.error(e);
216+
}
217+
}
218+
}
219+
203220
/**
204221
* Will transpile this module and all eventual children (requires) that go with it
205222
* @param {*} entry
206223
*/
207224
transpileModules(entry: Module) {
225+
this.setEnvironmentVariables();
208226
this.cachedPaths = {};
209227
const transpiledModule = this.getTranspiledModule(entry);
210228

@@ -290,6 +308,9 @@ export default class Manager {
290308
extensions: defaultExtensions.map(ext => '.' + ext),
291309
isFile: this.isFile,
292310
readFileSync: this.readFileSync,
311+
moduleDirectory: ['node_modules', this.envVariables.NODE_PATH].filter(
312+
x => x
313+
),
293314
});
294315

295316
this.cachedPaths[pathId] = resolvedPath;

packages/app/src/sandbox/eval/npm/fetch-npm-module.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ export default async function fetchModule(
135135
{
136136
filename: currentPath,
137137
extensions: defaultExtensions.map(ext => '.' + ext),
138+
moduleDirectory: [
139+
'node_modules',
140+
manager.envVariables.NODE_PATH,
141+
].filter(x => x),
138142
isFile: (p, c) => c(null, !!manager.transpiledModules[p] || !!meta[p]),
139143
readFile: async (p, c, cb) => {
140144
const callback = cb || c;

packages/app/src/sandbox/eval/presets/create-react-app/index.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@ import babelTranspiler from '../../transpilers/babel';
55
import jsonTranspiler from '../../transpilers/json';
66
import rawTranspiler from '../../transpilers/raw';
77

8-
const preset = new Preset('create-react-app', [
9-
'web.js',
10-
'js',
11-
'json',
12-
'web.jsx',
13-
'jsx',
14-
]);
8+
const preset = new Preset(
9+
'create-react-app',
10+
['web.js', 'js', 'json', 'web.jsx', 'jsx'],
11+
{},
12+
{ hasDotEnv: true }
13+
);
1514

1615
preset.registerTranspiler(module => /\.css$/.test(module.path), [
1716
{ transpiler: stylesTranspiler },

packages/app/src/sandbox/eval/presets/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,20 @@ export default class Preset {
3333
name: string;
3434
ignoredExtensions: Array<string>;
3535
alias: { [path: string]: string };
36+
// Whether this preset supports .env files
37+
hasDotEnv: boolean;
3638

3739
constructor(
3840
name: string,
3941
ignoredExtensions: ?Array<string>,
40-
alias: { [path: string]: string }
42+
alias: { [path: string]: string },
43+
{ hasDotEnv }: { hasDotEnv: boolean } = {}
4144
) {
4245
this.loaders = [];
4346
this.transpilers = new Set();
4447
this.name = name;
4548

49+
this.hasDotEnv = hasDotEnv || false;
4650
this.alias = alias || {};
4751
this.ignoredExtensions = ignoredExtensions || ['js', 'jsx', 'json'];
4852
}

packages/app/src/sandbox/eval/transpiled-module.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,8 @@ export default class TranspiledModule {
483483
const exports = evaluate(
484484
this.source.compiledCode,
485485
require,
486-
this.compilation.exports
486+
this.compilation.exports,
487+
manager.envVariables
487488
);
488489

489490
this.compilation.exports = exports;

0 commit comments

Comments
 (0)