mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
add --node-args option (#5858)
This message is from @timneutkens after making changes: - Convert executables to Typescript - Remove `minimist` in favor of `arg` - Implement `--node-args` usage: `--node-args="--throw-deprecation"` - Adds tests for usage of the `next` cli
This commit is contained in:
parent
dfa0f82669
commit
ebf217cb16
|
@ -62,6 +62,7 @@
|
|||
- [Configuring the onDemandEntries](#configuring-the-ondemandentries)
|
||||
- [Configuring extensions looked for when resolving pages in `pages`](#configuring-extensions-looked-for-when-resolving-pages-in-pages)
|
||||
- [Configuring the build ID](#configuring-the-build-id)
|
||||
- [Configuring Next process script](#configuring-next-process-script)
|
||||
- [Customizing webpack config](#customizing-webpack-config)
|
||||
- [Customizing babel config](#customizing-babel-config)
|
||||
- [Exposing configuration to the server / client side](#exposing-configuration-to-the-server--client-side)
|
||||
|
@ -1337,6 +1338,17 @@ module.exports = {
|
|||
}
|
||||
```
|
||||
|
||||
#### Configuring next process script
|
||||
|
||||
You can pass any node arguments to `next` cli command.
|
||||
|
||||
|
||||
```bash
|
||||
next --node-args="--throw-deprecation"
|
||||
next start --node-args="--inspect"
|
||||
next build --node-args="-r esm"
|
||||
```
|
||||
|
||||
### Customizing webpack config
|
||||
|
||||
<details>
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
import { join } from 'path'
|
||||
import { spawn } from 'cross-spawn'
|
||||
import pkg from '../../package.json'
|
||||
import {CONFIG_FILE} from 'next-server/constants'
|
||||
|
||||
if (pkg.peerDependencies) {
|
||||
Object.keys(pkg.peerDependencies).forEach(dependency => {
|
||||
try {
|
||||
// When 'npm link' is used it checks the clone location. Not the project.
|
||||
require.resolve(dependency)
|
||||
} catch (err) {
|
||||
console.warn(`The module '${dependency}' was not found. Next.js requires that you include it in 'dependencies' of your 'package.json'. To add it, run 'npm install --save ${dependency}'`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const defaultCommand = 'dev'
|
||||
const commands = new Set([
|
||||
'init',
|
||||
'build',
|
||||
'start',
|
||||
'export',
|
||||
defaultCommand
|
||||
])
|
||||
|
||||
let cmd = process.argv[2]
|
||||
let args = []
|
||||
let nodeArgs = []
|
||||
|
||||
if (new Set(['--version', '-v']).has(cmd)) {
|
||||
console.log(`next.js v${pkg.version}`)
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
const inspectArg = process.argv.find(arg => arg.includes('--inspect'))
|
||||
if (inspectArg) {
|
||||
nodeArgs.push(inspectArg)
|
||||
}
|
||||
|
||||
if (new Set(['--help', '-h']).has(cmd)) {
|
||||
console.log(`
|
||||
Usage
|
||||
$ next <command>
|
||||
|
||||
Available commands
|
||||
${Array.from(commands).join(', ')}
|
||||
|
||||
For more information run a command with the --help flag
|
||||
$ next init --help
|
||||
`)
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
if (commands.has(cmd)) {
|
||||
args = process.argv.slice(3)
|
||||
} else {
|
||||
cmd = defaultCommand
|
||||
args = process.argv.slice(2)
|
||||
}
|
||||
|
||||
const defaultEnv = cmd === 'dev' ? 'development' : 'production'
|
||||
process.env.NODE_ENV = process.env.NODE_ENV || defaultEnv
|
||||
|
||||
const bin = join(__dirname, 'next-' + cmd)
|
||||
|
||||
const startProcess = () => {
|
||||
const proc = spawn('node', [...nodeArgs, ...[bin], ...args], { stdio: 'inherit', customFds: [0, 1, 2] })
|
||||
proc.on('close', (code, signal) => {
|
||||
if (code !== null) {
|
||||
process.exit(code)
|
||||
}
|
||||
if (signal) {
|
||||
if (signal === 'SIGKILL') {
|
||||
process.exit(137)
|
||||
}
|
||||
console.log(`got signal ${signal}, exiting`)
|
||||
process.exit(signal === 'SIGINT' ? 0 : 1)
|
||||
}
|
||||
process.exit(0)
|
||||
})
|
||||
proc.on('error', (err) => {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
return proc
|
||||
}
|
||||
|
||||
let proc = startProcess()
|
||||
|
||||
const wrapper = () => {
|
||||
if (proc) {
|
||||
proc.kill()
|
||||
}
|
||||
}
|
||||
process.on('SIGINT', wrapper)
|
||||
process.on('SIGTERM', wrapper)
|
||||
process.on('exit', wrapper)
|
||||
|
||||
if (cmd === 'dev') {
|
||||
const {watchFile} = require('fs')
|
||||
watchFile(`${process.cwd()}/${CONFIG_FILE}`, (cur, prev) => {
|
||||
if (cur.size > 0 || prev.size > 0) {
|
||||
console.log(`\n> Found a change in ${CONFIG_FILE}, restarting the server...`)
|
||||
// Don't listen to 'close' now since otherwise parent gets killed by listener
|
||||
proc.removeAllListeners('close')
|
||||
proc.kill()
|
||||
proc = startProcess()
|
||||
}
|
||||
})
|
||||
}
|
|
@ -1,19 +1,21 @@
|
|||
#!/usr/bin/env node
|
||||
import { resolve, join } from 'path'
|
||||
import { existsSync } from 'fs'
|
||||
import parseArgs from 'minimist'
|
||||
import arg from 'arg'
|
||||
import build from '../build'
|
||||
import { printAndExit } from '../server/lib/utils'
|
||||
|
||||
const argv = parseArgs(process.argv.slice(2), {
|
||||
alias: {
|
||||
h: 'help',
|
||||
l: 'lambdas'
|
||||
},
|
||||
boolean: ['h', 'l']
|
||||
const args = arg({
|
||||
// Types
|
||||
'--help': Boolean,
|
||||
'--lambdas': Boolean,
|
||||
|
||||
// Aliases
|
||||
'-h': '--help',
|
||||
'-l': '--lambdas'
|
||||
})
|
||||
|
||||
if (argv.help) {
|
||||
if (args['--help']) {
|
||||
printAndExit(`
|
||||
Description
|
||||
Compiles the application for production deployment
|
||||
|
@ -27,8 +29,8 @@ if (argv.help) {
|
|||
`, 0)
|
||||
}
|
||||
|
||||
const dir = resolve(argv._[0] || '.')
|
||||
const lambdas = argv.lambdas
|
||||
const dir = resolve(args._[0] || '.')
|
||||
const lambdas = args['--lambdas']
|
||||
|
||||
// Check if pages dir exists and warn if not
|
||||
if (!existsSync(dir)) {
|
|
@ -1,22 +1,23 @@
|
|||
#!/usr/bin/env node
|
||||
import { resolve, join } from 'path'
|
||||
import parseArgs from 'minimist'
|
||||
import arg from 'arg'
|
||||
import { existsSync } from 'fs'
|
||||
import startServer from '../server/lib/start-server'
|
||||
import { printAndExit } from '../server/lib/utils'
|
||||
|
||||
const argv = parseArgs(process.argv.slice(2), {
|
||||
alias: {
|
||||
h: 'help',
|
||||
H: 'hostname',
|
||||
p: 'port'
|
||||
},
|
||||
boolean: ['h'],
|
||||
string: ['H'],
|
||||
default: { p: 3000 }
|
||||
const args = arg({
|
||||
// Types
|
||||
'--help': Boolean,
|
||||
'--port': Number,
|
||||
'--hostname': String,
|
||||
|
||||
// Aliases
|
||||
'-h': '--help',
|
||||
'-p': '--port',
|
||||
'-H': '--hostname'
|
||||
})
|
||||
|
||||
if (argv.help) {
|
||||
if (args['--help']) {
|
||||
console.log(`
|
||||
Description
|
||||
Starts the application in development mode (hot-code reloading, error
|
||||
|
@ -37,7 +38,7 @@ if (argv.help) {
|
|||
process.exit(0)
|
||||
}
|
||||
|
||||
const dir = resolve(argv._[0] || '.')
|
||||
const dir = resolve(args._[0] || '.')
|
||||
|
||||
// Check if pages dir exists and warn if not
|
||||
if (!existsSync(dir)) {
|
||||
|
@ -52,13 +53,14 @@ if (!existsSync(join(dir, 'pages'))) {
|
|||
printAndExit('> Couldn\'t find a `pages` directory. Please create one under the project root')
|
||||
}
|
||||
|
||||
startServer({dir, dev: true}, argv.port, argv.hostname)
|
||||
const port = args['--port'] || 3000
|
||||
startServer({dir, dev: true}, port, args['--hostname'])
|
||||
.then(async () => {
|
||||
console.log(`> Ready on http://${argv.hostname ? argv.hostname : 'localhost'}:${argv.port}`)
|
||||
console.log(`> Ready on http://${args['--hostname'] || 'localhost'}:${port}`)
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err.code === 'EADDRINUSE') {
|
||||
let errorMessage = `Port ${argv.port} is already in use.`
|
||||
let errorMessage = `Port ${port} is already in use.`
|
||||
const pkgAppPath = require('find-up').sync('package.json', {
|
||||
cwd: dir
|
||||
})
|
|
@ -1,24 +1,25 @@
|
|||
#!/usr/bin/env node
|
||||
import { resolve, join } from 'path'
|
||||
import { existsSync } from 'fs'
|
||||
import parseArgs from 'minimist'
|
||||
import arg from 'arg'
|
||||
import exportApp from '../export'
|
||||
import { printAndExit } from '../server/lib/utils'
|
||||
|
||||
const argv = parseArgs(process.argv.slice(2), {
|
||||
alias: {
|
||||
h: 'help',
|
||||
s: 'silent',
|
||||
o: 'outdir'
|
||||
},
|
||||
boolean: ['h'],
|
||||
default: {
|
||||
s: false,
|
||||
o: null
|
||||
}
|
||||
const args = arg({
|
||||
// Types
|
||||
'--help': Boolean,
|
||||
'--silent': Boolean,
|
||||
'--outdir': String,
|
||||
'--threads': Number,
|
||||
'--concurrency': Number,
|
||||
|
||||
// Aliases
|
||||
'-h': '--help',
|
||||
'-s': '--silent',
|
||||
'-o': '--outdir'
|
||||
})
|
||||
|
||||
if (argv.help) {
|
||||
if (args['--help']) {
|
||||
console.log(`
|
||||
Description
|
||||
Exports the application for production deployment
|
||||
|
@ -37,7 +38,7 @@ if (argv.help) {
|
|||
process.exit(0)
|
||||
}
|
||||
|
||||
const dir = resolve(argv._[0] || '.')
|
||||
const dir = resolve(args._[0] || '.')
|
||||
|
||||
// Check if pages dir exists and warn if not
|
||||
if (!existsSync(dir)) {
|
||||
|
@ -53,10 +54,10 @@ if (!existsSync(join(dir, 'pages'))) {
|
|||
}
|
||||
|
||||
const options = {
|
||||
silent: argv.silent,
|
||||
threads: argv.threads,
|
||||
concurrency: argv.concurrency,
|
||||
outdir: argv.outdir ? resolve(argv.outdir) : resolve(dir, 'out')
|
||||
silent: args['--silent'] || false,
|
||||
threads: args['--threads'],
|
||||
concurrency: args['--concurrency'],
|
||||
outdir: args['--outdir'] ? resolve(args['--outdir']) : join(dir, 'out')
|
||||
}
|
||||
|
||||
exportApp(dir, options)
|
|
@ -1,4 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
console.log('`next init` is not supported anymore. These community projects provide the same functionality as `next init` with additional features: http://npmjs.com/next-init and http://npmjs.com/create-next-app.')
|
||||
|
||||
process.exit(0)
|
|
@ -1,26 +1,22 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
import { resolve } from 'path'
|
||||
import parseArgs from 'minimist'
|
||||
import arg from 'arg'
|
||||
import startServer from '../server/lib/start-server'
|
||||
|
||||
const argv = parseArgs(process.argv.slice(2), {
|
||||
alias: {
|
||||
h: 'help',
|
||||
H: 'hostname',
|
||||
p: 'port'
|
||||
},
|
||||
boolean: ['h'],
|
||||
string: ['H'],
|
||||
default: { p: 3000 }
|
||||
const args = arg({
|
||||
// Types
|
||||
'--help': Boolean,
|
||||
'--port': Number,
|
||||
'--hostname': String,
|
||||
|
||||
// Aliases
|
||||
'-h': '--help',
|
||||
'-p': '--port',
|
||||
'-H': '--hostname'
|
||||
})
|
||||
|
||||
if (argv.hostname === '') {
|
||||
console.error(`> Provided hostname argument has no value`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (argv.help) {
|
||||
if (args['--help']) {
|
||||
console.log(`
|
||||
Description
|
||||
Starts the application in production mode.
|
||||
|
@ -42,11 +38,11 @@ if (argv.help) {
|
|||
process.exit(0)
|
||||
}
|
||||
|
||||
const dir = resolve(argv._[0] || '.')
|
||||
|
||||
startServer({dir}, argv.port, argv.hostname)
|
||||
const dir = resolve(args._[0] || '.')
|
||||
const port = args['--port'] || 3000
|
||||
startServer({dir}, port, args['--hostname'])
|
||||
.then(() => {
|
||||
console.log(`> Ready on http://${argv.hostname ? argv.hostname : 'localhost'}:${argv.port}`)
|
||||
console.log(`> Ready on http://${args['--hostname']}:${port}`)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err)
|
137
packages/next/bin/next.ts
Executable file
137
packages/next/bin/next.ts
Executable file
|
@ -0,0 +1,137 @@
|
|||
#!/usr/bin/env node
|
||||
import { join } from 'path'
|
||||
import spawn from 'cross-spawn'
|
||||
import arg from 'arg'
|
||||
|
||||
['react', 'react-dom'].forEach(dependency => {
|
||||
try {
|
||||
// When 'npm link' is used it checks the clone location. Not the project.
|
||||
require.resolve(dependency)
|
||||
} catch (err) {
|
||||
console.warn(`The module '${dependency}' was not found. Next.js requires that you include it in 'dependencies' of your 'package.json'. To add it, run 'npm install --save ${dependency}'`)
|
||||
}
|
||||
})
|
||||
|
||||
const defaultCommand = 'dev'
|
||||
const commands = [
|
||||
'build',
|
||||
'start',
|
||||
'export',
|
||||
defaultCommand
|
||||
]
|
||||
|
||||
const args = arg({
|
||||
// Types
|
||||
'--version': Boolean,
|
||||
'--help': Boolean,
|
||||
'--node-args': String,
|
||||
'--inspect': Boolean,
|
||||
|
||||
// Aliases
|
||||
'-v': '--version',
|
||||
'-h': '--help'
|
||||
}, {
|
||||
permissive: true
|
||||
})
|
||||
|
||||
// Version is inlined into the file using taskr build pipeline
|
||||
if (args['--version']) {
|
||||
console.log(`Next.js v${process.env.NEXT_VERSION}`)
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
// Check if we are running `next <subcommand>` or `next`
|
||||
const foundCommand = args._.find(cmd => commands.includes(cmd))
|
||||
|
||||
// Makes sure the `next <subcommand> --help` case is covered
|
||||
// This help message is only showed for `next --help`
|
||||
if (!foundCommand && args['--help']) {
|
||||
console.log(`
|
||||
Usage
|
||||
$ next <command>
|
||||
|
||||
Available commands
|
||||
${commands.join(', ')}
|
||||
|
||||
Options
|
||||
--version, -p Version number
|
||||
--node-args Node arguments applied to the process
|
||||
--help, -h Displays this message
|
||||
|
||||
For more information run a command with the --help flag
|
||||
$ next build --help
|
||||
`)
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
// Add support for `--node-args` to send Node.js arguments to the spawned process
|
||||
const nodeArguments = args['--node-args'] && args['--node-args'] !== '' ? args['--node-args'].split(' ') : []
|
||||
if (args['--inspect']) {
|
||||
console.log('The `--inspect` option is deprecated in favor of `--node-args`')
|
||||
nodeArguments.push('--inspect')
|
||||
}
|
||||
|
||||
if (nodeArguments.length > 0) {
|
||||
console.log(`Passing arguments to Node.js: "${nodeArguments.join(' ')}"`)
|
||||
}
|
||||
|
||||
const command = foundCommand || defaultCommand
|
||||
const forwardedArgs = args._.filter(arg => arg !== command)
|
||||
|
||||
// Make sure the `next <subcommand> --help` case is covered
|
||||
if (args['--help']) {
|
||||
forwardedArgs.push('--help')
|
||||
}
|
||||
|
||||
const defaultEnv = command === 'dev' ? 'development' : 'production'
|
||||
process.env.NODE_ENV = process.env.NODE_ENV || defaultEnv
|
||||
|
||||
const bin = join(__dirname, 'next-' + command)
|
||||
|
||||
const startProcess = () => {
|
||||
const proc = spawn('node', [...nodeArguments, bin, ...forwardedArgs], { stdio: 'inherit' })
|
||||
proc.on('close', (code, signal) => {
|
||||
if (code !== null) {
|
||||
process.exit(code)
|
||||
}
|
||||
if (signal) {
|
||||
if (signal === 'SIGKILL') {
|
||||
process.exit(137)
|
||||
}
|
||||
console.log(`got signal ${signal}, exiting`)
|
||||
process.exit(signal === 'SIGINT' ? 0 : 1)
|
||||
}
|
||||
process.exit(0)
|
||||
})
|
||||
proc.on('error', (err) => {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
return proc
|
||||
}
|
||||
|
||||
let proc = startProcess()
|
||||
|
||||
function wrapper () {
|
||||
if (proc) {
|
||||
proc.kill()
|
||||
}
|
||||
}
|
||||
|
||||
process.on('SIGINT', wrapper)
|
||||
process.on('SIGTERM', wrapper)
|
||||
process.on('exit', wrapper)
|
||||
|
||||
if (command === 'dev') {
|
||||
const {CONFIG_FILE} = require('next-server/constants')
|
||||
const {watchFile} = require('fs')
|
||||
watchFile(`${process.cwd()}/${CONFIG_FILE}`, (cur: any, prev: any) => {
|
||||
if (cur.size > 0 || prev.size > 0) {
|
||||
console.log(`\n> Found a change in ${CONFIG_FILE}, restarting the server...`)
|
||||
// Don't listen to 'close' now since otherwise parent gets killed by listener
|
||||
proc.removeAllListeners('close')
|
||||
proc.kill()
|
||||
proc = startProcess()
|
||||
}
|
||||
})
|
||||
}
|
|
@ -49,6 +49,7 @@
|
|||
"@babel/runtime-corejs2": "7.1.2",
|
||||
"@babel/template": "7.1.2",
|
||||
"ansi-html": "0.0.7",
|
||||
"arg": "3.0.0",
|
||||
"async-sema": "^2.1.4",
|
||||
"autodll-webpack-plugin": "0.4.2",
|
||||
"babel-core": "7.0.0-bridge.0",
|
||||
|
@ -68,7 +69,6 @@
|
|||
"http-status": "1.0.1",
|
||||
"launch-editor": "2.2.1",
|
||||
"loader-utils": "1.1.0",
|
||||
"minimist": "1.2.0",
|
||||
"mkdirp-then": "1.2.0",
|
||||
"nanoid": "1.2.1",
|
||||
"next-server": "^7.0.2-canary.43",
|
||||
|
@ -103,6 +103,7 @@
|
|||
"@types/babel__generator": "7.0.1",
|
||||
"@types/babel__template": "7.0.1",
|
||||
"@types/babel__traverse": "7.0.3",
|
||||
"@types/cross-spawn": "6.0.0",
|
||||
"@types/etag": "1.8.0",
|
||||
"@types/fresh": "0.5.0",
|
||||
"@types/nanoid": "1.2.0",
|
||||
|
|
|
@ -6,11 +6,13 @@ try {
|
|||
|
||||
module.exports = function (task) {
|
||||
task.plugin('typescript', { every: true }, function * (file, options) {
|
||||
const {stripExtension} = options
|
||||
const opts = {
|
||||
fileName: file.base,
|
||||
compilerOptions: {
|
||||
...config.compilerOptions,
|
||||
...options
|
||||
...options,
|
||||
stripExtension: undefined // since it's an option of the typescript taskr plugin
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,7 +21,7 @@ try {
|
|||
if (ext) {
|
||||
// Replace `.ts` with `.js`
|
||||
const extRegex = new RegExp(ext.replace('.', '\\.') + '$', 'i')
|
||||
file.base = file.base.replace(extRegex, '.js')
|
||||
file.base = file.base.replace(extRegex, stripExtension ? '' : '.js')
|
||||
}
|
||||
|
||||
// compile output
|
||||
|
@ -35,7 +37,7 @@ try {
|
|||
}
|
||||
|
||||
// update file's data
|
||||
file.data = Buffer.from(result.outputText, 'utf8')
|
||||
file.data = Buffer.from(result.outputText.replace(/process\.env\.NEXT_VERSION/, `"${require('./package.json').version}"`), 'utf8')
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
|
|
|
@ -5,7 +5,7 @@ export async function compile (task) {
|
|||
}
|
||||
|
||||
export async function bin (task, opts) {
|
||||
await task.source(opts.src || 'bin/*').typescript({module: 'commonjs'}).target('dist/bin', {mode: '0755'})
|
||||
await task.source(opts.src || 'bin/*').typescript({module: 'commonjs', stripExtension: true}).target('dist/bin', {mode: '0755'})
|
||||
notify('Compiled binaries')
|
||||
}
|
||||
|
||||
|
|
23
packages/next/types/index.d.ts
vendored
23
packages/next/types/index.d.ts
vendored
|
@ -1,3 +1,26 @@
|
|||
declare module '@babel/plugin-transform-modules-commonjs';
|
||||
declare module 'next-server/next-config';
|
||||
declare module 'next-server/constants';
|
||||
declare module 'arg' {
|
||||
function arg<T extends arg.Spec>(spec: T, options?: {argv?: string[], permissive?: boolean}): arg.Result<T>;
|
||||
|
||||
namespace arg {
|
||||
export type Handler = (value: string) => any;
|
||||
|
||||
export interface Spec {
|
||||
[key: string]: string | Handler | [Handler];
|
||||
}
|
||||
|
||||
export type Result<T extends Spec> = { _: string[] } & {
|
||||
[K in keyof T]: T[K] extends string
|
||||
? never
|
||||
: T[K] extends Handler
|
||||
? ReturnType<T[K]>
|
||||
: T[K] extends [Handler]
|
||||
? Array<ReturnType<T[K][0]>>
|
||||
: never
|
||||
};
|
||||
}
|
||||
|
||||
export = arg;
|
||||
}
|
1
test/integration/cli/pages/index.js
Normal file
1
test/integration/cli/pages/index.js
Normal file
|
@ -0,0 +1 @@
|
|||
export default () => 'test'
|
151
test/integration/cli/test/index.test.js
Normal file
151
test/integration/cli/test/index.test.js
Normal file
|
@ -0,0 +1,151 @@
|
|||
/* eslint-env jest */
|
||||
/* global jasmine */
|
||||
import {
|
||||
runNextCommand,
|
||||
runNextCommandDev,
|
||||
findPort
|
||||
} from 'next-test-utils'
|
||||
import {join} from 'path'
|
||||
import pkg from 'next/package'
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 5
|
||||
|
||||
const dir = join(__dirname, '..')
|
||||
|
||||
describe('CLI Usage', () => {
|
||||
describe('no command', () => {
|
||||
test('--help', async () => {
|
||||
const help = await runNextCommand(['--help'], {
|
||||
stdout: true
|
||||
})
|
||||
expect(help.stdout).toMatch(/Usage/)
|
||||
})
|
||||
|
||||
test('-h', async () => {
|
||||
const help = await runNextCommand(['-h'], {
|
||||
stdout: true
|
||||
})
|
||||
expect(help.stdout).toMatch(/Usage/)
|
||||
})
|
||||
|
||||
test('--version', async () => {
|
||||
const output = await runNextCommand(['--version'], {
|
||||
stdout: true
|
||||
})
|
||||
expect(output.stdout).toMatch(new RegExp(`Next\\.js v${pkg.version.replace(/\./g, '\\.')}`))
|
||||
})
|
||||
|
||||
test('-v', async () => {
|
||||
const output = await runNextCommand(['--version'], {
|
||||
stdout: true
|
||||
})
|
||||
expect(output.stdout).toMatch(new RegExp(`Next\\.js v${pkg.version.replace(/\./g, '\\.')}`))
|
||||
})
|
||||
|
||||
test('--inspect', async () => {
|
||||
const output = await runNextCommand(['build', dir, '--inspect'], {
|
||||
stdout: true
|
||||
})
|
||||
expect(output.stdout).toMatch(/The `--inspect` option is deprecated/)
|
||||
})
|
||||
|
||||
test('--node-args', async () => {
|
||||
const output = await runNextCommand(['build', dir, '--node-args=--inspect'], {
|
||||
stdout: true
|
||||
})
|
||||
expect(output.stdout).toMatch(/Passing arguments to Node\.js: "--inspect"/)
|
||||
})
|
||||
})
|
||||
describe('build', () => {
|
||||
test('--help', async () => {
|
||||
const help = await runNextCommand(['build', '--help'], {
|
||||
stdout: true
|
||||
})
|
||||
expect(help.stdout).toMatch(/Compiles the application for production deployment/)
|
||||
})
|
||||
|
||||
test('-h', async () => {
|
||||
const help = await runNextCommand(['build', '-h'], {
|
||||
stdout: true
|
||||
})
|
||||
expect(help.stdout).toMatch(/Compiles the application for production deployment/)
|
||||
})
|
||||
})
|
||||
|
||||
describe('dev', () => {
|
||||
test('--help', async () => {
|
||||
const help = await runNextCommand(['dev', '--help'], {
|
||||
stdout: true
|
||||
})
|
||||
expect(help.stdout).toMatch(/Starts the application in development mode/)
|
||||
})
|
||||
|
||||
test('-h', async () => {
|
||||
const help = await runNextCommand(['dev', '-h'], {
|
||||
stdout: true
|
||||
})
|
||||
expect(help.stdout).toMatch(/Starts the application in development mode/)
|
||||
})
|
||||
|
||||
test('custom directory', async () => {
|
||||
const port = await findPort()
|
||||
const output = await runNextCommandDev([dir, '--port', port], true)
|
||||
expect(output).toMatch(/Ready on/)
|
||||
})
|
||||
|
||||
test('--port', async () => {
|
||||
const port = await findPort()
|
||||
const output = await runNextCommandDev([dir, '--port', port], true)
|
||||
expect(output).toMatch(new RegExp(`http://localhost:${port}`))
|
||||
})
|
||||
|
||||
test('-p', async () => {
|
||||
const port = await findPort()
|
||||
const output = await runNextCommandDev([dir, '-p', port], true)
|
||||
expect(output).toMatch(new RegExp(`http://localhost:${port}`))
|
||||
})
|
||||
|
||||
test('--hostname', async () => {
|
||||
const port = await findPort()
|
||||
const output = await runNextCommandDev([dir, '--hostname', '0.0.0.0', '--port', port], true)
|
||||
expect(output).toMatch(new RegExp(`http://0.0.0.0:${port}`))
|
||||
})
|
||||
|
||||
test('-H', async () => {
|
||||
const port = await findPort()
|
||||
const output = await runNextCommandDev([dir, '-H', '0.0.0.0', '--port', port], true)
|
||||
expect(output).toMatch(new RegExp(`http://0.0.0.0:${port}`))
|
||||
})
|
||||
})
|
||||
|
||||
describe('start', () => {
|
||||
test('--help', async () => {
|
||||
const help = await runNextCommand(['start', '--help'], {
|
||||
stdout: true
|
||||
})
|
||||
expect(help.stdout).toMatch(/Starts the application in production mode/)
|
||||
})
|
||||
|
||||
test('-h', async () => {
|
||||
const help = await runNextCommand(['start', '-h'], {
|
||||
stdout: true
|
||||
})
|
||||
expect(help.stdout).toMatch(/Starts the application in production mode/)
|
||||
})
|
||||
})
|
||||
|
||||
describe('export', () => {
|
||||
test('--help', async () => {
|
||||
const help = await runNextCommand(['export', '--help'], {
|
||||
stdout: true
|
||||
})
|
||||
expect(help.stdout).toMatch(/Exports the application/)
|
||||
})
|
||||
|
||||
test('-h', async () => {
|
||||
const help = await runNextCommand(['export', '-h'], {
|
||||
stdout: true
|
||||
})
|
||||
expect(help.stdout).toMatch(/Exports the application/)
|
||||
})
|
||||
})
|
||||
})
|
|
@ -4,7 +4,7 @@ import http from 'http'
|
|||
import express from 'express'
|
||||
import path from 'path'
|
||||
import getPort from 'get-port'
|
||||
import { spawn } from 'child_process'
|
||||
import spawn from 'cross-spawn'
|
||||
import { readFileSync, writeFileSync, existsSync, unlinkSync } from 'fs'
|
||||
import fkill from 'fkill'
|
||||
|
||||
|
@ -12,13 +12,9 @@ import fkill from 'fkill'
|
|||
// This is done so that requiring from `next` works.
|
||||
// The reason we don't import the relative path `../../dist/<etc>` is that it would lead to inconsistent module singletons
|
||||
import server from 'next/dist/server/next'
|
||||
import build from 'next/dist/build'
|
||||
import _export from 'next/dist/export'
|
||||
import _pkg from 'next/package.json'
|
||||
|
||||
export const nextServer = server
|
||||
export const nextBuild = build
|
||||
export const nextExport = _export
|
||||
export const pkg = _pkg
|
||||
|
||||
export function initNextServerScript (scriptPath, successRegexp, env) {
|
||||
|
@ -69,16 +65,40 @@ export function findPort () {
|
|||
return getPort()
|
||||
}
|
||||
|
||||
// Launch the app in dev mode.
|
||||
export function launchApp (dir, port) {
|
||||
export function runNextCommand (argv, options = {}) {
|
||||
const cwd = path.dirname(require.resolve('next/package'))
|
||||
return new Promise((resolve, reject) => {
|
||||
const instance = spawn('node', ['dist/bin/next', dir, '-p', port], { cwd })
|
||||
console.log(`Running command "next ${argv.join(' ')}"`)
|
||||
const instance = spawn('node', ['dist/bin/next', ...argv], { cwd, stdio: options.stdout ? ['ignore', 'pipe', 'ignore'] : 'inherit' })
|
||||
|
||||
let stdoutOutput = ''
|
||||
if (options.stdout) {
|
||||
instance.stdout.on('data', function (chunk) {
|
||||
stdoutOutput += chunk
|
||||
})
|
||||
}
|
||||
|
||||
instance.on('close', () => {
|
||||
resolve({
|
||||
stdout: stdoutOutput
|
||||
})
|
||||
})
|
||||
|
||||
instance.on('error', (err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function runNextCommandDev (argv, stdOut) {
|
||||
const cwd = path.dirname(require.resolve('next/package'))
|
||||
return new Promise((resolve, reject) => {
|
||||
const instance = spawn('node', ['dist/bin/next', ...argv], { cwd })
|
||||
|
||||
function handleStdout (data) {
|
||||
const message = data.toString()
|
||||
if (/> Ready on/.test(message)) {
|
||||
resolve(instance)
|
||||
resolve(stdOut ? message : instance)
|
||||
}
|
||||
process.stdout.write(message)
|
||||
}
|
||||
|
@ -101,6 +121,19 @@ export function launchApp (dir, port) {
|
|||
})
|
||||
}
|
||||
|
||||
// Launch the app in dev mode.
|
||||
export function launchApp (dir, port) {
|
||||
return runNextCommandDev([dir, '-p', port])
|
||||
}
|
||||
|
||||
export function nextBuild (dir) {
|
||||
return runNextCommand(['build', dir])
|
||||
}
|
||||
|
||||
export function nextExport (dir, {outdir}) {
|
||||
return runNextCommand(['export', dir, '--outdir', outdir])
|
||||
}
|
||||
|
||||
// Kill a launched app
|
||||
export async function killApp (instance) {
|
||||
await fkill(instance.pid)
|
||||
|
|
14
yarn.lock
14
yarn.lock
|
@ -1378,6 +1378,13 @@
|
|||
dependencies:
|
||||
"@babel/types" "^7.0.0"
|
||||
|
||||
"@types/cross-spawn@6.0.0":
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/cross-spawn/-/cross-spawn-6.0.0.tgz#320aaf1d1a12979f1b84fe7a5590a7e860bf3a80"
|
||||
integrity sha512-evp2ZGsFw9YKprDbg8ySgC9NA15g3YgiI8ANkGmKKvvi0P2aDGYLPxQIC5qfeKNUOe3TjABVGuah6omPRpIYhg==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/etag@1.8.0":
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/etag/-/etag-1.8.0.tgz#37f0b1f3ea46da7ae319bbedb607e375b4c99f7e"
|
||||
|
@ -1900,6 +1907,11 @@ are-we-there-yet@~1.1.2:
|
|||
delegates "^1.0.0"
|
||||
readable-stream "^2.0.6"
|
||||
|
||||
arg@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/arg/-/arg-3.0.0.tgz#386c20035dfbeb13e280ca8a1e6868aa17942def"
|
||||
integrity sha512-C5Scb477yHhNck9AFzW5RwAzS2Eqn0HR+Fv0pmcZBXBT8g/g7OOuZTr0upVSSUGWZQH+XWdAKIw2OfC86EuggQ==
|
||||
|
||||
argparse@^1.0.7:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
|
||||
|
@ -7530,7 +7542,7 @@ minimist@0.0.8:
|
|||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
|
||||
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
|
||||
|
||||
minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0:
|
||||
minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
|
||||
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
|
||||
|
|
Loading…
Reference in a new issue