Convert Export to TypeScript (#8965)

This pull request converts Next.js' export CLI command to use TypeScript. This is useful for upcoming changes.
This commit is contained in:
Joe Haddad 2019-10-04 11:26:44 -04:00 committed by GitHub
parent 9af587930f
commit d299811bfa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 63 additions and 53 deletions

View file

@ -41,7 +41,7 @@ type AmpStatus = {
code: string
}
type AmpPageStatus = {
export type AmpPageStatus = {
[page: string]: { errors: AmpStatus[]; warnings: AmpStatus[] }
}

View file

@ -1,5 +0,0 @@
export default function(
dir: string,
options: any,
configuration?: any
): Promise<void>

View file

@ -1,36 +1,37 @@
import { cpus } from 'os'
import chalk from 'chalk'
import { copyFile as copyFileOrig, existsSync, readFileSync } from 'fs'
import Worker from 'jest-worker'
import { promisify } from 'util'
import mkdirpModule from 'mkdirp'
import { resolve, join, dirname } from 'path'
import { cpus } from 'os'
import { dirname, join, resolve } from 'path'
import { promisify } from 'util'
import { AmpPageStatus, formatAmpMessages } from '../build/output/index'
import createSpinner from '../build/spinner'
import { API_ROUTE } from '../lib/constants'
import { existsSync, readFileSync, copyFile as copyFileOrig } from 'fs'
import { recursiveCopy } from '../lib/recursive-copy'
import { recursiveDelete } from '../lib/recursive-delete'
import { formatAmpMessages } from '../build/output/index'
import { setDistDir as setTelemetryDir } from '../telemetry/storage'
import { recordVersion } from '../telemetry/events'
import loadConfig, {
isTargetLikeServerless
} from '../next-server/server/config'
import {
PHASE_EXPORT,
SERVER_DIRECTORY,
PAGES_MANIFEST,
CONFIG_FILE,
BUILD_ID_FILE,
PRERENDER_MANIFEST,
SERVERLESS_DIRECTORY,
CLIENT_PUBLIC_FILES_PATH,
CLIENT_STATIC_FILES_PATH
CLIENT_STATIC_FILES_PATH,
CONFIG_FILE,
PAGES_MANIFEST,
PHASE_EXPORT,
PRERENDER_MANIFEST,
SERVER_DIRECTORY,
SERVERLESS_DIRECTORY,
} from '../next-server/lib/constants'
import createSpinner from '../build/spinner'
import loadConfig, {
isTargetLikeServerless,
} from '../next-server/server/config'
import { recordVersion } from '../telemetry/events'
import { setDistDir as setTelemetryDir } from '../telemetry/storage'
const mkdirp = promisify(mkdirpModule)
const copyFile = promisify(copyFileOrig)
const createProgress = (total, label = 'Exporting') => {
const createProgress = (total: number, label = 'Exporting') => {
let curProgress = 0
let progressSpinner = createSpinner(`${label} (${curProgress}/${total})`, {
spinner: {
@ -49,10 +50,10 @@ const createProgress = (total, label = 'Exporting') => {
'[====]',
'[=== ]',
'[== ]',
'[= ]'
'[= ]',
],
interval: 80
}
interval: 80,
},
})
return () => {
@ -72,9 +73,19 @@ const createProgress = (total, label = 'Exporting') => {
}
}
export default async function (dir, options, configuration) {
function log (message) {
if (options.silent) return
type ExportPathMap = {
[page: string]: { page: string; query?: { [key: string]: string } }
}
export default async function(
dir: string,
options: any,
configuration?: any
): Promise<void> {
function log(message: string) {
if (options.silent) {
return
}
console.log(message)
}
@ -122,7 +133,7 @@ export default async function (dir, options, configuration) {
)
const pages = options.pages || Object.keys(pagesManifest)
const defaultPathMap = {}
const defaultPathMap: ExportPathMap = {}
for (const page of pages) {
// _document and _app are not real pages
@ -165,7 +176,7 @@ export default async function (dir, options, configuration) {
console.log(
`> No "exportPathMap" found in "${CONFIG_FILE}". Generating map from "./pages"`
)
nextConfig.exportPathMap = async defaultMap => {
nextConfig.exportPathMap = async (defaultMap: ExportPathMap) => {
return defaultMap
}
}
@ -181,18 +192,18 @@ export default async function (dir, options, configuration) {
staticMarkup: false,
hotReloader: null,
canonicalBase: (nextConfig.amp && nextConfig.amp.canonicalBase) || '',
isModern: nextConfig.experimental.modern
isModern: nextConfig.experimental.modern,
}
const { serverRuntimeConfig, publicRuntimeConfig } = nextConfig
if (Object.keys(publicRuntimeConfig).length > 0) {
renderOpts.runtimeConfig = publicRuntimeConfig
;(renderOpts as any).runtimeConfig = publicRuntimeConfig
}
// We need this for server rendering the Link component.
global.__NEXT_DATA__ = {
nextExport: true
;(global as any).__NEXT_DATA__ = {
nextExport: true,
}
log(` launching ${threads} workers`)
@ -201,11 +212,11 @@ export default async function (dir, options, configuration) {
dir,
outDir,
distDir,
buildId
buildId,
})
if (!exportPathMap['/404']) {
exportPathMap['/404.html'] = exportPathMap['/404.html'] || {
page: '/_error'
page: '/_error',
}
}
const exportPaths = Object.keys(exportPathMap)
@ -227,7 +238,7 @@ export default async function (dir, options, configuration) {
const progress = !options.silent && createProgress(filteredPaths.length)
const sprDataDir = options.buildExport ? outDir : join(outDir, '_next/data')
const ampValidations = {}
const ampValidations: AmpPageStatus = {}
let hadValidationError = false
const publicDir = join(dir, CLIENT_PUBLIC_FILES_PATH)
@ -240,19 +251,22 @@ export default async function (dir, options, configuration) {
) {
log(' copying "public" directory')
await recursiveCopy(publicDir, outDir, {
filter (path) {
filter(path) {
// Exclude paths used by pages
return !exportPathMap[path]
}
},
})
}
const worker = new Worker(require.resolve('./worker'), {
maxRetries: 0,
numWorkers: threads,
enableWorkerThreads: true,
exposedMethods: ['default']
})
const worker: Worker & { default: Function } = new Worker(
require.resolve('./worker'),
{
maxRetries: 0,
numWorkers: threads,
enableWorkerThreads: true,
exposedMethods: ['default'],
}
) as any
worker.getStdout().pipe(process.stdout)
worker.getStderr().pipe(process.stderr)
@ -272,16 +286,17 @@ export default async function (dir, options, configuration) {
serverRuntimeConfig,
subFolders,
buildExport: options.buildExport,
serverless: isTargetLikeServerless(nextConfig.target)
serverless: isTargetLikeServerless(nextConfig.target),
})
for (const validation of result.ampValidations || []) {
const { page, result } = validation
ampValidations[page] = result
hadValidationError |=
Array.isArray(result && result.errors) && result.errors.length > 0
hadValidationError =
hadValidationError ||
(Array.isArray(result && result.errors) && result.errors.length > 0)
}
renderError |= result.error
renderError = renderError || !!result.error
if (
options.buildExport &&

View file

@ -105,7 +105,7 @@ function normalizeConfig(phase: string, config: any) {
export default function loadConfig(
phase: string,
dir: string,
customConfig: any
customConfig?: object | null
) {
if (customConfig) {
return assignDefaults({ configOrigin: 'server', ...customConfig })