1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00

Merge master into dynamic-import.

This commit is contained in:
Arunoda Susiripala 2017-04-27 08:48:43 -07:00
commit 686dd4c4dd
76 changed files with 1997 additions and 1249 deletions

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/basic-css)
# Basic CSS example

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/custom-server-express)
# Custom Express Server example

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/custom-server-hapi)
# Custom server using Hapi example

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/custom-server-koa)
# Custom Koa Server example

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/custom-server)
# Custom server example

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/data-fetch)
# Data fetch example

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/head-elements)
# Head elements example

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/hello-world)
# Hello World example

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/layout-component)
# Layout component example

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/nested-components)
# Example app using nested components

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/parameterized-routing)
# Parametrized routes example (dynamic routing)

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/progressive-render)
# Example app implementing progressive server-side render
## How to use

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/shared-modules)
# Example app using shared modules
## How to use

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/ssr-caching)
# Example app where it caches SSR'ed pages in the memory

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/svg-components)
# SVG components example

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/using-inferno)
# Hello World example

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/using-preact)
# Hello World example

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/using-router)
# Example app utilizing next/router for routing
## How to use

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-amp)
# Google AMP

View file

@ -1,13 +1,16 @@
import Document, { Head } from 'next/document'
import { DOMProperty } from 'react-dom/lib/ReactInjection'
import { properties as DOMProperties } from 'react-dom/lib/DOMProperty'
// By default React limit the set of valid DOM elements and attributes
// (https://github.com/facebook/react/issues/140) this config whitelist
// Amp elements/attributes
DOMProperty.injectDOMPropertyConfig({
Properties: { amp: DOMProperty.MUST_USE_ATTRIBUTE },
isCustomAttribute: attributeName => attributeName.startsWith('amp-')
})
if (typeof DOMProperties.amp === 'undefined') {
DOMProperty.injectDOMPropertyConfig({
Properties: { amp: DOMProperty.MUST_USE_ATTRIBUTE },
isCustomAttribute: attributeName => attributeName.startsWith('amp-')
})
}
export default class MyDocument extends Document {
render () {

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-aphrodite)
# Example app with aphrodite

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-apollo-and-redux)
# Apollo & Redux Example
## How to use

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-apollo)
# Apollo Example
## Demo

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-custom-babel-config)
# Example app using custom babel config
Download the example [or clone the repo](https://github.com/zeit/next.js):

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-cxs)
# Example app with cxs

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-external-scoped-css)
## Scoped Style with external CSS file
The motivation for this example is using scoped css from external files and in the end generate a compiled static `.css` file to use in production..

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-fela)
# Example app with Fela

View file

