Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check next.config.js settings #10425

Merged
merged 6 commits into from Feb 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/next/build/index.ts
Expand Up @@ -50,8 +50,8 @@ import { normalizePagePath } from '../next-server/server/normalize-page-path'
import {
eventBuildCompleted,
eventBuildOptimize,
eventCliSession,
eventNextPlugins,
eventVersion,
} from '../telemetry/events'
import { Telemetry } from '../telemetry/storage'
import { CompilerResult, runCompiler } from './compiler'
Expand Down Expand Up @@ -161,7 +161,7 @@ export default async function build(dir: string, conf = null): Promise<void> {
let hasPublicDir = false

telemetry.record(
eventVersion({
eventCliSession(PHASE_PRODUCTION_BUILD, dir, {
cliCommand: 'build',
isSrcDir: path.relative(dir, pagesDir!).startsWith('src'),
hasNowJson: !!(await findUp('now.json', { cwd: dir })),
Expand Down
4 changes: 2 additions & 2 deletions packages/next/export/index.ts
Expand Up @@ -31,7 +31,7 @@ import {
import loadConfig, {
isTargetLikeServerless,
} from '../next-server/server/config'
import { eventVersion } from '../telemetry/events'
import { eventCliSession } from '../telemetry/events'
import { Telemetry } from '../telemetry/storage'
import { normalizePagePath } from '../next-server/server/normalize-page-path'

Expand Down Expand Up @@ -105,7 +105,7 @@ export default async function(

if (telemetry) {
telemetry.record(
eventVersion({
eventCliSession(PHASE_EXPORT, distDir, {
cliCommand: 'export',
isSrcDir: null,
hasNowJson: !!(await findUp('now.json', { cwd: dir })),
Expand Down
2 changes: 1 addition & 1 deletion packages/next/next-server/server/config.ts
Expand Up @@ -198,7 +198,7 @@ function assignDefaults(userConfig: { [key: string]: any }) {
return result
}

function normalizeConfig(phase: string, config: any) {
export function normalizeConfig(phase: string, config: any) {
if (typeof config === 'function') {
config = config(phase, { defaultConfig })

Expand Down
4 changes: 2 additions & 2 deletions packages/next/server/next-dev-server.ts
Expand Up @@ -25,7 +25,7 @@ import { __ApiPreviewProps } from '../next-server/server/api-utils'
import Server, { ServerConstructor } from '../next-server/server/next-server'
import { normalizePagePath } from '../next-server/server/normalize-page-path'
import Router, { Params, route } from '../next-server/server/router'
import { eventVersion } from '../telemetry/events'
import { eventCliSession } from '../telemetry/events'
import { Telemetry } from '../telemetry/storage'
import ErrorDebug from './error-debug'
import HotReloader from './hot-reloader'
Expand Down Expand Up @@ -233,7 +233,7 @@ export default class DevServer extends Server {

const telemetry = new Telemetry({ distDir: this.distDir })
telemetry.record(
eventVersion({
eventCliSession(PHASE_DEVELOPMENT_SERVER, this.distDir, {
cliCommand: 'dev',
isSrcDir: relative(this.dir, this.pagesDir!).startsWith('src'),
hasNowJson: !!(await findUp('now.json', { cwd: this.dir })),
Expand Down
105 changes: 90 additions & 15 deletions packages/next/telemetry/events/version.ts
@@ -1,3 +1,13 @@
import findUp from 'find-up'
import path from 'path'
import {
CONFIG_FILE,
PHASE_DEVELOPMENT_SERVER,
PHASE_EXPORT,
PHASE_PRODUCTION_BUILD,
} from '../../next-server/lib/constants'
import { normalizeConfig } from '../../next-server/server/config'

const EVENT_VERSION = 'NEXT_CLI_SESSION_STARTED'

type EventCliSessionStarted = {
Expand All @@ -7,27 +17,92 @@ type EventCliSessionStarted = {
isSrcDir: boolean | null
hasNowJson: boolean
isCustomServer: boolean | null
hasNextConfig: boolean
buildTarget: string
hasWebpackConfig: boolean
hasBabelConfig: boolean
}

function hasBabelConfig(dir: string): boolean {
try {
const noopFile = path.join(dir, 'noop.js')
const res = require('@babel/core').loadPartialConfig({
cwd: dir,
filename: noopFile,
sourceFileName: noopFile,
}) as any
const isForTooling =
res.options?.presets?.every(
(e: any) => e?.file?.request === 'next/babel'
) && res.options?.plugins?.length === 0
return res.hasFilesystemConfig() && !isForTooling
} catch {
return false
}
}

type NextConfigurationPhase =
| typeof PHASE_DEVELOPMENT_SERVER
| typeof PHASE_PRODUCTION_BUILD
| typeof PHASE_EXPORT

function getNextConfig(
phase: NextConfigurationPhase,
dir: string
): { [key: string]: any } | null {
try {
const configurationPath = findUp.sync(CONFIG_FILE, {
cwd: dir,
})

if (configurationPath) {
// This should've already been loaded, and thus should be cached / won't
// be re-evaluated.
const configurationModule = require(configurationPath)

// Re-normalize the configuration.
return normalizeConfig(
phase,
configurationModule.default || configurationModule
)
}
} catch {
// ignored
}
return null
}

export function eventVersion(
event: Omit<EventCliSessionStarted, 'nextVersion' | 'nodeVersion'>
export function eventCliSession(
phase: NextConfigurationPhase,
dir: string,
event: Omit<
EventCliSessionStarted,
| 'nextVersion'
| 'nodeVersion'
| 'hasNextConfig'
| 'buildTarget'
| 'hasWebpackConfig'
| 'hasBabelConfig'
>
): { eventName: string; payload: EventCliSessionStarted }[] {
// This should be an invariant, if it fails our build tooling is broken.
if (typeof process.env.__NEXT_VERSION !== 'string') {
return []
}

return [
{
eventName: EVENT_VERSION,
payload: {
nextVersion: process.env.__NEXT_VERSION,
nodeVersion: process.version,
cliCommand: event.cliCommand,
isSrcDir: event.isSrcDir,
hasNowJson: event.hasNowJson,
isCustomServer: event.isCustomServer,
} as EventCliSessionStarted,
},
]
const userConfiguration = getNextConfig(phase, dir)

const payload: EventCliSessionStarted = {
nextVersion: process.env.__NEXT_VERSION,
nodeVersion: process.version,
cliCommand: event.cliCommand,
isSrcDir: event.isSrcDir,
hasNowJson: event.hasNowJson,
isCustomServer: event.isCustomServer,
hasNextConfig: !!userConfiguration,
buildTarget: userConfiguration?.target ?? 'default',
hasWebpackConfig: typeof userConfiguration?.webpack === 'function',
hasBabelConfig: hasBabelConfig(dir),
}
return [{ eventName: EVENT_VERSION, payload }]
}
3 changes: 3 additions & 0 deletions test/integration/telemetry/.babelrc.default
@@ -0,0 +1,3 @@
{
"presets": ["next/babel"]
}
4 changes: 4 additions & 0 deletions test/integration/telemetry/.babelrc.plugin
@@ -0,0 +1,4 @@
{
"presets": ["next/babel"],
"plugins": ["@babel/plugin-proposal-object-rest-spread"]
}
3 changes: 3 additions & 0 deletions test/integration/telemetry/.babelrc.preset
@@ -0,0 +1,3 @@
{
"presets": ["next/babel", "@babel/preset-flow"]
}
10 changes: 10 additions & 0 deletions test/integration/telemetry/next.config.target
@@ -0,0 +1,10 @@
const { PHASE_PRODUCTION_BUILD } = require('next/constants')

module.exports = phase => {
if (phase === PHASE_PRODUCTION_BUILD) {
return {
target: 'experimental-serverless-trace',
}
}
return {}
}
5 changes: 5 additions & 0 deletions test/integration/telemetry/next.config.webpack
@@ -0,0 +1,5 @@
module.exports = {
webpack(config) {
return config
},
}
10 changes: 10 additions & 0 deletions test/integration/telemetry/package.babel
@@ -0,0 +1,10 @@
{
"babel": {
"presets": [
"next/babel"
],
"plugins": [
"@babel/plugin-proposal-object-rest-spread"
]
}
}