Skip to content

Commit e41fd1f

Browse files
authored
Support ESM module loaders in Flight fixture (#20229)
This lets the Flight fixture run as "type": "module" or "commonjs". Experimental loaders can be used similar to require.extensions to do the transpilation and replacement of .client.js references.
1 parent 760d9ab commit e41fd1f

File tree

13 files changed

+108
-7
lines changed

13 files changed

+108
-7
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"type": "commonjs"
3+
}

fixtures/flight/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
{
22
"name": "flight",
3+
"type": "module",
34
"version": "0.1.0",
45
"private": true,
56
"dependencies": {
67
"@babel/core": "7.6.0",
8+
"@babel/plugin-syntax-import-meta": "^7.10.4",
79
"@babel/register": "^7.7.0",
810
"@svgr/webpack": "4.3.2",
911
"@typescript-eslint/eslint-plugin": "^2.2.0",
@@ -65,7 +67,7 @@
6567
"prebuild": "cp -r ../../build/node_modules/* ./node_modules/",
6668
"start": "concurrently \"npm run start:server\" \"npm run start:client\"",
6769
"start:client": "node scripts/start.js",
68-
"start:server": "NODE_ENV=development node server",
70+
"start:server": "NODE_ENV=development node --experimental-loader ./server/loader.mjs server",
6971
"start:prod": "node scripts/build.js && NODE_ENV=production node server",
7072
"build": "node scripts/build.js",
7173
"test": "node scripts/test.js --env=jsdom"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"type": "commonjs"
3+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import {pipeToNodeWritable} from 'react-transport-dom-webpack/server.js';
2+
import * as React from 'react';
3+
import App from '../src/App.server.js';
4+
5+
import {URL} from 'url';
6+
7+
const rootPath = import.meta.url;
8+
function resolve(relative) {
9+
return new URL(relative, rootPath).href;
10+
}
11+
12+
export default function(req, res) {
13+
res.setHeader('Access-Control-Allow-Origin', '*');
14+
pipeToNodeWritable(<App />, res, {
15+
// TODO: Read from a map on the disk.
16+
[resolve('../src/Counter.client.js')]: {
17+
id: './src/Counter.client.js',
18+
chunks: ['1'],
19+
name: 'default',
20+
},
21+
[resolve('../src/ShowMore.client.js')]: {
22+
id: './src/ShowMore.client.js',
23+
chunks: ['2'],
24+
name: 'default',
25+
},
26+
});
27+
};

fixtures/flight/server/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ app.get('/', function(req, res) {
2525
delete require.cache[key];
2626
}
2727
}
28-
require('./handler.server')(req, res);
28+
import('./handler.server.mjs').then(m => m.default(req, res));
29+
// require('./handler.server.js')(req, res);
2930
});
3031

3132
app.listen(3001, () => {

fixtures/flight/server/loader.mjs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import babel from '@babel/core';
2+
3+
const options = {
4+
babelrc: false,
5+
ignore: [/\/(build|node_modules)\//],
6+
plugins: [
7+
'@babel/plugin-syntax-import-meta',
8+
'@babel/plugin-transform-react-jsx',
9+
],
10+
};
11+
12+
const optionsCommonJS = {
13+
ignore: [/\/(build|node_modules)\//],
14+
presets: ['react-app'],
15+
plugins: ['@babel/transform-modules-commonjs'],
16+
};
17+
18+
export async function transformSource(source, context, defaultTransformSource) {
19+
const {format} = context;
20+
if (format === 'module' || format === 'commonjs') {
21+
const opt = Object.assign(
22+
{filename: context.url},
23+
format === 'commonjs' ? optionsCommonJS : options
24+
);
25+
const {code} = await babel.transformAsync(source, opt);
26+
return {source: code};
27+
}
28+
return defaultTransformSource(source, context);
29+
}
30+
31+
export async function getSource(url, context, defaultGetSource) {
32+
if (url.endsWith('.client.js')) {
33+
const name = url;
34+
return {
35+
source:
36+
"export default { $$typeof: Symbol.for('react.module.reference'), name: " +
37+
JSON.stringify(name) +
38+
'}',
39+
};
40+
}
41+
return defaultGetSource(url, context, defaultGetSource);
42+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"type": "commonjs"
3+
}

fixtures/flight/src/App.server.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import * as React from 'react';
22

3-
import Container from './Container';
3+
import Container from './Container.js';
44

5-
import Counter from './Counter.client';
5+
import Counter from './Counter.client.js';
66

7-
import ShowMore from './ShowMore.client';
7+
import ShowMore from './ShowMore.client.js';
88

99
export default function App() {
1010
return (

fixtures/flight/src/Counter.client.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as React from 'react';
22

3-
import Container from './Container';
3+
import Container from './Container.js';
44

55
export default function Counter() {
66
const [count, setCount] = React.useState(0);

fixtures/flight/src/ShowMore.client.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as React from 'react';
22

3-
import Container from './Container';
3+
import Container from './Container.js';
44

55
export default function ShowMore({children}) {
66
const [show, setShow] = React.useState(false);

0 commit comments

Comments
 (0)