Load React + Emotion from CDN URLs, use globals

Remove @emotion/babel-preset-css-prop and import { jsx } from
@emotion/core directly instead so Rollup can preserve imports order when
bundling (instead of @emotion/core automatically inserting itself as the
first import).
This commit is contained in:
Michael Jackson
2019-01-23 21:27:58 -08:00
parent 6228f0de5c
commit bbb092d974
117 changed files with 109774 additions and 1773 deletions

View File

@ -5,9 +5,22 @@ import semver from 'semver';
import MainTemplate from '../client/MainTemplate';
import AutoIndexApp from '../client/autoIndex/App';
import createHTML from '../client/utils/createHTML';
import getEntryPoints from '../utils/getEntryPoints';
import getScripts from '../utils/getScripts';
import renderTemplate from '../utils/renderTemplate';
const globalURLs =
process.env.NODE_ENV === 'production'
? {
'@emotion/core': '/@emotion/core@10.0.6/dist/core.umd.min.js',
react: '/react@16.7.0/umd/react.production.min.js',
'react-dom': '/react-dom@16.7.0/umd/react-dom.production.min.js'
}
: {
'@emotion/core': '/@emotion/core@10.0.6/dist/core.umd.min.js',
react: '/react@16.7.0/umd/react.development.js',
'react-dom': '/react-dom@16.7.0/umd/react-dom.development.js'
};
function byVersion(a, b) {
return semver.lt(a, b) ? -1 : semver.gt(a, b) ? 1 : 0;
}
@ -26,17 +39,14 @@ export default function serveAutoIndexPage(req, res) {
ReactDOMServer.renderToString(React.createElement(AutoIndexApp, data))
);
const entryPoints = getEntryPoints('autoIndex', {
es: 'module',
system: 'nomodule'
});
const scripts = getScripts('autoIndex', globalURLs);
const html = renderTemplate(MainTemplate, {
title: `UNPKG - ${req.packageName}`,
description: `The CDN for ${req.packageName}`,
data,
content,
entryPoints
scripts
});
res

View File

@ -4,18 +4,26 @@ import { renderToString } from 'react-dom/server';
import MainTemplate from '../client/MainTemplate';
import MainApp from '../client/main/App';
import createHTML from '../client/utils/createHTML';
import getEntryPoints from '../utils/getEntryPoints';
import getScripts from '../utils/getScripts';
import renderTemplate from '../utils/renderTemplate';
const globalURLs =
process.env.NODE_ENV === 'production'
? {
'@emotion/core': '/@emotion/core@10.0.6/dist/core.umd.min.js',
react: '/react@16.7.0/umd/react.production.min.js',
'react-dom': '/react-dom@16.7.0/umd/react-dom.production.min.js'
}
: {
'@emotion/core': '/@emotion/core@10.0.6/dist/core.umd.min.js',
react: '/react@16.7.0/umd/react.development.js',
'react-dom': '/react-dom@16.7.0/umd/react-dom.development.js'
};
export default function serveMainPage(req, res) {
const content = createHTML(renderToString(React.createElement(MainApp)));
const entryPoints = getEntryPoints('main', {
es: 'module',
system: 'nomodule'
});
const html = renderTemplate(MainTemplate, { content, entryPoints });
const scripts = getScripts('main', globalURLs);
const html = renderTemplate(MainTemplate, { content, scripts });
res
.set({

View File

@ -1,8 +1,7 @@
{
"presets": [
["@babel/preset-env", { "loose": true }],
"@babel/preset-react",
"@emotion/babel-preset-css-prop"
"@babel/preset-react"
],
"plugins": [
["@babel/plugin-proposal-class-properties", { "loose": true }]

View File

@ -15,7 +15,7 @@ export default function MainTemplate({
favicon,
data,
content,
entryPoints
scripts
}) {
return (
<html lang="en">
@ -36,22 +36,9 @@ export default function MainTemplate({
</head>
<body>
<div id="root" dangerouslySetInnerHTML={content} />
{entryPoints.module &&
x(`
import('${entryPoints.module}');
window.supportsDynamicImport = true;
`)}
{entryPoints.nomodule &&
x(`
if (!window.supportsDynamicImport) {
var s = document.createElement('script');
s.src = '/systemjs@2.0.0/dist/s.min.js';
s.addEventListener('load', function() {
System.import('${entryPoints.nomodule}');
});
document.head.appendChild(s);
}
`)}
{scripts.map(src => (
<script key={src} src={src} />
))}
</body>
</html>
);
@ -61,7 +48,8 @@ MainTemplate.defaultProps = {
title: 'UNPKG',
description: 'The CDN for everything on npm',
favicon: '/favicon.ico',
content: createHTML('')
content: createHTML(''),
scripts: []
};
if (process.env.NODE_ENV !== 'production') {
@ -75,9 +63,6 @@ if (process.env.NODE_ENV !== 'production') {
favicon: PropTypes.string,
data: PropTypes.any,
content: htmlType,
entryPoints: PropTypes.shape({
module: PropTypes.string,
nomodule: PropTypes.string
}).isRequired
scripts: PropTypes.arrayOf(PropTypes.string)
};
}

View File

@ -1,6 +1,7 @@
/** @jsx jsx */
import React from 'react';
import PropTypes from 'prop-types';
import { Global, css } from '@emotion/core';
import { Global, css, jsx } from '@emotion/core';
import DirectoryListing from './DirectoryListing';

View File

@ -1,5 +1,7 @@
/** @jsx jsx */
import React from 'react';
import PropTypes from 'prop-types';
import { jsx } from '@emotion/core';
import formatBytes from 'pretty-bytes';
import sortBy from 'sort-by';

View File

@ -1,6 +1,7 @@
/** @jsx jsx */
import React from 'react';
import PropTypes from 'prop-types';
import { Global, css } from '@emotion/core';
import { Global, css, jsx } from '@emotion/core';
import formatBytes from 'pretty-bytes';
import formatDate from 'date-fns/format';
import parseDate from 'date-fns/parse';
@ -19,7 +20,7 @@ const globalStyles = css`
Helvetica, Arial, sans-serif;
line-height: 1.7;
padding: 5px 20px;
color: #000000;
color: black;
}
@media (min-width: 800px) {

View File

@ -0,0 +1,17 @@
// Virtual module id; see rollup.config.js
import entryManifest from 'entry-manifest';
export default function getEntryPoint(name, format) {
let entryPoints;
entryManifest.forEach(manifest => {
if (name in manifest) {
entryPoints = manifest[name];
}
});
if (entryPoints) {
return entryPoints.find(e => e.format === format);
}
return null;
}

View File

@ -1,19 +0,0 @@
import invariant from 'invariant';
// Virtual module id; see rollup.config.js
import entryManifest from 'entry-manifest';
export default function getEntryPoints(entryName, formatKeys) {
const manifest = entryManifest[entryName];
invariant(manifest, 'Invalid entry name: %s', entryName);
return manifest.reduce((memo, entryPoint) => {
if (entryPoint.format in formatKeys) {
const key = formatKeys[entryPoint.format];
memo[key] = entryPoint.url;
}
return memo;
}, {});
}

View File

@ -0,0 +1,16 @@
import invariant from 'invariant';
import getEntryPoint from './getEntryPoint';
export default function getScripts(entryName, globalURLs) {
const entryPoint = getEntryPoint(entryName, 'iife');
invariant(entryPoint, 'Invalid entry name "%s"', entryName);
const globalScripts = entryPoint.globalImports.map(id => {
invariant(globalURLs[id], 'Missing global URL for id "%s"', id);
return globalURLs[id];
});
return globalScripts.concat(entryPoint.url);
}