@ -20,7 +20,10 @@ export default class MyDocument extends Document {
<html>
<Head>
<title>My page</title>
<style id='fela-stylesheet'>{this.props.css}</style>
<style
dangerouslySetInnerHTML={{ __html: this.props.css }}
id='fela-stylesheet'
/>
</Head>
<body>
<Main />

View file

@ -2,6 +2,7 @@ import { createComponent } from 'react-fela'
import Page from '../layout'
const title = ({ size }) => ({
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
fontSize: size + 'px',
color: 'red'
})

View file

@ -0,0 +1,34 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-firebase)
# With Firebase example
## How to use
Download the example [or clone the repo](https://github.com/zeit/next.js):
```bash
curl https://codeload.github.com/zeit/next.js/tar.gz/master | tar -xz --strip=2 next.js-master/examples/with-firebase
cd with-firebase
```
Set up firebase:
- create a project
- get your service account credentials and client credentials and set both in firebaseCredentials.js
- set your firebase database url in server.js
- on the firebase Authentication console, select Google as your provider
Install it and run:
```bash
npm install
npm run dev
```
Deploy it to the cloud with [now](https://zeit.co/now) ([download](https://zeit.co/download))
```bash
now
```
## The idea behind the example
The goal is to authenticate users with firebase and store their auth token in sessions. A logged in user will see their messages on page load and then be able to post new messages.

View file

@ -0,0 +1,8 @@
module.exports = {
clientCredentials: {
// TODO firebase client config
},
serverCredentials: {
// TODO service account json here
}
}

View file

@ -0,0 +1,19 @@
{
"scripts": {
"dev": "node server.js",
"build": "next build",
"start": "NODE_ENV=production node server.js"
},
"dependencies": {
"body-parser": "^1.17.1",
"express": "^4.14.0",
"express-session": "^1.15.2",
"firebase": "^3.7.5",
"firebase-admin": "^4.2.0",
"isomorphic-fetch": "2.2.1",
"next": "latest",
"react": "^15.4.2",
"react-dom": "^15.4.2",
"session-file-store": "^1.0.0"
}
}

View file

@ -0,0 +1,115 @@
import React, { Component } from 'react'
import firebase from 'firebase'
import 'isomorphic-fetch'
import { clientCredentials } from '../firebaseCredentials'
export default class Index extends Component {
static async getInitialProps ({req, query}) {
const user = req && req.session ? req.session.decodedToken : null
const snap = await req.firebaseServer.database().ref('messages').once('value')
return { user, messages: snap.val() }
}
constructor (props) {
super(props)
this.state = {
user: this.props.user,
value: '',
messages: this.props.messages
}
this.addDbListener = this.addDbListener.bind(this)
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
componentDidMount () {
firebase.initializeApp(clientCredentials)
if (this.state.user) this.addDbListener()
firebase.auth().onAuthStateChanged(user => {
if (user) {
this.setState({ user: user })
return user.getToken()
.then((token) => {
// eslint-disable-next-line no-undef
return fetch('/api/login', {
method: 'POST',
// eslint-disable-next-line no-undef
headers: new Headers({ 'Content-Type': 'application/json' }),
credentials: 'same-origin',
body: JSON.stringify({ token })
})
}).then((res) => this.addDbListener())
} else {
this.setState({ user: null })
// eslint-disable-next-line no-undef
fetch('/api/logout', {
method: 'POST',
credentials: 'same-origin'
}).then(() => firebase.database().ref('messages').off())
}
})
}
addDbListener () {
firebase.database().ref('messages').on('value', snap => {
const messages = snap.val()
if (messages) this.setState({ messages })
})
}
handleChange (event) {
this.setState({ value: event.target.value })
}
handleSubmit (event) {
event.preventDefault()
const date = new Date().getTime()
firebase.database().ref(`messages/${date}`).set({
id: date,
text: this.state.value
})
this.setState({ value: '' })
}
handleLogin () {
firebase.auth().signInWithPopup(new firebase.auth.GoogleAuthProvider())
}
handleLogout () {
firebase.auth().signOut()
}
render () {
const { user, value, messages } = this.state
return <div>
{
user
? <button onClick={this.handleLogout}>Logout</button>
: <button onClick={this.handleLogin}>Login</button>
}
{
user &&
<div>
<form onSubmit={this.handleSubmit}>
<input
type={'text'}
onChange={this.handleChange}
placeholder={'add message'}
value={value}
/>
</form>
<ul>
{
messages &&
Object.keys(messages).map(key => <li key={key}>{messages[key].text}</li>)
}
</ul>
</div>
}
</div>
}
}

View file

@ -0,0 +1,63 @@
const express = require('express')
const bodyParser = require('body-parser')
const session = require('express-session')
const FileStore = require('session-file-store')(session)
const next = require('next')
const admin = require('firebase-admin')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
const firebase = admin.initializeApp({
credential: admin.credential.cert(require('./firebaseCredentials').serverCredentials),
databaseURL: '' // TODO database URL goes here
}, 'server')
app.prepare()
.then(() => {
const server = express()
server.use(bodyParser.json())
server.use(session({
secret: 'geheimnis',
saveUninitialized: true,
store: new FileStore({path: '/tmp/sessions', secret: 'geheimnis'}),
resave: false,
rolling: true,
httpOnly: true,
cookie: { maxAge: 604800000 } // week
}))
server.use((req, res, next) => {
req.firebaseServer = firebase
next()
})
server.post('/api/login', (req, res) => {
if (!req.body) return res.sendStatus(400)
const token = req.body.token
firebase.auth().verifyIdToken(token)
.then((decodedToken) => {
req.session.decodedToken = decodedToken
return decodedToken
})
.then((decodedToken) => res.json({ status: true, decodedToken }))
.catch((error) => res.json({ error }))
})
server.post('/api/logout', (req, res) => {
req.session.decodedToken = null
res.json({ status: true })
})
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(3000, (err) => {
if (err) throw err
console.log('> Ready on http://localhost:3000')
})
})

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-flow)
# Example app with [Flow](https://flowtype.org/)
## How to use

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-glamor)
# Example app with glamor

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-glamorous)
# Example app with [glamorous](https://github.com/kentcdodds/glamorous)

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-global-stylesheet)
# Global Stylesheet example
This is an example of how you can include a global stylesheet in a next.js webapp.

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-jest)
# Example app with jest tests
## How to use

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-loading)
# Example app with page loading indicator
## How to use

