Performance improvements (#458)

* Performance improvements

- Use font-display: swap
- Preload CSS links
- Compress all request payloads

* inline react spinner css

* remove @zeit/next-css, move custom themes to static

* update contributing docs

* spinner styles

* move spinner back to top level

* load codemirror synchronously
main
Michael Fix 6 years ago committed by GitHub
parent 0d2f2f4444
commit a9b25e05a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -17,4 +17,4 @@ We're happy to accept any PRs adding new themes and languages to Carbon! Current
1. If the [theme](https://codemirror.net/demo/theme.html) or [language](https://codemirror.net/mode/index.html) is supported in Codemirror, all you have to do is add a [constant](https://github.com/dawnlabs/carbon/blob/master/lib/constants.js) for it. 1. If the [theme](https://codemirror.net/demo/theme.html) or [language](https://codemirror.net/mode/index.html) is supported in Codemirror, all you have to do is add a [constant](https://github.com/dawnlabs/carbon/blob/master/lib/constants.js) for it.
2. If it's not supported, you can add a Codemirror compliant [custom file](https://github.com/dawnlabs/carbon/tree/master/lib/custom) to implement it and add a constant like above. 2. If it's not supported, you can add a Codemirror compliant [custom theme](https://github.com/dawnlabs/carbon/tree/master/static/themes) or [custom mode](https://github.com/dawnlabs/carbon/tree/master/lib/custom/modes) to implement it and add a constant like above.

@ -4,7 +4,6 @@ import ResizeObserver from 'resize-observer-polyfill'
import debounce from 'lodash.debounce' import debounce from 'lodash.debounce'
import ms from 'ms' import ms from 'ms'
import { Controlled as CodeMirror } from 'react-codemirror2' import { Controlled as CodeMirror } from 'react-codemirror2'
import Spinner from 'react-spinner'
import WindowControls from '../components/WindowControls' import WindowControls from '../components/WindowControls'
import Watermark from '../components/svg/Watermark' import Watermark from '../components/svg/Watermark'
@ -29,7 +28,6 @@ class Carbon extends PureComponent {
super(props) super(props)
this.state = { this.state = {
loading: true,
language: props.config.language language: props.config.language
} }
@ -40,7 +38,6 @@ class Carbon extends PureComponent {
} }
componentDidMount() { componentDidMount() {
this.setState({ loading: false })
this.setState(handleLanguageChange(this.props.children, this.props)) this.setState(handleLanguageChange(this.props.children, this.props))
const ro = new ResizeObserver(entries => { const ro = new ResizeObserver(entries => {
@ -90,161 +87,146 @@ class Carbon extends PureComponent {
(this.props.config.backgroundImage && this.props.config.backgroundImageSelection) || (this.props.config.backgroundImage && this.props.config.backgroundImageSelection) ||
this.props.config.backgroundImage this.props.config.backgroundImage
let content = ( const content = (
<div> <div id="container">
<Spinner /> {config.windowControls ? (
<WindowControls
titleBar={this.props.titleBar}
theme={config.windowTheme}
handleTitleBarChange={this.handleTitleBarChange}
/>
) : null}
<CodeMirror
className={`CodeMirror__container window-theme__${config.windowTheme}`}
onBeforeChange={this.onBeforeChange}
value={this.props.children}
options={options}
/>
{config.watermark && <Watermark />}
<div id="container-bg">
<div className="white eliminateOnRender" />
<div className="alpha eliminateOnRender" />
<div className="bg" />
</div>
<style jsx> <style jsx>
{` {`
div { #container {
height: 352px; position: relative;
min-width: ${config.widthAdjustment ? '90px' : '680px'};
max-width: 1024px;
padding: ${config.paddingVertical} ${config.paddingHorizontal};
}
#container :global(.watermark) {
fill-opacity: 0.3;
position: absolute;
z-index: 2;
bottom: calc(${config.paddingVertical} + 16px);
right: calc(${config.paddingHorizontal} + 16px);
}
#container #container-bg {
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
}
#container .white {
background: #fff;
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
}
#container .bg {
${this.props.config.backgroundMode === 'image'
? `background: url(${backgroundImage});
background-size: cover;
background-repeat: no-repeat;`
: `background: ${this.props.config.backgroundColor || config.backgroundColor};
background-size: auto;
background-repeat: repeat;`} position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
}
#container .alpha {
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==);
}
#container :global(.cm-s-dracula .CodeMirror-cursor) {
border-left: solid 2px #159588;
}
#container :global(.cm-s-solarized) {
box-shadow: none;
}
#container :global(.cm-s-solarized.cm-s-light) {
text-shadow: #eee8d5 0 1px;
}
#container :global(.CodeMirror-gutters) {
background-color: unset;
border-right: none;
}
#container :global(.CodeMirror__container) {
min-width: inherit;
position: relative;
z-index: 1;
border-radius: 5px;
${config.dropShadow
? `box-shadow: 0 ${config.dropShadowOffsetY} ${
config.dropShadowBlurRadius
} rgba(0, 0, 0, 0.55)`
: ''};
}
#container :global(.CodeMirror__container .CodeMirror) {
height: auto;
min-width: inherit;
padding: 18px 18px;
${config.lineNumbers ? 'padding-left: 12px;' : ''} border-radius: 5px;
font-family: ${config.fontFamily}, monospace !important;
font-size: ${config.fontSize};
line-height: ${config.lineHeight};
font-variant-ligatures: contextual;
font-feature-settings: 'calt' 1;
user-select: none;
}
#container :global(.CodeMirror-scroll) {
overflow: hidden !important;
}
#container :global(.window-theme__sharp > .CodeMirror) {
border-radius: 0px;
}
#container :global(.window-theme__bw > .CodeMirror) {
border: 2px solid ${COLORS.SECONDARY};
}
#container :global(.window-controls + .CodeMirror__container > .CodeMirror) {
padding-top: 48px;
} }
`} `}
</style> </style>
</div> </div>
) )
if (this.state.loading === false) {
content = (
<div id="container">
{config.windowControls ? (
<WindowControls
titleBar={this.props.titleBar}
theme={config.windowTheme}
handleTitleBarChange={this.handleTitleBarChange}
/>
) : null}
<CodeMirror
className={`CodeMirror__container window-theme__${config.windowTheme}`}
onBeforeChange={this.onBeforeChange}
value={this.props.children}
options={options}
/>
{config.watermark && <Watermark />}
<div id="container-bg">
<div className="white eliminateOnRender" />
<div className="alpha eliminateOnRender" />
<div className="bg" />
</div>
<style jsx>
{`
#container {
position: relative;
min-width: ${config.widthAdjustment ? '90px' : '680px'};
max-width: 1024px;
padding: ${config.paddingVertical} ${config.paddingHorizontal};
}
#container :global(.watermark) {
fill-opacity: 0.3;
position: absolute;
z-index: 2;
bottom: calc(${config.paddingVertical} + 16px);
right: calc(${config.paddingHorizontal} + 16px);
}
#container #container-bg {
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
}
#container .white {
background: #fff;
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
}
#container .bg {
${this.props.config.backgroundMode === 'image'
? `background: url(${backgroundImage});
background-size: cover;
background-repeat: no-repeat;`
: `background: ${this.props.config.backgroundColor || config.backgroundColor};
background-size: auto;
background-repeat: repeat;`} position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
}
#container .alpha {
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==);
}
#container :global(.cm-s-dracula .CodeMirror-cursor) {
border-left: solid 2px #159588;
}
#container :global(.cm-s-solarized) {
box-shadow: none;
}
#container :global(.cm-s-solarized.cm-s-light) {
text-shadow: #eee8d5 0 1px;
}
#container :global(.CodeMirror-gutters) {
background-color: unset;
border-right: none;
}
#container :global(.CodeMirror__container) {
min-width: inherit;
position: relative;
z-index: 1;
border-radius: 5px;
${config.dropShadow
? `box-shadow: 0 ${config.dropShadowOffsetY} ${
config.dropShadowBlurRadius
} rgba(0, 0, 0, 0.55)`
: ''};
}
#container :global(.CodeMirror__container .CodeMirror) {
height: auto;
min-width: inherit;
padding: 18px 18px;
${config.lineNumbers ? 'padding-left: 12px;' : ''} border-radius: 5px;
font-family: ${config.fontFamily}, monospace !important;
font-size: ${config.fontSize};
line-height: ${config.lineHeight};
font-variant-ligatures: contextual;
font-feature-settings: 'calt' 1;
user-select: none;
}
#container :global(.CodeMirror-scroll) {
overflow: hidden !important;
}
#container :global(.window-theme__sharp > .CodeMirror) {
border-radius: 0px;
}
#container :global(.window-theme__bw > .CodeMirror) {
border: 2px solid ${COLORS.SECONDARY};
}
#container :global(.window-controls + .CodeMirror__container > .CodeMirror) {
padding-top: 48px;
}
`}
</style>
</div>
)
}
return ( return (
<div id="section"> <div id="section">
<div id="export-container" ref={ele => (this.exportContainerNode = ele)}> <div id="export-container" ref={ele => (this.exportContainerNode = ele)}>

@ -4,6 +4,7 @@ import HTML5Backend from 'react-dnd-html5-backend'
import { DragDropContext } from 'react-dnd' import { DragDropContext } from 'react-dnd'
import domtoimage from 'dom-to-image' import domtoimage from 'dom-to-image'
import ReadFileDropContainer, { DATA_URL, TEXT } from 'dropperx' import ReadFileDropContainer, { DATA_URL, TEXT } from 'dropperx'
import Spinner from 'react-spinner'
// Ours // Ours
import Button from './Button' import Button from './Button'
@ -26,7 +27,8 @@ import {
COLORS, COLORS,
EXPORT_SIZES_HASH, EXPORT_SIZES_HASH,
DEFAULT_CODE, DEFAULT_CODE,
DEFAULT_SETTINGS DEFAULT_SETTINGS,
DEFAULT_LANGUAGE
} from '../lib/constants' } from '../lib/constants'
import { serializeState } from '../lib/routing' import { serializeState } from '../lib/routing'
import { getState } from '../lib/util' import { getState } from '../lib/util'
@ -43,6 +45,7 @@ class Editor extends React.Component {
super(props) super(props)
this.state = { this.state = {
...DEFAULT_SETTINGS, ...DEFAULT_SETTINGS,
loading: true,
uploading: false, uploading: false,
code: props.content, code: props.content,
online: true online: true
@ -70,6 +73,7 @@ class Editor extends React.Component {
this.setState({ this.setState({
...getState(localStorage), ...getState(localStorage),
...this.props.initialState, ...this.props.initialState,
loading: false,
online: Boolean(window && window.navigator && window.navigator.onLine) online: Boolean(window && window.navigator && window.navigator.onLine)
}) })
@ -213,6 +217,20 @@ class Editor extends React.Component {
} }
render() { render() {
if (this.state.loading) {
return (
<div>
<Spinner />
<style jsx>
{`
div {
height: 160px;
}
`}
</style>
</div>
)
}
return ( return (
<React.Fragment> <React.Fragment>
<div id="editor"> <div id="editor">
@ -227,7 +245,7 @@ class Editor extends React.Component {
LANGUAGE_NAME_HASH[this.state.language] || LANGUAGE_NAME_HASH[this.state.language] ||
LANGUAGE_MIME_HASH[this.state.language] || LANGUAGE_MIME_HASH[this.state.language] ||
LANGUAGE_MODE_HASH[this.state.language] || LANGUAGE_MODE_HASH[this.state.language] ||
'auto' DEFAULT_LANGUAGE
} }
list={LANGUAGES} list={LANGUAGES}
onChange={this.updateLanguage} onChange={this.updateLanguage}

@ -4,12 +4,11 @@ import Reset from './style/Reset'
import Font from './style/Font' import Font from './style/Font'
import Typography from './style/Typography' import Typography from './style/Typography'
import '../static/react-crop.css' const LOCAL_STYLESHEETS = ['one-dark', 'verminal', 'night-owl', 'nord']
import '../static/react-spinner.css'
import '../lib/custom/themes/one-dark.css' const CDN_STYLESHEETS = THEMES.filter(
import '../lib/custom/themes/verminal.css' t => t.hasStylesheet !== false && LOCAL_STYLESHEETS.indexOf(t.id) < 0
import '../lib/custom/themes/night-owl.css' )
import '../lib/custom/themes/nord.css'
export default () => { export default () => {
const onBrowser = typeof window !== 'undefined' const onBrowser = typeof window !== 'undefined'
@ -38,24 +37,44 @@ export default () => {
<title>Carbon</title> <title>Carbon</title>
<link rel="manifest" href="/static/manifest.json" /> <link rel="manifest" href="/static/manifest.json" />
<link rel="shortcut icon" href="/static/favicon.ico" /> <link rel="shortcut icon" href="/static/favicon.ico" />
<link rel="stylesheet" href="/_next/static/style.css" /> <link
rel="preload"
as="style"
onLoad="this.onload=null;this.rel='stylesheet'"
href="/static/react-crop.css"
/>
<link <link
rel="stylesheet" rel="stylesheet"
href="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.26.0/codemirror.min.css" href="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.26.0/codemirror.min.css"
/> />
<link <link
rel="stylesheet" rel="preload"
as="style"
onLoad="this.onload=null;this.rel='stylesheet'"
href="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.30.0/theme/solarized.min.css" href="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.30.0/theme/solarized.min.css"
/> />
<link <link
rel="stylesheet" rel="preload"
as="style"
onLoad="this.onload=null;this.rel='stylesheet'"
href="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.36.0/theme/seti.min.css" href="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.36.0/theme/seti.min.css"
/> />
{LOCAL_STYLESHEETS.map(id => (
<link
key={id}
rel="preload"
as="style"
onLoad="this.onload=null;this.rel='stylesheet'"
href={`/static/themes/${id}.css`}
/>
))}
{onBrowser {onBrowser
? THEMES.filter(t => t.hasStylesheet !== false).map(theme => ( ? CDN_STYLESHEETS.map(theme => (
<link <link
key={theme.id} key={theme.id}
rel="stylesheet" rel="preload"
as="style"
onLoad="this.onload=null;this.rel='stylesheet'"
href={ href={
theme.link || theme.link ||
`//cdnjs.cloudflare.com/ajax/libs/codemirror/5.36.0/theme/${theme.id}.min.css` `//cdnjs.cloudflare.com/ajax/libs/codemirror/5.36.0/theme/${theme.id}.min.css`

@ -1,8 +1,14 @@
/*
* See https://developers.google.com/web/updates/2016/02/font-display and
* https://css-tricks.com/font-display-masses/#article-header-id-2
* for `font-display` information
*/
export default () => ( export default () => (
<style jsx global> <style jsx global>
{` {`
@font-face { @font-face {
font-family: 'Iosevka'; font-family: 'Iosevka';
font-display: swap;
src: url('//cdn.jsdelivr.net/npm/@typopro/web-iosevka@3.7.5/TypoPRO-iosevka-term-bold.woff') src: url('//cdn.jsdelivr.net/npm/@typopro/web-iosevka@3.7.5/TypoPRO-iosevka-term-bold.woff')
format('woff'); format('woff');
font-weight: 400; font-weight: 400;
@ -11,6 +17,7 @@ export default () => (
@font-face { @font-face {
font-family: 'Monoid'; font-family: 'Monoid';
font-display: swap;
src: url('//cdn.jsdelivr.net/npm/@typopro/web-monoid@3.7.5/TypoPRO-Monoid-Regular.woff') src: url('//cdn.jsdelivr.net/npm/@typopro/web-monoid@3.7.5/TypoPRO-Monoid-Regular.woff')
format('woff2'), format('woff2'),
url('//cdn.jsdelivr.net/npm/@typopro/web-monoid@3.7.5/TypoPRO-Monoid-Regular.woff') url('//cdn.jsdelivr.net/npm/@typopro/web-monoid@3.7.5/TypoPRO-Monoid-Regular.woff')
@ -21,6 +28,7 @@ export default () => (
@font-face { @font-face {
font-family: 'Fantasque Sans Mono'; font-family: 'Fantasque Sans Mono';
font-display: swap;
src: url('//cdn.jsdelivr.net/npm/@typopro/web-fantasque-sans-mono@3.7.5/TypoPRO-FantasqueSansMono-Regular.woff') src: url('//cdn.jsdelivr.net/npm/@typopro/web-fantasque-sans-mono@3.7.5/TypoPRO-FantasqueSansMono-Regular.woff')
format('woff2'), format('woff2'),
url('//cdn.jsdelivr.net/npm/@typopro/web-fantasque-sans-mono@3.7.5/TypoPRO-FantasqueSansMono-Regular.woff') url('//cdn.jsdelivr.net/npm/@typopro/web-fantasque-sans-mono@3.7.5/TypoPRO-FantasqueSansMono-Regular.woff')
@ -31,6 +39,7 @@ export default () => (
@font-face { @font-face {
font-family: 'Hack'; font-family: 'Hack';
font-display: swap;
src: url('//cdn.jsdelivr.net/font-hack/2.020/fonts/woff2/hack-regular-webfont.woff2?v=2.020') src: url('//cdn.jsdelivr.net/font-hack/2.020/fonts/woff2/hack-regular-webfont.woff2?v=2.020')
format('woff2'), format('woff2'),
url('//cdn.jsdelivr.net/font-hack/2.020/fonts/woff/hack-regular-webfont.woff?v=2.020') url('//cdn.jsdelivr.net/font-hack/2.020/fonts/woff/hack-regular-webfont.woff?v=2.020')
@ -41,6 +50,7 @@ export default () => (
@font-face { @font-face {
font-family: 'Fira Code'; font-family: 'Fira Code';
font-display: swap;
src: url('//cdn.rawgit.com/tonsky/FiraCode/1.204/distr/woff2/FiraCode-Regular.woff2') src: url('//cdn.rawgit.com/tonsky/FiraCode/1.204/distr/woff2/FiraCode-Regular.woff2')
format('woff2'), format('woff2'),
url('//cdn.rawgit.com/tonsky/FiraCode/1.204/distr/woff/FiraCode-Regular.woff') url('//cdn.rawgit.com/tonsky/FiraCode/1.204/distr/woff/FiraCode-Regular.woff')
@ -52,6 +62,7 @@ export default () => (
/* latin */ /* latin */
@font-face { @font-face {
font-family: 'IBM Plex Mono'; font-family: 'IBM Plex Mono';
font-display: swap;
font-style: italic; font-style: italic;
font-weight: 500; font-weight: 500;
src: local('IBM Plex Mono Medium Italic'), local('IBMPlexMono-MediumItalic'), src: local('IBM Plex Mono Medium Italic'), local('IBMPlexMono-MediumItalic'),
@ -65,6 +76,7 @@ export default () => (
/* latin */ /* latin */
@font-face { @font-face {
font-family: 'Anonymous Pro'; font-family: 'Anonymous Pro';
font-display: swap;
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Anonymous Pro Regular'), local('AnonymousPro-Regular'), src: local('Anonymous Pro Regular'), local('AnonymousPro-Regular'),
@ -77,6 +89,7 @@ export default () => (
/* latin */ /* latin */
@font-face { @font-face {
font-family: 'Droid Sans Mono'; font-family: 'Droid Sans Mono';
font-display: swap;
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Droid Sans Mono Regular'), local('DroidSansMono-Regular'), src: local('Droid Sans Mono Regular'), local('DroidSansMono-Regular'),
@ -89,6 +102,7 @@ export default () => (
/* latin */ /* latin */
@font-face { @font-face {
font-family: 'Inconsolata'; font-family: 'Inconsolata';
font-display: swap;
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Inconsolata Regular'), local('Inconsolata-Regular'), src: local('Inconsolata Regular'), local('Inconsolata-Regular'),
@ -101,6 +115,7 @@ export default () => (
/* latin */ /* latin */
@font-face { @font-face {
font-family: 'Source Code Pro'; font-family: 'Source Code Pro';
font-display: swap;
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Source Code Pro'), local('SourceCodePro-Regular'), src: local('Source Code Pro'), local('SourceCodePro-Regular'),
@ -113,6 +128,7 @@ export default () => (
/* latin */ /* latin */
@font-face { @font-face {
font-family: 'Ubuntu Mono'; font-family: 'Ubuntu Mono';
font-display: swap;
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Ubuntu Mono'), local('UbuntuMono-Regular'), src: local('Ubuntu Mono'), local('UbuntuMono-Regular'),
@ -125,6 +141,7 @@ export default () => (
/* latin */ /* latin */
@font-face { @font-face {
font-family: 'Space Mono'; font-family: 'Space Mono';
font-display: swap;
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Space Mono'), local('SpaceMono-Regular'), src: local('Space Mono'), local('SpaceMono-Regular'),

@ -191,6 +191,8 @@ export default () => (
color: ${COLORS.PRIMARY}; color: ${COLORS.PRIMARY};
background: none; background: none;
} }
.react-spinner{z-index: 999;position:relative;width:32px;height:32px;top:50%;left:50%}.react-spinner_bar{-webkit-animation:react-spinner_spin 1.2s linear infinite;-moz-animation:react-spinner_spin 1.2s linear infinite;animation:react-spinner_spin 1.2s linear infinite;border-radius:5px;background-color:#fff;position:absolute;width:20%;height:7.8%;top:-3.9%;left:-10%}@keyframes react-spinner_spin{0%{opacity:1}100%{opacity:.15}}@-moz-keyframes react-spinner_spin{0%{opacity:1}100%{opacity:.15}}@-webkit-keyframes react-spinner_spin{0%{opacity:1}100%{opacity:.15}}
`} `}
</style> </style>
) )

@ -15,7 +15,6 @@ export const FONTS = [
{ id: 'Ubuntu Mono', name: 'Ubuntu Mono' } { id: 'Ubuntu Mono', name: 'Ubuntu Mono' }
] ]
const hasStylesheet = false
export const THEMES = [ export const THEMES = [
{ {
id: '3024-night', id: '3024-night',
@ -63,13 +62,11 @@ export const THEMES = [
}, },
{ {
id: 'night-owl', id: 'night-owl',
name: 'Night Owl', name: 'Night Owl'
hasStylesheet
}, },
{ {
id: 'nord', id: 'nord',
name: 'Nord', name: 'Nord'
hasStylesheet
}, },
{ {
id: 'oceanic-next', id: 'oceanic-next',
@ -77,8 +74,7 @@ export const THEMES = [
}, },
{ {
id: 'one-dark', id: 'one-dark',
name: 'One Dark', name: 'One Dark'
hasStylesheet
}, },
{ {
id: 'panda-syntax', id: 'panda-syntax',
@ -95,12 +91,12 @@ export const THEMES = [
{ {
id: 'solarized dark', id: 'solarized dark',
name: 'Solarized (Dark)', name: 'Solarized (Dark)',
hasStylesheet hasStylesheet: false
}, },
{ {
id: 'solarized light', id: 'solarized light',
name: 'Solarized (Light)', name: 'Solarized (Light)',
hasStylesheet hasStylesheet: false
}, },
{ {
id: 'tomorrow-night-bright', id: 'tomorrow-night-bright',
@ -112,8 +108,7 @@ export const THEMES = [
}, },
{ {
id: 'verminal', id: 'verminal',
name: 'Verminal', name: 'Verminal'
hasStylesheet
}, },
{ {
id: 'yeti', id: 'yeti',

@ -1,4 +1,3 @@
const withCSS = require('@zeit/next-css')
const withOffline = require('next-offline') const withOffline = require('next-offline')
module.exports = withOffline(withCSS()) module.exports = withOffline()

@ -23,6 +23,7 @@
"codemirror": "^5.36.0", "codemirror": "^5.36.0",
"codemirror-graphql": "^0.6.12", "codemirror-graphql": "^0.6.12",
"codemirror-mode-elixir": "^1.1.1", "codemirror-mode-elixir": "^1.1.1",
"compression": "^1.7.3",
"dom-to-image": "^2.5.2", "dom-to-image": "^2.5.2",
"downshift": "^2.0.0", "downshift": "^2.0.0",
"dropperx": "0.2.1", "dropperx": "0.2.1",
@ -57,7 +58,6 @@
"unsplash-js": "^4.8.0" "unsplash-js": "^4.8.0"
}, },
"devDependencies": { "devDependencies": {
"@zeit/next-css": "^0.2.0",
"all-contributors-cli": "^5.0.0", "all-contributors-cli": "^5.0.0",
"babel-eslint": "^8.2.3", "babel-eslint": "^8.2.3",
"cypress": "^3.0.0", "cypress": "^3.0.0",

@ -1,5 +1,6 @@
const path = require('path') const path = require('path')
const express = require('express') const express = require('express')
const compression = require('compression')
const morgan = require('morgan') const morgan = require('morgan')
const bodyParser = require('body-parser') const bodyParser = require('body-parser')
const next = require('next') const next = require('next')
@ -46,6 +47,8 @@ app
server.use(morgan('tiny')) server.use(morgan('tiny'))
} }
server.use(compression())
const filePath = path.join(__dirname, '.next', 'service-worker.js') const filePath = path.join(__dirname, '.next', 'service-worker.js')
server.get('/service-worker.js', (req, res) => app.serveStatic(req, res, filePath)) server.get('/service-worker.js', (req, res) => app.serveStatic(req, res, filePath))
// api endpoints // api endpoints

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save