Skip to content

Commit 09914c1

Browse files
committed
Server render the main page
Also, add hashes to asset file names and use the "entry manifest" plugin in dev to get auto-reloading.
1 parent 45c48cb commit 09914c1

176 files changed

Lines changed: 4110 additions & 121207 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ npm-debug.log*
77
/functions/*.js
88
/functions/node_modules/
99
/node_modules/
10-
/public/_assets/
10+
/public/_client/
1111
/manifest.json
1212
/secret_key
1313
/tokens/

.size-snapshot.json

Lines changed: 0 additions & 12 deletions
This file was deleted.

firebase.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
{ "source": "/api/auth", "function": "serveAuth" },
77
{ "source": "/api/public-key", "function": "servePublicKey" },
88
{ "source": "/api/stats", "function": "serveStats" },
9+
{ "source": "/", "function": "serveMainPage" },
910
{ "source": "**/", "function": "serveAutoIndexPage" },
1011
{ "source": "**", "function": "serveNpmPackageFile" }
1112
]

functions/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
"warning": "^4.0.2",
4343
"whatwg-url": "^7.0.0"
4444
},
45-
"devDependencies": {},
4645
"engines": {
4746
"node": "8"
4847
}

modules/actions/serveAutoIndexPage.js

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,49 +2,41 @@ import React from 'react';
22
import ReactDOMServer from 'react-dom/server';
33
import semver from 'semver';
44

5-
import MainPage from '../client/MainPage';
5+
import MainTemplate from '../client/MainTemplate';
66
import AutoIndexApp from '../client/autoIndex/App';
77
import createHTML from '../client/utils/createHTML';
8-
import renderPage from '../utils/renderPage';
9-
10-
const globalScripts =
11-
process.env.NODE_ENV === 'production'
12-
? [
13-
'/[email protected]/umd/react.production.min.js',
14-
'/[email protected]/umd/react-dom.production.min.js'
15-
]
16-
: [
17-
'/[email protected]/umd/react.development.js',
18-
'/[email protected]/umd/react-dom.development.js'
19-
];
8+
import getEntryPoints from '../utils/getEntryPoints';
9+
import renderTemplate from '../utils/renderTemplate';
2010

2111
function byVersion(a, b) {
2212
return semver.lt(a, b) ? -1 : semver.gt(a, b) ? 1 : 0;
2313
}
2414