View file

@ -0,0 +1,29 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-material-ui)
# Material-UI example
## How to use
Download the example [or clone the repo](https://github.com/zeit/next.js):
```bash
curl https://codeload.github.com/zeit/next.js/tar.gz/master | tar -xz --strip=2 next.js-master/examples/with-material-ui
cd with-material-ui
```
Install it and run:
```bash
npm install
npm run dev
```
Deploy it to the cloud with [now](https://zeit.co/now) ([download](https://zeit.co/download))
```bash
now
```
## The idea behind the example
This example features how you use [material-ui](https://github.com/callemall/material-ui) (Material components that implement Google's Material Design) with Next.js.

View file

@ -0,0 +1,14 @@
{
"dependencies": {
"material-ui": "^0.17.4",
"next": "latest",
"react": "^15.5.4",
"react-dom": "^15.5.4",
"react-tap-event-plugin": "^2.0.1"
},
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
}
}

View file

@ -0,0 +1,97 @@
import React, {Component} from 'react'
import RaisedButton from 'material-ui/RaisedButton'
import Dialog from 'material-ui/Dialog'
import {deepOrange500} from 'material-ui/styles/colors'
import FlatButton from 'material-ui/FlatButton'
import getMuiTheme from 'material-ui/styles/getMuiTheme'
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
import injectTapEventPlugin from 'react-tap-event-plugin'
// Needed for onTouchTap
// http://stackoverflow.com/a/34015469/988941
try {
if (typeof window !== 'undefined') {
injectTapEventPlugin()
}
} catch (e) {
// do nothing
}
const styles = {
container: {
textAlign: 'center',
paddingTop: 200
}
}
const _muiTheme = getMuiTheme({
palette: {
accent1Color: deepOrange500
}
})
class Main extends Component {
static getInitialProps ({ req }) {
const userAgent = req ? req.headers['user-agent'] : navigator.userAgent
const isServer = !!req
return {isServer, userAgent}
}
constructor (props, context) {
super(props, context)
this.state = {
open: false
}
}
handleRequestClose = () => {
this.setState({
open: false
})
}
handleTouchTap = () => {
this.setState({
open: true
})
}
render () {
const standardActions = (
<FlatButton
label='Ok'
primary={Boolean(true)}
onTouchTap={this.handleRequestClose}
/>
)
const { userAgent } = this.props
/* https://github.com/callemall/material-ui/issues/3336 */
const muiTheme = getMuiTheme(getMuiTheme({userAgent: userAgent}), _muiTheme)
return (
<MuiThemeProvider muiTheme={muiTheme}>
<div style={styles.container}>
<Dialog
open={this.state.open}
title='Super Secret Password'
actions={standardActions}
onRequestClose={this.handleRequestClose}
>
1-2-3-4-5
</Dialog>
<h1>Material-UI</h1>
<h2>example project</h2>
<RaisedButton
label='Super Secret Password'
secondary={Boolean(true)}
onTouchTap={this.handleTouchTap}
/>
</div>
</MuiThemeProvider>
)
}
}
export default Main

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-mobx)
# MobX example

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-next-routes)
# Named routes example ([next-routes](https://github.com/fridays/next-routes))
## How to use

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-prefetching)
# Example app with prefetching pages
## How to use

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-pretty-url-routing)
# Example app with pretty url routing

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-react-helmet)
# react-helmet example

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-react-intl)
# Example app with [React Intl][]
## How to use

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-react-md)
# Example app with react-md

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-redux)
# Redux example

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-refnux)
# Refnux example

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-scoped-stylesheets-and-postcss)
# Scoped stylesheets with PostCSS example
This is an example of using scoped stylesheets and PostCSS, heavily influenced by @davibe's [`with-global-stylesheet`](https://github.com/zeit/next.js/tree/master/examples/with-global-stylesheet).

View file

