mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
next-dev
This commit is contained in:
parent
e51c7eabf1
commit
88b01e0a72
|
@ -1,11 +1,8 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
import { resolve, dirname } from 'path'
|
import { resolve } from 'path'
|
||||||
import parseArgs from 'minimist'
|
import parseArgs from 'minimist'
|
||||||
import fs from 'mz/fs'
|
import build from '../server/build'
|
||||||
import mkdirp from 'mkdirp-then';
|
|
||||||
import glob from 'glob-promise'
|
|
||||||
import { transpile, bundle } from '../server/build'
|
|
||||||
|
|
||||||
const argv = parseArgs(process.argv.slice(2), {
|
const argv = parseArgs(process.argv.slice(2), {
|
||||||
alias: {
|
alias: {
|
||||||
|
@ -16,29 +13,8 @@ const argv = parseArgs(process.argv.slice(2), {
|
||||||
|
|
||||||
const dir = resolve(argv._[0] || '.')
|
const dir = resolve(argv._[0] || '.')
|
||||||
|
|
||||||
Promise.resolve()
|
build(dir)
|
||||||
.then(async () => {
|
|
||||||
const paths = await glob('**/*.js', { cwd: dir, ignore: 'node_modules/**' })
|
|
||||||
await Promise.all(paths.map(async (p) => {
|
|
||||||
const code = await transpile(resolve(dir, p))
|
|
||||||
const outpath = resolve(dir, '.next', p)
|
|
||||||
await writeFile(outpath, code)
|
|
||||||
}))
|
|
||||||
|
|
||||||
const pagePaths = await glob('.next/pages/**/*.js', { cwd: dir })
|
|
||||||
await Promise.all(pagePaths.map(async (p) => {
|
|
||||||
const code = await bundle(resolve(dir, p))
|
|
||||||
const outpath = resolve(dir, '.next', p)
|
|
||||||
await writeFile(outpath, code)
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
exit(1)
|
exit(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
async function writeFile (path, data) {
|
|
||||||
await mkdirp(dirname(path))
|
|
||||||
await fs.writeFile(path, data, { encoding: 'utf8', flag: 'w+' })
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
30
bin/next-dev
Executable file
30
bin/next-dev
Executable file
|
@ -0,0 +1,30 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import { resolve } from 'path'
|
||||||
|
import parseArgs from 'minimist'
|
||||||
|
import Server from '../server'
|
||||||
|
import build from '../server/build'
|
||||||
|
|
||||||
|
const argv = parseArgs(process.argv.slice(2), {
|
||||||
|
alias: {
|
||||||
|
h: 'help',
|
||||||
|
p: 'port'
|
||||||
|
},
|
||||||
|
boolean: ['h'],
|
||||||
|
default: {
|
||||||
|
p: 3000
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const dir = resolve(argv._[0] || '.')
|
||||||
|
|
||||||
|
build(dir)
|
||||||
|
.then(async () => {
|
||||||
|
const srv = new Server({ dir, dev: true })
|
||||||
|
await srv.start(argv.port)
|
||||||
|
console.log('> Ready on http://localhost:%d', argv.port);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
exit(1)
|
||||||
|
})
|
|
@ -1,5 +1,6 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import { resolve } from 'path'
|
||||||
import parseArgs from 'minimist'
|
import parseArgs from 'minimist'
|
||||||
import Server from '../server'
|
import Server from '../server'
|
||||||
|
|
||||||
|
@ -14,9 +15,9 @@ const argv = parseArgs(process.argv.slice(2), {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const dir = argv._[0] || '.'
|
const dir = resolve(argv._[0] || '.')
|
||||||
|
|
||||||
const srv = new Server(dir)
|
const srv = new Server({ dir })
|
||||||
srv.start(argv.port)
|
srv.start(argv.port)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
console.log('> Ready on http://localhost:%d', argv.port);
|
console.log('> Ready on http://localhost:%d', argv.port);
|
||||||
|
|
1
client/next-dev.js
Normal file
1
client/next-dev.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
import './next'
|
|
@ -54,8 +54,8 @@ export function DevTools (props, context) {
|
||||||
DevTools.contextTypes = { _documentProps: PropTypes.any }
|
DevTools.contextTypes = { _documentProps: PropTypes.any }
|
||||||
|
|
||||||
export function NextScript (props, context) {
|
export function NextScript (props, context) {
|
||||||
const { hotReload } = context._documentProps;
|
const { dev } = context._documentProps;
|
||||||
const src = !hotReload ? '/_next/next.bundle.js' : '/_next/next-dev.bundle.js'
|
const src = !dev ? '/_next/next.bundle.js' : '/_next/next-dev.bundle.js'
|
||||||
return <script type='text/javascript' src={src}/>
|
return <script type='text/javascript' src={src}/>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
"cross-spawn": "4.0.2",
|
"cross-spawn": "4.0.2",
|
||||||
"glob-promise": "1.0.6",
|
"glob-promise": "1.0.6",
|
||||||
"htmlescape": "1.1.1",
|
"htmlescape": "1.1.1",
|
||||||
"memory-fs": "0.3.0",
|
|
||||||
"minimist": "1.2.0",
|
"minimist": "1.2.0",
|
||||||
"mkdirp-then": "1.2.0",
|
"mkdirp-then": "1.2.0",
|
||||||
"mz": "2.4.0",
|
"mz": "2.4.0",
|
||||||
|
|
|
@ -1,93 +0,0 @@
|
||||||
import { resolve, dirname, basename } from 'path'
|
|
||||||
import webpack from 'webpack'
|
|
||||||
import { transformFile } from 'babel-core'
|
|
||||||
import MemoryFS from 'memory-fs'
|
|
||||||
import preset2015 from 'babel-preset-es2015'
|
|
||||||
import presetReact from 'babel-preset-react'
|
|
||||||
import transformAsyncToGenerator from 'babel-plugin-transform-async-to-generator'
|
|
||||||
import transformClassProperties from 'babel-plugin-transform-class-properties'
|
|
||||||
import transformObjectRestSpread from 'babel-plugin-transform-object-rest-spread'
|
|
||||||
import transformRuntime from 'babel-plugin-transform-runtime'
|
|
||||||
import moduleAlias from 'babel-plugin-module-alias'
|
|
||||||
|
|
||||||
const babelRuntimePath = require.resolve('babel-runtime/package')
|
|
||||||
.replace(/[\\\/]package\.json$/, '');
|
|
||||||
|
|
||||||
export function transpile (path) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
transformFile(path, {
|
|
||||||
presets: [preset2015, presetReact],
|
|
||||||
plugins: [
|
|
||||||
transformAsyncToGenerator,
|
|
||||||
transformClassProperties,
|
|
||||||
transformObjectRestSpread,
|
|
||||||
transformRuntime,
|
|
||||||
[
|
|
||||||
moduleAlias,
|
|
||||||
[
|
|
||||||
{ src: `npm:${babelRuntimePath}`, expose: 'babel-runtime' },
|
|
||||||
{ src: `npm:${require.resolve('react')}`, expose: 'react' },
|
|
||||||
{ src: `npm:${require.resolve('../lib/link')}`, expose: 'next/link' }
|
|
||||||
]
|
|
||||||
]
|
|
||||||
],
|
|
||||||
ast: false
|
|
||||||
}, (err, result) => {
|
|
||||||
if (err) return reject(err)
|
|
||||||
resolve(result.code)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function bundle (path) {
|
|
||||||
const fs = new MemoryFS()
|
|
||||||
|
|
||||||
const compiler = webpack({
|
|
||||||
entry: path,
|
|
||||||
output: {
|
|
||||||
path: dirname(path),
|
|
||||||
filename: basename(path),
|
|
||||||
libraryTarget: 'commonjs2'
|
|
||||||
},
|
|
||||||
externals: [
|
|
||||||
'react',
|
|
||||||
'react-dom',
|
|
||||||
{
|
|
||||||
[require.resolve('react')]: 'react',
|
|
||||||
[require.resolve('../lib/link')]: 'next/link'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
resolveLoader: {
|
|
||||||
root: resolve(__dirname, '..', '..', 'node_modules')
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
new webpack.optimize.UglifyJsPlugin({
|
|
||||||
compress: { warnings: false },
|
|
||||||
sourceMap: false
|
|
||||||
})
|
|
||||||
],
|
|
||||||
module: {
|
|
||||||
preLoaders: [
|
|
||||||
{ test: /\.json$/, loader: 'json-loader' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
compiler.outputFileSystem = fs
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
compiler.run((err, stats) => {
|
|
||||||
if (err) return reject(err)
|
|
||||||
|
|
||||||
const jsonStats = stats.toJson()
|
|
||||||
if (jsonStats.errors.length > 0) {
|
|
||||||
const error = new Error(jsonStats.errors[0])
|
|
||||||
error.errors = jsonStats.errors
|
|
||||||
error.warnings = jsonStats.warnings
|
|
||||||
return reject(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve(fs.readFileSync(path))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
51
server/build/bundle.js
Normal file
51
server/build/bundle.js
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import { resolve, dirname, basename } from 'path'
|
||||||
|
import webpack from 'webpack'
|
||||||
|
|
||||||
|
export default function bundle (src, dst) {
|
||||||
|
const compiler = webpack({
|
||||||
|
entry: src,
|
||||||
|
output: {
|
||||||
|
path: dirname(dst),
|
||||||
|
filename: basename(dst),
|
||||||
|
libraryTarget: 'commonjs2'
|
||||||
|
},
|
||||||
|
externals: [
|
||||||
|
'react',
|
||||||
|
'react-dom',
|
||||||
|
{
|
||||||
|
[require.resolve('react')]: 'react',
|
||||||
|
[require.resolve('../lib/link')]: 'next/link'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
resolveLoader: {
|
||||||
|
root: resolve(__dirname, '..', '..', 'node_modules')
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new webpack.optimize.UglifyJsPlugin({
|
||||||
|
compress: { warnings: false },
|
||||||
|
sourceMap: false
|
||||||
|
})
|
||||||
|
],
|
||||||
|
module: {
|
||||||
|
preLoaders: [
|
||||||
|
{ test: /\.json$/, loader: 'json-loader' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
compiler.run((err, stats) => {
|
||||||
|
if (err) return reject(err)
|
||||||
|
|
||||||
|
const jsonStats = stats.toJson()
|
||||||
|
if (jsonStats.errors.length > 0) {
|
||||||
|
const error = new Error(jsonStats.errors[0])
|
||||||
|
error.errors = jsonStats.errors
|
||||||
|
error.warnings = jsonStats.warnings
|
||||||
|
return reject(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
18
server/build/index.js
Normal file
18
server/build/index.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { resolve } from 'path'
|
||||||
|
import glob from 'glob-promise'
|
||||||
|
import transpile from './transpile'
|
||||||
|
import bundle from './bundle'
|
||||||
|
|
||||||
|
export default async function build (dir) {
|
||||||
|
const dstDir = resolve(dir, '.next')
|
||||||
|
|
||||||
|
const paths = await glob('**/*.js', { cwd: dir, ignore: 'node_modules/**' })
|
||||||
|
await Promise.all(paths.map(async (p) => {
|
||||||
|
await transpile(resolve(dir, p), resolve(dstDir, p))
|
||||||
|
}))
|
||||||
|
|
||||||
|
const pagePaths = await glob('pages/**/*.js', { cwd: dstDir })
|
||||||
|
await Promise.all(pagePaths.map(async (p) => {
|
||||||
|
await bundle(resolve(dstDir, p), resolve(dstDir, '_bundles', p))
|
||||||
|
}))
|
||||||
|
}
|
49
server/build/transpile.js
Normal file
49
server/build/transpile.js
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
import { dirname } from 'path'
|
||||||
|
import fs from 'mz/fs'
|
||||||
|
import mkdirp from 'mkdirp-then';
|
||||||
|
import { transformFile } from 'babel-core'
|
||||||
|
import preset2015 from 'babel-preset-es2015'
|
||||||
|
import presetReact from 'babel-preset-react'
|
||||||
|
import transformAsyncToGenerator from 'babel-plugin-transform-async-to-generator'
|
||||||
|
import transformClassProperties from 'babel-plugin-transform-class-properties'
|
||||||
|
import transformObjectRestSpread from 'babel-plugin-transform-object-rest-spread'
|
||||||
|
import transformRuntime from 'babel-plugin-transform-runtime'
|
||||||
|
import moduleAlias from 'babel-plugin-module-alias'
|
||||||
|
|
||||||
|
const babelRuntimePath = require.resolve('babel-runtime/package')
|
||||||
|
.replace(/[\\\/]package\.json$/, '');
|
||||||
|
|
||||||
|
const babelOptions = {
|
||||||
|
presets: [preset2015, presetReact],
|
||||||
|
plugins: [
|
||||||
|
transformAsyncToGenerator,
|
||||||
|
transformClassProperties,
|
||||||
|
transformObjectRestSpread,
|
||||||
|
transformRuntime,
|
||||||
|
[
|
||||||
|
moduleAlias,
|
||||||
|
[
|
||||||
|
{ src: `npm:${babelRuntimePath}`, expose: 'babel-runtime' },
|
||||||
|
{ src: `npm:${require.resolve('react')}`, expose: 'react' },
|
||||||
|
{ src: `npm:${require.resolve('../lib/link')}`, expose: 'next/link' }
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
ast: false
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function transpile (src, dst) {
|
||||||
|
const code = await new Promise((resolve, reject) => {
|
||||||
|
transformFile(src, babelOptions, (err, result) => {
|
||||||
|
if (err) return reject(err)
|
||||||
|
resolve(result.code)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
await writeFile(dst, code)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function writeFile (path, data) {
|
||||||
|
await mkdirp(dirname(path))
|
||||||
|
await fs.writeFile(path, data, { encoding: 'utf8', flag: 'w+' })
|
||||||
|
}
|
|
@ -5,8 +5,9 @@ import Router from './router'
|
||||||
import { render, renderJSON } from './render'
|
import { render, renderJSON } from './render'
|
||||||
|
|
||||||
export default class Server {
|
export default class Server {
|
||||||
constructor (root) {
|
constructor ({ dir = '.', dev = false }) {
|
||||||
this.root = resolve(root)
|
this.dir = resolve(dir)
|
||||||
|
this.dev = dev
|
||||||
this.router = new Router()
|
this.router = new Router()
|
||||||
|
|
||||||
this.http = http.createServer((req, res) => {
|
this.http = http.createServer((req, res) => {
|
||||||
|
@ -50,10 +51,10 @@ export default class Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
async render (req, res, path) {
|
async render (req, res, path) {
|
||||||
const { root } = this
|
const { dir } = this
|
||||||
let html
|
let html
|
||||||
try {
|
try {
|
||||||
html = await render(path, req, res, { root })
|
html = await render(path, req, res, { dir })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if ('MODULE_NOT_FOUND' === err.code) {
|
if ('MODULE_NOT_FOUND' === err.code) {
|
||||||
return this.render404(req, res)
|
return this.render404(req, res)
|
||||||
|
@ -66,10 +67,10 @@ export default class Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
async renderJSON (req, res, path) {
|
async renderJSON (req, res, path) {
|
||||||
const { root } = this
|
const { dir } = this
|
||||||
let json
|
let json
|
||||||
try {
|
try {
|
||||||
json = await renderJSON(path, { root })
|
json = await renderJSON(path, { dir })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if ('MODULE_NOT_FOUND' === err.code) {
|
if ('MODULE_NOT_FOUND' === err.code) {
|
||||||
return this.render404(req, res)
|
return this.render404(req, res)
|
||||||
|
|
|
@ -6,8 +6,8 @@ import Document from '../lib/document'
|
||||||
import App from '../lib/app'
|
import App from '../lib/app'
|
||||||
import { StyleSheetServer } from '../lib/css'
|
import { StyleSheetServer } from '../lib/css'
|
||||||
|
|
||||||
export async function render (path, req, res, { root = process.cwd() } = {}) {
|
export async function render (path, req, res, { dir = process.cwd(), dev = false } = {}) {
|
||||||
const mod = require(resolve(root, '.next', 'pages', path)) || {}
|
const mod = require(resolve(dir, '.next', 'pages', path)) || {}
|
||||||
const Component = mod.default
|
const Component = mod.default
|
||||||
|
|
||||||
let props = {}
|
let props = {}
|
||||||
|
@ -15,7 +15,7 @@ export async function render (path, req, res, { root = process.cwd() } = {}) {
|
||||||
props = await Component.getInitialProps({ req, res })
|
props = await Component.getInitialProps({ req, res })
|
||||||
}
|
}
|
||||||
|
|
||||||
const bundlePath = resolve(root, '.next', '.next', 'pages', (path || 'index') + '.js')
|
const bundlePath = resolve(dir, '.next', '_bundles', 'pages', (path || 'index') + '.js')
|
||||||
const component = await fs.readFile(bundlePath, 'utf8')
|
const component = await fs.readFile(bundlePath, 'utf8')
|
||||||
|
|
||||||
const { html, css } = StyleSheetServer.renderStatic(() => {
|
const { html, css } = StyleSheetServer.renderStatic(() => {
|
||||||
|
@ -33,14 +33,15 @@ export async function render (path, req, res, { root = process.cwd() } = {}) {
|
||||||
html: html,
|
html: html,
|
||||||
css: css,
|
css: css,
|
||||||
data: { component },
|
data: { component },
|
||||||
hotReload: false
|
hotReload: false,
|
||||||
|
dev
|
||||||
})
|
})
|
||||||
|
|
||||||
return '<!DOCTYPE html>' + renderToStaticMarkup(doc)
|
return '<!DOCTYPE html>' + renderToStaticMarkup(doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function renderJSON (path, { root = process.cwd() }) {
|
export async function renderJSON (path, { dir = process.cwd() }) {
|
||||||
const bundlePath = resolve(root, '.next', '.next', 'pages', (path || 'index') + '.js')
|
const bundlePath = resolve(dir, '.next', '_bundles', 'pages', (path || 'index') + '.js')
|
||||||
const component = await fs.readFile(bundlePath, 'utf8')
|
const component = await fs.readFile(bundlePath, 'utf8')
|
||||||
return { component }
|
return { component }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue