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

feat(nuxt): warn on external webpack/nitro/postcss config #22521

Merged
merged 10 commits into from
Aug 8, 2023
19 changes: 10 additions & 9 deletions packages/nuxt/src/core/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import { isIgnored, tryResolveModule, useNuxt } from '@nuxt/kit'
import { interopDefault } from 'mlly'
import { debounce } from 'perfect-debounce'
import { normalize, relative, resolve } from 'pathe'
import type { Nuxt } from 'nuxt/schema'
import type { Nuxt, NuxtBuilder } from 'nuxt/schema'

import { generateApp as _generateApp, createApp } from './app'
import { checkForExternalConfigurationFiles } from './external-config-files'

export async function build (nuxt: Nuxt) {
const app = createApp(nuxt)
Expand Down Expand Up @@ -43,7 +44,7 @@ export async function build (nuxt: Nuxt) {

await nuxt.callHook('build:before')
if (!nuxt.options._prepare) {
await bundle(nuxt)
await Promise.all([checkForExternalConfigurationFiles(), bundle(nuxt)])
await nuxt.callHook('build:done')
}

Expand Down Expand Up @@ -178,23 +179,23 @@ async function bundle (nuxt: Nuxt) {
? await loadBuilder(nuxt, nuxt.options.builder)
: nuxt.options.builder

return bundle(nuxt)
await bundle(nuxt)
} catch (error: any) {
await nuxt.callHook('build:error', error)

if (error.toString().includes('Cannot find module \'@nuxt/webpack-builder\'')) {
throw new Error([
'Could not load `@nuxt/webpack-builder`. You may need to add it to your project dependencies, following the steps in `https://github.com/nuxt/framework/pull/2812`.'
].join('\n'))
throw new Error('Could not load `@nuxt/webpack-builder`. You may need to add it to your project dependencies, following the steps in `https://github.com/nuxt/framework/pull/2812`.')
}

throw error
}
}

async function loadBuilder (nuxt: Nuxt, builder: string) {
async function loadBuilder (nuxt: Nuxt, builder: string): Promise<NuxtBuilder> {
const builderPath = await tryResolveModule(builder, [nuxt.options.rootDir, import.meta.url])
if (builderPath) {
return import(pathToFileURL(builderPath).href)

if (!builderPath) {
throw new Error(`Loading \`${builder}\` builder failed. You can read more about the nuxt \`builder\` option at: \`https://nuxt.com/docs/api/configuration/nuxt-config#builder\``)
}
return import(pathToFileURL(builderPath).href)
}
77 changes: 77 additions & 0 deletions packages/nuxt/src/core/external-config-files.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { findPath } from '@nuxt/kit'
import { basename } from 'pathe'
import { generateApp as _generateApp } from './app'

/**
* Check for those external configuration files that are not compatible with Nuxt,
* and warns the user about them.
*
* @see {@link https://nuxt.com/docs/getting-started/configuration#external-configuration-files}
*/
export async function checkForExternalConfigurationFiles () {
const checkResults = await Promise.all([checkViteConfig(), checkWebpackConfig(), checkNitroConfig(), checkPostCSSConfig()])
const warningMessages = checkResults.filter(Boolean) as string[]

if (!warningMessages.length) {
return
}

const foundOneExternalConfig = warningMessages.length === 1
if (foundOneExternalConfig) {
console.warn(warningMessages[0])
} else {
const warningsAsList = warningMessages.map(message => `- ${message}`).join('\n')
const warning = `Found multiple external configuration files: \n\n${warningsAsList}`
console.warn(warning)
}
}

async function checkViteConfig () {
// https://github.com/vitejs/vite/blob/8fe69524d25d45290179175ba9b9956cbce87a91/packages/vite/src/node/constants.ts#L38
return await checkAndWarnAboutConfigFileExistence({
fileName: 'vite.config',
extensions: ['.js', '.mjs', '.ts', '.cjs', '.mts', '.cts'],
createWarningMessage: foundFile => `Using \`${foundFile}\` is not supported together with Nuxt. Use \`options.vite\` instead. You can read more in \`https://nuxt.com/docs/api/configuration/nuxt-config#vite\`.`
})
}

async function checkWebpackConfig () {
// https://webpack.js.org/configuration/configuration-languages/
return await checkAndWarnAboutConfigFileExistence({
fileName: 'webpack.config',
extensions: ['.js', '.mjs', '.ts', '.cjs', '.mts', '.cts', 'coffee'],
createWarningMessage: foundFile => `Using \`${foundFile}\` is not supported together with Nuxt. Use \`options.webpack\` instead. You can read more in \`https://nuxt.com/docs/api/configuration/nuxt-config#webpack-1\`.`
})
}

async function checkNitroConfig () {
// https://nitro.unjs.io/config#configuration
return await checkAndWarnAboutConfigFileExistence({
fileName: 'nitro.config',
extensions: ['.ts', '.mts'],
createWarningMessage: foundFile => `Using \`${foundFile}\` is not supported together with Nuxt. Use \`options.nitro\` instead. You can read more in \`https://nuxt.com/docs/api/configuration/nuxt-config#nitro\`.`
})
}

async function checkPostCSSConfig () {
return await checkAndWarnAboutConfigFileExistence({
fileName: 'postcss.config',
extensions: ['.js', '.cjs'],
createWarningMessage: foundFile => `Using \`${foundFile}\` is not supported together with Nuxt. Use \`options.postcss\` instead. You can read more in \`https://nuxt.com/docs/api/configuration/nuxt-config#postcss\`.`
})
}

interface CheckAndWarnAboutConfigFileExistenceOptions {
fileName: string,
extensions: string[],
createWarningMessage: (foundFile: string) => string
}

async function checkAndWarnAboutConfigFileExistence (options: CheckAndWarnAboutConfigFileExistenceOptions) {
const { fileName, extensions, createWarningMessage } = options

const configFile = await findPath(fileName, { extensions }).catch(() => null)
if (configFile) {
return createWarningMessage(basename(configFile))
}
}
6 changes: 5 additions & 1 deletion packages/schema/src/types/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export type NuxtConfigLayer = ConfigLayer<NuxtConfig & {
/** Normalized Nuxt options available as `nuxt.options.*` */
export interface NuxtOptions extends Omit<ConfigSchema, 'builder' | 'webpack'> {
sourcemap: Required<Exclude<ConfigSchema['sourcemap'], boolean>>
builder: '@nuxt/vite-builder' | '@nuxt/webpack-builder' | { bundle: (nuxt: Nuxt) => Promise<void> }
builder: '@nuxt/vite-builder' | '@nuxt/webpack-builder' | NuxtBuilder
webpack: ConfigSchema['webpack'] & {
$client: ConfigSchema['webpack']
$server: ConfigSchema['webpack']
Expand All @@ -104,6 +104,10 @@ export interface NuxtOptions extends Omit<ConfigSchema, 'builder' | 'webpack'> {
$schema: SchemaDefinition
}

export interface NuxtBuilder {
bundle: (nuxt: Nuxt) => Promise<void>
}

export interface ViteConfig extends Omit<ViteUserConfig, 'publicDir'> {
/** The path to the entrypoint for the Vite build. */
entry?: string
Expand Down
15 changes: 4 additions & 11 deletions packages/vite/src/vite.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { existsSync } from 'node:fs'
import * as vite from 'vite'
import { basename, dirname, join, resolve } from 'pathe'
import type { Nuxt, ViteConfig } from '@nuxt/schema'
import { dirname, join, resolve } from 'pathe'
import type { Nuxt, NuxtBuilder, ViteConfig } from '@nuxt/schema'
import { addVitePlugin, isIgnored, logger, resolvePath } from '@nuxt/kit'
import replace from '@rollup/plugin-replace'
import { sanitizeFilePath } from 'mlly'
import { withoutLeadingSlash } from 'ufo'
import { filename } from 'pathe/utils'
import { resolveTSConfig } from 'pkg-types'
import { consola } from 'consola'

import { buildClient } from './client'
import { buildServer } from './server'
import virtual from './plugins/virtual'
Expand All @@ -26,14 +26,7 @@ export interface ViteBuildContext {
ssrServer?: vite.ViteDevServer
}

export async function bundle (nuxt: Nuxt) {
// https://github.com/vitejs/vite/blob/8fe69524d25d45290179175ba9b9956cbce87a91/packages/vite/src/node/constants.ts#L38
const viteConfigPrefix = resolve(nuxt.options.rootDir, 'vite.config')
const viteConfigFile = await resolvePath(viteConfigPrefix).catch(() => null)
if (viteConfigFile && viteConfigFile !== viteConfigPrefix) {
consola.warn(`Using \`${basename(viteConfigFile)}\` is not supported together with Nuxt. Use \`options.vite\` instead. You can read more in \`https://nuxt.com/docs/api/configuration/nuxt-config#vite\`.`)
}

export const bundle: NuxtBuilder['bundle'] = async (nuxt) => {
const useAsyncEntry = nuxt.options.experimental.asyncEntry ||
(nuxt.options.vite.devBundler === 'vite-node' && nuxt.options.dev)
const entry = await resolvePath(resolve(nuxt.options.appDir, useAsyncEntry ? 'entry.async' : 'entry'))
Expand Down
7 changes: 4 additions & 3 deletions packages/webpack/src/webpack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import webpackDevMiddleware from 'webpack-dev-middleware'
import webpackHotMiddleware from 'webpack-hot-middleware'
import type { Compiler, Watching } from 'webpack'
import { defu } from 'defu'
import type { Nuxt } from '@nuxt/schema'
import type { NuxtBuilder } from '@nuxt/schema'
import { joinURL } from 'ufo'
import { logger, useNuxt } from '@nuxt/kit'

Expand All @@ -22,7 +22,7 @@ import { applyPresets, createWebpackConfigContext, getWebpackConfig } from './ut
// TODO: Support plugins
// const plugins: string[] = []

export async function bundle (nuxt: Nuxt) {
export const bundle: NuxtBuilder['bundle'] = async (nuxt) => {
registerVirtualModules()

const webpackConfigs = [client, ...nuxt.options.ssr ? [server] : []].map((preset) => {
Expand Down Expand Up @@ -75,7 +75,8 @@ export async function bundle (nuxt: Nuxt) {

// Start Builds
if (nuxt.options.dev) {
return Promise.all(compilers.map(c => compile(c)))
await Promise.all(compilers.map(c => compile(c)))
return
}

for (const c of compilers) {
Expand Down