@ -0,0 +1,30 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-semantic-ui)
# Semantic UI example
## How to use
Download the example [or clone the repo](https://github.com/zeit/next.js):
```bash
curl https://codeload.github.com/zeit/next.js/tar.gz/master | tar -xz --strip=2 next.js-master/examples/with-semantic-ui
cd with-semantic-ui
```
Install it and run:
```bash
npm install
npm run dev
```
Deploy it to the cloud with [now](https://zeit.co/now) ([download](https://zeit.co/download))
```bash
now
```
## The idea behind the example
This example shows how to use Next.js along with [Semantic UI React](http://react.semantic-ui.com). This is intended to show the integration of this
UI toolkit with the Framework,

View file

@ -0,0 +1,17 @@
{
"name": "with-semantic-ui",
"version": "1.0.0",
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
},
"dependencies": {
"next": "latest",
"react": "^15.4.2",
"react-dom": "^15.4.2",
"semantic-ui-react": "^0.68.0"
},
"author": "",
"license": "ISC"
}

View file

@ -0,0 +1,38 @@
import Head from 'next/head'
import { Modal, Header, Button, List } from 'semantic-ui-react'
export default () => (
<div>
<Head>
<link rel='stylesheet' href='//cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.2/semantic.min.css' />
</Head>
<Modal trigger={<Button>Show Modal</Button>}>
<Modal.Header>Select a Photo</Modal.Header>
<Modal.Content image>
<Modal.Description>
<Header>Default Profile Image</Header>
<p>We've found the following gravatar image associated with your e-mail address.</p>
<p>Is it okay to use this photo?</p>
</Modal.Description>
</Modal.Content>
</Modal>
<List vertical relaxed>
<List.Item>
<List.Content>
<List.Header as='a'>Next.js</List.Header>
</List.Content>
</List.Item>
<List.Item>
<List.Content>
<List.Header as='a'>React</List.Header>
</List.Content>
</List.Item>
<List.Item>
<List.Content>
<List.Header as='a'>Vue.js</List.Header>
</List.Content>
</List.Item>
</List>
</div>
)

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-shallow-routing)
# Shallow Routing Example

View file

@ -0,0 +1,25 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-socket.io)
# Socket.io example
## How to use
Download the example [or clone the repo](https://github.com/zeit/next.js):
```bash
curl https://codeload.github.com/zeit/next.js/tar.gz/master | tar -xz --strip=2 next.js-master/examples/with-socket.io
cd with-socket.io
```
Install it and run:
```bash
npm install
npm run dev
```
## The idea behind the example
This example show how to use [socket.io](https://socket.io/) inside a Next.js application. It uses `getInitialProps` to fetch the old messages from a HTTP endpoint as if it was a Rest API. The example combine the WebSocket server with the Next server, in a production application you should split them as different services.
**Example:** [https://next-socket-io.now.sh/](https://next-socket-io.now.sh/)

View file

@ -0,0 +1,16 @@
{
"dependencies": {
"express": "^4.15.2",
"isomorphic-fetch": "^2.2.1",
"next": "latest",
"react": "^15.5.4",
"react-dom": "^15.5.4",
"socket.io": "^1.7.3",
"socket.io-client": "^1.7.3"
},
"scripts": {
"dev": "node server.js",
"build": "next build",
"start": "NODE_ENV=production node server.js"
}
}

View file

@ -0,0 +1,88 @@
import { Component } from 'react'
import io from 'socket.io-client'
import fetch from 'isomorphic-fetch'
class HomePage extends Component {
// fetch old messages data from the server
static async getInitialProps ({ req }) {
const response = await fetch('http://localhost:3000/messages')
const messages = await response.json()
return { messages }
}
static defaultProps = {
messages: []
}
// init state with the prefetched messages
state = {
field: '',
messages: this.props.messages
}
// connect to WS server and listen event
componentDidMount () {
this.socket = io('http://localhost:3000/')
this.socket.on('message', this.handleMessage)
}
// close socket connection
componentWillUnmount () {
this.socket.off('message', this.handleMessage)
this.socket.close()
}
// add messages from server to the state
handleMessage = (message) => {
this.setState(state => ({ messages: state.messages.concat(message) }))
}
handleChange = event => {
this.setState({ field: event.target.value })
}
// send messages to server and add them to the state
handleSubmit = event => {
event.preventDefault()
// create message object
const message = {
id: (new Date()).getTime(),
value: this.state.field
}
// send object to WS server
this.socket.emit('message', message)
// add it to state and clean current input value
this.setState(state => ({
field: '',
messages: state.messages.concat(message)
}))
}
render () {
return (
<main>
<div>
<ul>
{this.state.messages.map(message =>
<li key={message.id}>{message.value}</li>
)}
</ul>
<form onSubmit={this.handleSubmit}>
<input
onChange={this.handleChange}
type='text'
placeholder='Hello world!'
value={this.state.field}
/>
<button>Send</button>
</form>
</div>
</main>
)
}
}
export default HomePage

View file

@ -0,0 +1,34 @@
const app = require('express')()
const server = require('http').Server(app)
const io = require('socket.io')(server)
const next = require('next')
const dev = process.env.NODE_ENV !== 'production'
const nextApp = next({ dev })
const nextHandler = nextApp.getRequestHandler()
// fake DB
const messages = []
// socket.io server
io.on('connection', socket => {
socket.on('message', (data) => {
messages.push(data)
socket.broadcast.emit('message', data)
})
})
nextApp.prepare().then(() => {
app.get('/messages', (req, res) => {
res.json(messages)
})
app.get('*', (req, res) => {
return nextHandler(req, res)
})
server.listen(3000, (err) => {
if (err) throw err
console.log('> Ready on http://localhost:3000')
})
})

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-styled-components)
# Example app with styled-components

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-styled-jsx-postcss)
# Example app with styled-jsx-postcss

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-styletron)
# Example app with styletron

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-typescript)
# TypeScript Next.js example
This is a really simple project that show the usage of Next.js with TypeScript.

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-universal-configuration)
# With universal configuration
@ -29,4 +30,5 @@ This example show how to set custom environment variables for your application b
## Caveats
Because a babel plugin is used the output is cached in `node_modules/.cache` by `babel-loader`. When modifying the configuration you will have to manually clear this cache to make changes visible.
- Because a babel plugin is used the output is cached in `node_modules/.cache` by `babel-loader`. When modifying the configuration you will have to manually clear this cache to make changes visible. Alternately, you may skip caching for `babel-loader` as shown [here](https://github.com/zeit/next.js/issues/1103#issuecomment-279529809).
- This example sets the environment configuration at build time, meaning the same build might not be used in e.g. both staging and production. For a solution which sets the environment at runtime, see [here](https://github.com/zeit/next.js/issues/1488#issuecomment-289108931).

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-url-object-routing)
# URL object routing
## How to use

View file

@ -5,7 +5,7 @@
"start": "NODE_ENV=production node server.js"
},
"dependencies": {
"next": "beta",
"next": "latest",
"path-match": "1.2.4",
"react": "^15.4.2",
"react-dom": "^15.4.2"

View file

@ -1,3 +1,4 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-webpack-bundle-analyzer)
# Webpack Bundle Analyzer example

