Skip to content

Commit e05cb19

Browse files
author
Artem Sapegin
committed
Refactor: Improve default/named module resolution in example
1 parent e032df5 commit e05cb19

File tree

7 files changed

+61
-68
lines changed

7 files changed

+61
-68
lines changed

src/client/utils/__tests__/compileCode.spec.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ var bar = baz.bar;"
1414

1515
test('transform imports to require()', () => {
1616
const result = compileCode(`import foo from 'bar'`, compilerConfig);
17-
expect(result).toMatchInlineSnapshot(`"const foo = require('bar');"`);
17+
expect(result).toMatchInlineSnapshot(`
18+
"const bar$0 = require('bar');
19+
const foo = bar$0.default || bar$0;"
20+
`);
1821
});
1922

2023
test('transform imports to require() in front of JSX', () => {
@@ -27,8 +30,10 @@ import Button from 'button';
2730
);
2831
expect(result).toMatchInlineSnapshot(`
2932
"
30-
const foo = require('bar');
31-
const Button = require('button');
33+
const bar$0 = require('bar');
34+
const foo = bar$0.default || bar$0;
35+
const button$0 = require('button');
36+
const Button = button$0.default || button$0;
3237
React.createElement( Button, null )"
3338
`);
3439
});

src/client/utils/__tests__/transpileImports.spec.js

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ import transpileImports from '../transpileImports';
33
describe('transpileImports', () => {
44
test('transpile default imports', () => {
55
const result = transpileImports(`import B from 'cat'`);
6-
expect(result).toMatchInlineSnapshot(`"const B = require('cat');"`);
6+
expect(result).toMatchInlineSnapshot(`
7+
"const cat$0 = require('cat');
8+
const B = cat$0.default || cat$0;"
9+
`);
710
});
811

912
test('transpile named imports', () => {
@@ -17,8 +20,9 @@ const B = cat$0.B;"
1720
test('transpile mixed imports', () => {
1821
const result = transpileImports(`import A, {B} from 'cat'`);
1922
expect(result).toMatchInlineSnapshot(`
20-
"const A = require('cat');
21-
const B = A.B;"
23+
"const cat$0 = require('cat');
24+
const A = cat$0.default || cat$0;
25+
const B = cat$0.B;"
2226
`);
2327
});
2428

@@ -40,11 +44,15 @@ import E from 'snake'
4044
*/
4145
require('dog');
4246
/* Less important comments */
43-
const B = require('cat');
47+
const cat$0 = require('cat');
48+
const B = cat$0.default || cat$0;
4449
// Absolutely not important comment
45-
const C = require('capybara');
46-
const D = require('hamster'); // One more comment
47-
const E = require('snake');
50+
const capybara$0 = require('capybara');
51+
const C = capybara$0.default || capybara$0;
52+
const hamster$0 = require('hamster');
53+
const D = hamster$0.default || hamster$0; // One more comment
54+
const snake$0 = require('snake');
55+
const E = snake$0.default || snake$0;
4856
"
4957
`);
5058
});

src/client/utils/rewriteImports.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,23 @@ function alias(key) {
1515

1616
function generate(keys, dep, base, fn) {
1717
const tmp =
18-
base ||
1918
dep
2019
.split('/')
2120
.pop()
2221
.replace(/\W/g, '_') +
23-
'$' +
24-
num++; // uniqueness
25-
const name = base || alias(tmp).name;
22+
'$' +
23+
num++; // uniqueness
24+
const name = alias(tmp).name;
2625

2726
dep = `${fn}('${dep}')`;
2827

2928
let obj;
3029
let out = `const ${name} = ${dep};`;
3130

31+
if (base) {
32+
out += `\nconst ${base} = ${tmp}.default || ${tmp};`;
33+
}
34+
3235
keys.forEach(key => {
3336
obj = alias(key);
3437
out += `\nconst ${obj.name} = ${tmp}.${obj.key};`;

src/loaders/__tests__/examples-loader.spec.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,9 @@ it('should prepend example code with React require()', () => {
180180

181181
expect(result).toBeTruthy();
182182
expect(() => new Function(result)).not.toThrowError(SyntaxError);
183-
expect(result).toMatch(`const React = require('react');`);
183+
expect(result).toMatch(
184+
`const React$0 = require('react');\\nconst React = React$0.default || React$0;`
185+
);
184186
});
185187

186188
it('should prepend example code with component require()', () => {
@@ -195,7 +197,9 @@ it('should prepend example code with component require()', () => {
195197

196198
expect(result).toBeTruthy();
197199
expect(() => new Function(result)).not.toThrowError(SyntaxError);
198-
expect(result).toMatch(`const FooComponent = require('../foo.js');`);
200+
expect(result).toMatch(
201+
`const FooComponent$0 = require('../foo.js');\\nconst FooComponent = FooComponent$0.default || FooComponent$0;`
202+
);
199203
});
200204

201205
it('should allow explicit import of React and component module', () => {
@@ -213,8 +217,12 @@ it('should allow explicit import of React and component module', () => {
213217

214218
expect(result).toBeTruthy();
215219
expect(() => new Function(result)).not.toThrowError(SyntaxError);
216-
expect(result).toMatch(`const React = require('react');`);
217-
expect(result).toMatch(`const FooComponent = require('../foo.js');`);
220+
expect(result).toMatch(
221+
`const React$0 = require('react');\\nconst React = React$0.default || React$0;`
222+
);
223+
expect(result).toMatch(
224+
`const FooComponent$0 = require('../foo.js');\\nconst FooComponent = FooComponent$0.default || FooComponent$0;`
225+
);
218226
});
219227

220228
it('should works for any Markdown file, without a current component', () => {
@@ -232,6 +240,8 @@ it('should works for any Markdown file, without a current component', () => {
232240

233241
expect(result).toBeTruthy();
234242
expect(() => new Function(result)).not.toThrowError(SyntaxError);
235-
expect(result).toMatch(`const React = require('react');`);
243+
expect(result).toMatch(
244+
`const React$0 = require('react');\\nconst React = React$0.default || React$0;`
245+
);
236246
expect(result).not.toMatch('undefined');
237247
});

src/loaders/examples-loader.js

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import path from 'path';
22
import filter from 'lodash/filter';
33
import map from 'lodash/map';
44
import values from 'lodash/values';
5+
import flatten from 'lodash/flatten';
56
import loaderUtils from 'loader-utils';
67
import { generate } from 'escodegen';
78
import toAst from 'to-ast';
@@ -71,10 +72,19 @@ export default function examplesLoader(source) {
7172

7273
// Require context modules so they are available in an example
7374
const requireContextCode = b.program(
74-
// const name = require(path)
75-
map(fullContext, (requireRequest, name) =>
76-
b.variableDeclaration('const', [
77-
b.variableDeclarator(b.identifier(name), requireIt(requireRequest).toAST()),
75+
flatten(
76+
map(fullContext, (requireRequest, name) => [
77+
// const name$0 = require(path);
78+
b.variableDeclaration('const', [
79+
b.variableDeclarator(b.identifier(`${name}$0`), requireIt(requireRequest).toAST()),
80+
]),
81+
// const name = name$0.default || name$0;
82+
b.variableDeclaration('const', [
83+
b.variableDeclarator(
84+
b.identifier(name),
85+
b.logicalExpression('||', b.identifier(`${name}$0.default`), b.identifier(`${name}$0`))
86+
),
87+
]),
7888
])
7989
)
8090
);

src/loaders/utils/client/__tests__/requireInRuntime.spec.js

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,6 @@ import requireInRuntime from '../requireInRuntime';
22

33
const map = {
44
a: () => 'a',
5-
b: () => 'b',
6-
c: {
7-
default: () => 'c.default',
8-
},
9-
d: {
10-
named: () => 'd.named',
11-
},
12-
e: {
13-
default: () => 'e.default',
14-
named: () => 'e.named',
15-
},
165
};
176

187
test('return a module from the map', () => {
@@ -21,27 +10,6 @@ test('return a module from the map', () => {
2110
expect(result()).toBe('a');
2211
});
2312

24-
test('return a default export', () => {
25-
const result = requireInRuntime(map, 'c');
26-
expect(result).toBeDefined();
27-
expect(result()).toBe('c.default');
28-
});
29-
30-
test('return a named export', () => {
31-
const result = requireInRuntime(map, 'd');
32-
expect(result).toBeDefined();
33-
expect(result.named).toBeDefined();
34-
expect(result.named()).toBe('d.named');
35-
});
36-
37-
test('return both a default and a named exports', () => {
38-
const result = requireInRuntime(map, 'e');
39-
expect(result).toBeDefined();
40-
expect(result.named).toBeDefined();
41-
expect(result()).toBe('e.default');
42-
expect(result.named()).toBe('e.named');
43-
});
44-
4513
test('throw if module is not in the map', () => {
4614
const fn = () => requireInRuntime(map, 'pizza');
4715
expect(fn).toThrowError('require() statements can be added');

src/loaders/utils/client/requireInRuntime.js

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,6 @@
33
type Module = { [name: string]: any } | (() => any);
44
type RequireMap = { [filepath: string]: Module };
55

6-
const getModule = (mod: Module): Module => {
7-
if (!mod.default) {
8-
return mod;
9-
}
10-
11-
// Merge named exports with default export to allow requiring like this:
12-
// const a, {b} = requireInRuntime('a')
13-
const merged = mod.default;
14-
Object.assign(merged, mod);
15-
return merged;
16-
};
17-
186
/**
197
* Return module from a given map (like {react: require('react')}) or throw.
208
* We alllow to require modules only from Markdown examples (won’t work dinamically becasue we need to know all required
@@ -26,5 +14,6 @@ export default function requireInRuntime(requireMap: RequireMap, filepath: strin
2614
`import or require() statements can be added only by editing a Markdown example file: ${filepath}`
2715
);
2816
}
29-
return getModule(requireMap[filepath]);
17+
18+
return requireMap[filepath];
3019
}

0 commit comments

Comments
 (0)