2515
export default function serveAutoIndexPage(req, res) {
26-
const scripts = globalScripts.concat('/_assets/autoIndex.js');
27-
const styles = ['/autoIndex.css'];
28-
29-
const props = {
16+
const data = {
3017
packageName: req.packageName,
3118
packageVersion: req.packageVersion,
3219
availableVersions: Object.keys(req.packageInfo.versions).sort(byVersion),
3320
filename: req.filename,
3421
entry: req.entry,
3522
entries: req.entries
3623
};
24+
3725
const content = createHTML(
38-
ReactDOMServer.renderToString(React.createElement(AutoIndexApp, props))
26+
ReactDOMServer.renderToString(React.createElement(AutoIndexApp, data))
3927
);
4028

41-
const html = renderPage(MainPage, {
29+
const entryPoints = getEntryPoints('autoIndex', {
30+
es: 'module',
31+
system: 'nomodule'
32+
});
33+
34+
const html = renderTemplate(MainTemplate, {
4235
title: `UNPKG - ${req.packageName}`,
4336
description: `The CDN for ${req.packageName}`,
44-
scripts: scripts,
45-
styles: styles,
46-
data: props,
47-
content: content
37+
data,
38+
content,
39+
entryPoints
4840
});
4941

5042
res

modules/actions/serveMainPage.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import React from 'react';
2+
import ReactDOMServer from 'react-dom/server';
3+
import { StaticRouter } from 'react-router-dom';
4+
5+
import MainTemplate from '../client/MainTemplate';
6+
import MainApp from '../client/main/App';
7+
import createHTML from '../client/utils/createHTML';
8+
import getEntryPoints from '../utils/getEntryPoints';
9+
import renderTemplate from '../utils/renderTemplate';
10+
11+
export default function serveMainPage(req, res) {
12+
const element = React.createElement(
13+
StaticRouter,
14+
{ location: req.url },
15+
React.createElement(MainApp)
16+
);
17+
const content = createHTML(ReactDOMServer.renderToString(element));
18+
19+
const entryPoints = getEntryPoints('main', {
20+
es: 'module',
21+
system: 'nomodule'
22+
});
23+
24+
const html = renderTemplate(MainTemplate, { content, entryPoints });
25+
26+
res
27+
.set({
28+
'Cache-Control': 'public, max-age=14400', // 4 hours
29+
'Cache-Tag': 'main'
30+
})
31+
.send(html);
32+
}

modules/client/.babelrc

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
{
2-
"presets": [["@babel/env", { "loose": true }], "@babel/react"],
3-
"plugins": [["@babel/plugin-proposal-class-properties", { "loose": true }]]
2+
"presets": [
3+
["@babel/env", { "loose": true }],
4+
"@babel/react"
5+
],
6+
"plugins": [
7+
["@babel/plugin-proposal-class-properties", { "loose": true }]
8+
]
49
}

modules/client/MainPage.js

Lines changed: 0 additions & 72 deletions
This file was deleted.

modules/client/MainTemplate.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
import createHTML from './utils/createHTML';
5+
import x from './utils/execScript';
6+
7+
const promiseShim =
8+
'window.Promise || document.write(\'\\x3Cscript src="/[email protected]/dist/es6-promise.min.js">\\x3C/script>\\x3Cscript>ES6Promise.polyfill()\\x3C/script>\')';
9+
const fetchShim =
10+
'window.fetch || document.write(\'\\x3Cscript src="/[email protected]/dist/fetch.umd.js">\\x3C/script>\')';
11+
12+
export default function MainTemplate({
13+
title,
14+
description,
15+
favicon,
16+
data,
17+
content,
18+
globalScripts,
19+
entryPoints
20+
}) {
21+
return (
22+
<html lang="en">
23+
<head>
24+
<meta charSet="utf-8" />
25+
<meta httpEquiv="X-UA-Compatible" content="IE=edge,chrome=1" />
26+
{description && <meta name="description" content={description} />}
27+
<meta
28+
name="viewport"
29+
content="width=device-width,initial-scale=1,maximum-scale=1"
30+
/>
31+
<meta name="timestamp" content={new Date().toISOString()} />
32+
{favicon && <link rel="shortcut icon" href={favicon} />}
33+
<title>{title}</title>
34+
{x(promiseShim)}
35+
{x(fetchShim)}
36+
{data && x(`window.__DATA__ = ${JSON.stringify(data)}`)}
37+
</head>
38+
<body>
39+
<div id="root" dangerouslySetInnerHTML={content} />
40+
41+
{globalScripts.map(src => (
42+
<script key={src} src={src} />
43+
))}
44+
45+
{entryPoints.module &&
46+
x(`
47+
import('${entryPoints.module}');
48+
window.supportsDynamicImport = true;
49+
`)}
50+
{entryPoints.nomodule &&
51+
x(`
52+
if (!window.supportsDynamicImport) {
53+
var s = document.createElement('script');
54+
s.src = '/[email protected]/dist/s.min.js';
55+
s.addEventListener('load', function() {
56+
System.import('${entryPoints.nomodule}');
57+
});
58+
document.head.appendChild(s);
59+
}
60+
`)}
61+
</body>
62+
</html>
63+
);
64+
}
65+
66+
MainTemplate.defaultProps = {
67+
title: 'UNPKG',
68+
description: 'The CDN for everything on npm',
69+
favicon: '/favicon.ico',
70+
content: createHTML(''),
71+
globalScripts: []
72+
};
73+
74+
const htmlType = PropTypes.shape({
75+
__html: PropTypes.string
76+
});
77+
78+
MainTemplate.propTypes = {
79+
title: PropTypes.string,
80+
description: PropTypes.string,
81+
favicon: PropTypes.string,
82+
data: PropTypes.any,
83+
content: htmlType,
84+
globalScripts: PropTypes.arrayOf(PropTypes.string),
85+
entryPoints: PropTypes.shape({
86+
module: PropTypes.string,
87+
nomodule: PropTypes.string
88+
}).isRequired
89+
};

modules/client/autoIndex.css

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)