View file

@ -129,8 +129,8 @@ export default class Link extends Component {
function isLocal (href) {
const url = parse(href, false, true)
const origin = parse(getLocationOrigin(), false, true)
return (!url.host || !url.hostname) ||
(origin.host === url.host || origin.hostname === url.hostname)
return !url.host ||
(url.protocol === origin.protocol && url.host === origin.host)
}
const warnLink = execOnce(warn)

View file

@ -1,6 +1,6 @@
{
"name": "next",
"version": "2.1.1",
"version": "2.2.0",
"description": "Minimalistic framework for server-rendered React applications",
"main": "./dist/server/next.js",
"license": "MIT",
@ -45,19 +45,19 @@
"dependencies": {
"ansi-html": "0.0.7",
"babel-core": "6.24.0",
"babel-generator": "6.24.0",
"babel-loader": "6.4.1",
"babel-generator": "6.24.1",
"babel-loader": "7.0.0",
"babel-plugin-module-resolver": "2.6.2",
"babel-plugin-react-require": "3.0.0",
"babel-plugin-syntax-dynamic-import": "6.18.0",
"babel-plugin-transform-class-properties": "6.22.0",
"babel-plugin-transform-es2015-modules-commonjs": "6.24.0",
"babel-plugin-transform-class-properties": "6.24.1",
"babel-plugin-transform-es2015-modules-commonjs": "6.24.1",
"babel-plugin-transform-object-rest-spread": "6.22.0",
"babel-plugin-transform-react-jsx-source": "6.22.0",
"babel-plugin-transform-react-remove-prop-types": "0.4.0",
"babel-plugin-transform-react-remove-prop-types": "0.4.1",
"babel-plugin-transform-runtime": "6.22.0",
"babel-preset-env": "1.3.3",
"babel-preset-react": "6.23.0",
"babel-preset-react": "6.24.1",
"babel-runtime": "6.23.0",
"babel-template": "6.24.1",
"case-sensitive-paths-webpack-plugin": "2.0.0",
@ -75,7 +75,7 @@
"loader-utils": "1.1.0",
"md5-file": "3.1.1",
"minimist": "1.2.0",
"mitt": "1.1.0",
"mitt": "1.1.1",
"mkdirp-then": "1.2.0",
"mv": "2.1.1",
"mz": "2.6.0",
@ -83,7 +83,7 @@
"pkg-up": "1.0.0",
"prop-types": "15.5.7",
"react-hot-loader": "3.0.0-beta.6",
"send": "0.15.1",
"send": "0.15.2",
"source-map-support": "0.4.14",
"strip-ansi": "3.0.1",
"styled-jsx": "0.5.7",
@ -91,17 +91,17 @@
"unfetch": "2.1.2",
"url": "0.11.0",
"uuid": "3.0.1",
"webpack": "2.3.3",
"webpack-dev-middleware": "1.10.1",
"webpack": "2.4.0",
"webpack-dev-middleware": "1.10.2",
"webpack-hot-middleware": "2.18.0",
"write-file-webpack-plugin": "4.0.0"
"write-file-webpack-plugin": "4.0.2"
},
"devDependencies": {
"babel-eslint": "7.2.2",
"babel-eslint": "7.2.3",
"babel-jest": "18.0.0",
"babel-plugin-istanbul": "4.1.1",
"babel-plugin-transform-remove-strict-mode": "0.0.2",
"babel-preset-es2015": "6.24.0",
"babel-preset-es2015": "6.24.1",
"benchmark": "2.1.4",
"cheerio": "0.22.0",
"chromedriver": "2.29.0",

View file

@ -454,7 +454,7 @@ componentWillReceiveProps(nextProps) {
> ```js
> Router.push('/about?counter=10', '/about?counter=10', { shallow: true })
> ```
> Since that's a new page, it'll unload the current page, load the new one and call `getInitialProps` even we asked to do shallow routing.
> Since that's a new page, it'll unload the current page, load the new one and call `getInitialProps` even though we asked to do shallow routing.
### Prefetching Pages
@ -710,7 +710,7 @@ Here's an example `.babelrc` file:
To set up a CDN, you can set up the `assetPrefix` setting and configure your CDN's origin to resolve to the domain that Next.js is hosted on.
```js
const isProd = process.NODE_ENV === 'production'
const isProd = process.env.NODE_ENV === 'production'
module.exports = {
// You may only need to add assetPrefix in the production.
assetPrefix: isProd ? 'https://cdn.mydomain.com' : ''

View file

@ -148,7 +148,6 @@ export default async function createCompiler (dir, { dev = false, quiet = false,
const mainBabelOptions = {
cacheDirectory: true,
sourceMaps: dev ? 'both' : false,
presets: []
}
@ -249,7 +248,6 @@ export default async function createCompiler (dir, { dev = false, quiet = false,
options: {
babelrc: false,
cacheDirectory: true,
sourceMaps: dev ? 'both' : false,
presets: [require.resolve('./babel/preset')]
}
}, {

View file

@ -99,7 +99,7 @@ async function doRender (req, res, pathname, query, {
buildId,
buildStats,
assetPrefix,
err: (err && dev) ? errorToJSON(err) : null
err: (err) ? serializeError(dev, err) : null
},
dev,
staticMarkup,
@ -125,6 +125,9 @@ export async function renderScript (req, res, page, opts) {
}
export async function renderScriptError (req, res, page, error, customFields, opts) {
// Asks CDNs and others to not to cache the errored page
res.setHeader('Cache-Control', 'no-store, must-revalidate')
if (error.code === 'ENOENT') {
res.setHeader('Content-Type', 'text/javascript')
res.end(`
@ -190,6 +193,14 @@ function errorToJSON (err) {
return json
}
function serializeError (dev, err) {
if (dev) {
return errorToJSON(err)
}
return { message: '500 - Internal Server Error.' }
}
export function serveStatic (req, res, path) {
return new Promise((resolve, reject) => {
send(req, path)

31
wallaby.js Normal file
View file

@ -0,0 +1,31 @@
module.exports = function (wallaby) {
return {
files: [
'server/**/*.js',
'client/**/*.js',
'lib/**/*.js',
'dist/**/*.js',
'test/**/*.*',
'!test/**/*.test.js'
],
tests: [
'test/**/*.test.js',
'!test/integration/**/*.test.js'
],
compilers: {
'**/*.js': wallaby.compilers.babel()
},
env: {
type: 'node',
runner: 'node',
params: {
env: 'NODE_PATH=test/lib'
}
},
testFramework: 'jest'
}
}

2465
yarn.lock

File diff suppressed because it is too large Load diff