1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00
This commit is contained in:
nkzawa 2016-10-24 01:42:31 +09:00
commit 7dfc298859
16 changed files with 103 additions and 119 deletions

View file

@ -40,21 +40,24 @@ That means pages never load unneccessary code!
### CSS ### CSS
We use [Aphrodite](https://github.com/Khan/aphrodite) to provide a great built-in solution for CSS modularization We use [glamor](https://github.com/threepointone/glamor) to provide a great built-in solution for CSS isolation and modularization without trading off any CSS features
```jsx ```jsx
import React from 'react' import React from 'react'
import { css, StyleSheet } from 'next/css' import { style } from 'next/css'
export default () => ( export default () => (
<div className={ css(styles.main) }> <div className={style}>
Hello world Hello world
</div> </div>
) )
const styles = StyleSheet.create({ const style = style({
main: { main: {
background: 'red', background: 'red',
':hover': {
background: 'gray'
}
'@media (max-width: 600px)': { '@media (max-width: 600px)': {
background: 'blue' background: 'blue'
} }
@ -80,9 +83,9 @@ export default () => (
) )
``` ```
### Stateful components ### Lifecycle components
When state, lifecycle hooks or initial data population you can export a `React.Component`: When you need state, lifecycle hooks or **initial data population** you can export a `React.Component`:
```jsx ```jsx
import React from 'react' import React from 'react'
@ -92,7 +95,6 @@ export default class extends React.Component {
? { userAgent: req.headers.userAgent } ? { userAgent: req.headers.userAgent }
: { userAgent: navigator.userAgent } : { userAgent: navigator.userAgent }
} }
render () { render () {
return <div> return <div>
Hello World {this.props.userAgent} Hello World {this.props.userAgent}
@ -160,16 +162,16 @@ export default class Error extends React.Component {
} }
``` ```
### Production deployment ## Production deployment
To deploy, run: To deploy, instead of running `next`, you probably want to build ahead of time. Therefore, building and starting are separate commands:
```bash ```bash
next build next build
next start next start
``` ```
For example, to deploy with `now` a `package.json` like follows is recommended: For example, to deploy with [`now`](https://zeit.co/now) a `package.json` like follows is recommended:
```json ```json
{ {
@ -185,7 +187,11 @@ For example, to deploy with `now` a `package.json` like follows is recommended:
} }
``` ```
### In progress Then run `now` and enjoy!
Note: we recommend putting `.next` in `.npmignore` or `.gitigore`. Otherwise, use `files` or `now.files` to opt-into a whitelist of files you want to deploy (and obviously exclude `.next`)
## FAQ
The following tasks are planned and part of our roadmap The following tasks are planned and part of our roadmap

View file

@ -1,11 +1,11 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import { StyleSheet, css } from 'next/css' import { style } from 'next/css'
export default class CrazyCSS extends Component { export default class CrazyCSS extends Component {
spans () { spans () {
const out = [] const out = []
for (let i = 0; i < 1000; i++) { for (let i = 0; i < 1000; i++) {
out.push(<span key={i} class={css(styles[`padding-${i}`])}>This is ${i}</span>) out.push(<span key={i} class={spanStyles[`padding-${i}`]}>This is ${i}</span>)
} }
return out return out
} }
@ -17,7 +17,5 @@ export default class CrazyCSS extends Component {
const spanStyles = {} const spanStyles = {}
for (let i = 0; i < 1000; i++) { for (let i = 0; i < 1000; i++) {
spanStyles[`padding-${i}`] = { padding: i } spanStyles[`padding-${i}`] = style({ padding: i })
} }
const styles = StyleSheet.create(spanStyles)

View file

@ -1,13 +1,13 @@
import { createElement } from 'react' import { createElement } from 'react'
import { render } from 'react-dom' import { render } from 'react-dom'
import HeadManager from './head-manager' import HeadManager from './head-manager'
import { StyleSheet } from '../lib/css' import { rehydrate } from '../lib/css'
import Router from '../lib/router' import Router from '../lib/router'
import DefaultApp from '../lib/app' import DefaultApp from '../lib/app'
import evalScript from '../lib/eval-script' import evalScript from '../lib/eval-script'
const { const {
__NEXT_DATA__: { app, component, props, classNames, err } __NEXT_DATA__: { app, component, props, ids, err }
} = window } = window
const App = app ? evalScript(app).default : DefaultApp const App = app ? evalScript(app).default : DefaultApp
@ -19,5 +19,5 @@ const headManager = new HeadManager()
const container = document.getElementById('__next') const container = document.getElementById('__next')
const appProps = { Component, props, router, headManager } const appProps = { Component, props, router, headManager }
StyleSheet.rehydrate(classNames) rehydrate(ids)
render(createElement(App, appProps), container) render(createElement(App, appProps), container)

View file

@ -1,21 +1,19 @@
import React from 'react' import React from 'react'
import { css, StyleSheet } from 'next/css' import { style } from 'next/css'
export default () => ( export default () => (
<div className={css(styles.main)}> <div className={styles}>
<p>Hello World</p> <p>Hello World</p>
</div> </div>
) )
const styles = StyleSheet.create({ const styles = style({
main: { font: '15px Helvetica, Arial, sans-serif',
font: '15px Helvetica, Arial, sans-serif', background: '#eee',
background: '#eee', padding: '100px',
padding: '100px', textAlign: 'center',
textAlign: 'center', transition: '100ms ease-in background',
transition: '100ms ease-in background', ':hover': {
':hover': { background: '#ccc'
background: '#ccc'
}
} }
}) })

View file

@ -1,13 +1,11 @@
import React from 'react' import React from 'react'
import { css, StyleSheet } from 'next/css' import { style } from 'next/css'
export default ({ children }) => ( export default ({ children }) => (
<p className={css(styles.main)}>{children}</p> <p className={styles}>{children}</p>
) )
const styles = StyleSheet.create({ const styles = style({
main: { font: '13px Helvetica, Arial',
font: '13px Helvetica, Arial', margin: '10px 0'
margin: '10px 0'
}
}) })

View file

@ -1,23 +1,21 @@
import React from 'react' import React from 'react'
import { css, StyleSheet } from 'next/css' import { style } from 'next/css'
export default ({ title, children }) => ( export default ({ title, children }) => (
<div className={css(styles.main)}> <div className={mainStyle}>
<h1 className={css(styles.title)}>{ title }</h1> <h1 className={titleStyle}>{ title }</h1>
{ children } { children }
</div> </div>
) )
const styles = StyleSheet.create({ const mainStyle = style({
main: { font: '15px Helvetica, Arial',
font: '15px Helvetica, Arial', border: '1px solid #eee',
border: '1px solid #eee', padding: '0 10px'
padding: '0 10px' })
},
const titleStyle = style({
title: { fontSize: '16px',
fontSize: '16px', fontWeight: 'bold',
fontWeight: 'bold', margin: '10px 0'
margin: '10px 0'
}
}) })

View file

@ -1,10 +1,10 @@
import React from 'react' import React from 'react'
import P from '../components/paragraph' import P from '../components/paragraph'
import Post from '../components/post' import Post from '../components/post'
import { css, StyleSheet } from 'next/css' import { style } from 'next/css'
export default () => ( export default () => (
<div className={css(styles.main)}> <div className={styles.main}>
<Post title='My first blog post'> <Post title='My first blog post'>
<P>Hello there</P> <P>Hello there</P>
<P>This is an example of a componentized blog post</P> <P>This is an example of a componentized blog post</P>
@ -26,23 +26,23 @@ export default () => (
</div> </div>
) )
const Hr = () => <hr className={css(styles.hr)} /> const Hr = () => <hr className={styles.hr} />
const styles = StyleSheet.create({ const styles = {
main: { main: style({
margin: 'auto', margin: 'auto',
maxWidth: '420px', maxWidth: '420px',
padding: '10px' padding: '10px'
}, }),
hr: { hr: style({
width: '100px', width: '100px',
borderWidth: 0, borderWidth: 0,
margin: '20px auto', margin: '20px auto',
textAlign: 'center', textAlign: 'center',
':before': { '::before': {
content: '"***"', content: '"***"',
color: '#ccc' color: '#ccc'
} }
} })
}) }

View file

@ -1 +1 @@
module.exports = require('aphrodite') module.exports = require('glamor')

View file

@ -5,7 +5,7 @@ export default ({ head, css, html, data, dev, staticMarkup }) => {
return <html> return <html>
<head> <head>
{(head || []).map((h, i) => React.cloneElement(h, { key: i }))} {(head || []).map((h, i) => React.cloneElement(h, { key: i }))}
<style data-aphrodite='' dangerouslySetInnerHTML={{ __html: css.content }} /> <style dangerouslySetInnerHTML={{ __html: css }} />
</head> </head>
<body> <body>
<div id='__next' dangerouslySetInnerHTML={{ __html: html }} /> <div id='__next' dangerouslySetInnerHTML={{ __html: html }} />

View file

@ -2,7 +2,7 @@ import React from 'react'
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
import App from '../lib/app' import App from '../lib/app'
import Link from '../lib/link' import Link from '../lib/link'
import Css from '../lib/css' import * as Css from '../lib/css'
import Head from '../lib/head' import Head from '../lib/head'
const modules = new Map([ const modules = new Map([

View file

@ -17,7 +17,6 @@
"precommit": "npm run lint" "precommit": "npm run lint"
}, },
"dependencies": { "dependencies": {
"aphrodite": "0.5.0",
"babel-core": "6.17.0", "babel-core": "6.17.0",
"babel-generator": "6.17.0", "babel-generator": "6.17.0",
"babel-loader": "6.2.5", "babel-loader": "6.2.5",
@ -31,6 +30,7 @@
"babel-runtime": "6.11.6", "babel-runtime": "6.11.6",
"cross-spawn": "4.0.2", "cross-spawn": "4.0.2",
"del": "2.2.2", "del": "2.2.2",
"glamor": "2.17.10",
"glob-promise": "1.0.6", "glob-promise": "1.0.6",
"htmlescape": "1.1.1", "htmlescape": "1.1.1",
"loader-utils": "0.2.16", "loader-utils": "0.2.16",

View file

@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
import stripAnsi from 'strip-ansi' import stripAnsi from 'strip-ansi'
import Head from 'next/head' import Head from 'next/head'
import { css, StyleSheet } from 'next/css' import { style } from 'next/css'
export default class ErrorDebug extends React.Component { export default class ErrorDebug extends React.Component {
static getInitialProps ({ err }) { static getInitialProps ({ err }) {
@ -12,7 +12,7 @@ export default class ErrorDebug extends React.Component {
render () { render () {
const { message, path } = this.props const { message, path } = this.props
return <div className={css(styles.errorDebug)}> return <div className={styles.errorDebug}>
<Head> <Head>
<style dangerouslySetInnerHTML={{ __html: ` <style dangerouslySetInnerHTML={{ __html: `
body { body {
@ -21,48 +21,36 @@ export default class ErrorDebug extends React.Component {
} }
`}} /> `}} />
</Head> </Head>
<div className={css(styles.heading)}>Error in {path}</div> <div className={styles.heading}>Error in {path}</div>
<pre className={css(styles.message)}>{stripAnsi(message)}</pre> <pre className={styles.message}>{stripAnsi(message)}</pre>
</div> </div>
} }
} }
const styles = StyleSheet.create({ const styles = {
body: { body: style({
background: '#dc0067', background: '#dc0067',
margin: 0 margin: 0
}, }),
errorDebug: { errorDebug: style({
height: '100%', height: '100%',
padding: '16px', padding: '16px',
boxSizing: 'border-box' boxSizing: 'border-box'
}, }),
message: { message: style({
fontFamily: 'menlo-regular', fontFamily: 'menlo-regular',
fontSize: '10px', fontSize: '10px',
color: '#fff', color: '#fff',
margin: 0 margin: 0
}, }),
heading: { heading: style({
fontFamily: 'sans-serif', fontFamily: 'sans-serif',
fontSize: '13px', fontSize: '13px',
fontWeight: 'bold', fontWeight: 'bold',
color: '#ff90c6', color: '#ff90c6',
marginBottom: '20px' marginBottom: '20px'
}, })
}
token: {
backgroundColor: '#000'
},
marker: {
color: '#000'
},
dim: {
color: '#e85b9b'
}
})

View file

@ -1,5 +1,5 @@
import React from 'react' import React from 'react'
import { css, StyleSheet } from 'next/css' import { style, merge } from 'next/css'
export default class Error extends React.Component { export default class Error extends React.Component {
static getInitialProps ({ res, xhr }) { static getInitialProps ({ res, xhr }) {
@ -11,19 +11,19 @@ export default class Error extends React.Component {
const { statusCode } = this.props const { statusCode } = this.props
const title = statusCode === 404 ? 'This page could not be found' : 'Internal Server Error' const title = statusCode === 404 ? 'This page could not be found' : 'Internal Server Error'
return <div className={css(styles.error, styles['error_' + statusCode])}> return <div className={merge(styles.error, styles['error_' + statusCode])}>
<div className={css(styles.text)}> <div className={styles.text}>
<h1 className={css(styles.h1)}>{statusCode}</h1> <h1 className={styles.h1}>{statusCode}</h1>
<div className={css(styles.desc)}> <div className={styles.desc}>
<h2 className={css(styles.h2)}>{title}.</h2> <h2 className={styles.h2}>{title}.</h2>
</div> </div>
</div> </div>
</div> </div>
} }
} }
const styles = StyleSheet.create({ const styles = {
error: { error: style({
color: '#000', color: '#000',
background: '#fff', background: '#fff',
top: 0, top: 0,
@ -34,17 +34,17 @@ const styles = StyleSheet.create({
fontFamily: '"SF UI Text", "Helvetica Neue", "Lucida Grande"', fontFamily: '"SF UI Text", "Helvetica Neue", "Lucida Grande"',
textAlign: 'center', textAlign: 'center',
paddingTop: '20%' paddingTop: '20%'
}, }),
desc: { desc: style({
display: 'inline-block', display: 'inline-block',
textAlign: 'left', textAlign: 'left',
lineHeight: '49px', lineHeight: '49px',
height: '49px', height: '49px',
verticalAlign: 'middle' verticalAlign: 'middle'
}, }),
h1: { h1: style({
display: 'inline-block', display: 'inline-block',
borderRight: '1px solid rgba(0, 0, 0,.3)', borderRight: '1px solid rgba(0, 0, 0,.3)',
margin: 0, margin: 0,
@ -53,12 +53,12 @@ const styles = StyleSheet.create({
fontSize: '24px', fontSize: '24px',
fontWeight: 500, fontWeight: 500,
verticalAlign: 'top' verticalAlign: 'top'
}, }),
h2: { h2: style({
fontSize: '14px', fontSize: '14px',
fontWeight: 'normal', fontWeight: 'normal',
margin: 0, margin: 0,
padding: 0 padding: 0
} })
}) }

View file

@ -8,7 +8,7 @@ import Router from '../lib/router'
import Document from '../lib/document' import Document from '../lib/document'
import Head from '../lib/head' import Head from '../lib/head'
import App from '../lib/app' import App from '../lib/app'
import { StyleSheetServer } from '../lib/css' import { renderStatic } from 'glamor/server'
export async function render (url, ctx = {}, { export async function render (url, ctx = {}, {
dir = process.cwd(), dir = process.cwd(),
@ -22,7 +22,7 @@ export async function render (url, ctx = {}, {
const props = await (Component.getInitialProps ? Component.getInitialProps(ctx) : {}) const props = await (Component.getInitialProps ? Component.getInitialProps(ctx) : {})
const component = await read(join(dir, '.next', 'bundles', 'pages', path)) const component = await read(join(dir, '.next', 'bundles', 'pages', path))
const { html, css } = StyleSheetServer.renderStatic(() => { const { html, css, ids } = renderStatic(() => {
const app = createElement(App, { const app = createElement(App, {
Component, Component,
props, props,
@ -41,7 +41,7 @@ export async function render (url, ctx = {}, {
data: { data: {
component, component,
props, props,
classNames: css.renderedClassNames, ids: ids,
err: ctx.err ? errorToJSON(ctx.err) : null err: ctx.err ? errorToJSON(ctx.err) : null
}, },
hotReload: false, hotReload: false,

View file

@ -1,8 +1,6 @@
import React from 'react' import React from 'react'
import { StyleSheet, css } from 'next/css' import { style } from 'next/css'
export default () => <div className={css(styles.red)}>This is red</div> export default () => <div className={styles}>This is red</div>
const styles = StyleSheet.create({ const styles = style({ color: 'red' })
red: { color: 'red' }
})

View file

@ -14,8 +14,8 @@ test(async t => {
test(async t => { test(async t => {
const html = await render('/css') const html = await render('/css')
t.true(html.includes('<style data-aphrodite="">.red_im3wl1{color:red !important;}</style>')) t.true(html.includes('.css-im3wl1'))
t.true(html.includes('<div class="red_im3wl1">This is red</div>')) t.true(html.includes('<div class="css-im3wl1">This is red</div>'))
}) })
test(async t => { test(async t => {