diff --git a/__tests__/__fixtures__/configureWebpack/index.ts b/__tests__/__fixtures__/configureWebpack/index.ts new file mode 100644 index 000000000000..9b9b2f95c74c --- /dev/null +++ b/__tests__/__fixtures__/configureWebpack/index.ts @@ -0,0 +1,35 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import type {Plugin} from '../../../packages/docusaurus-types/src/index'; + +export const plugin: Plugin = { + name: 'example-plugin', + configureWebpack(config) { + return { + devServer: { + ...config.devServer, + open: '/docs', + client: {overlay: false}, + }, + optimization: {minimize: false}, + mergeStrategy: {'module.rules': 'prepend'}, + }; + }, +}; + +type WebpackResult = Exclude< + ReturnType>, + void +>; + +export const invalidConfig: WebpackResult = { + devServer: { + // @ts-expect-error The dev server open option does not accept numbers. + open: 42, + }, +}; diff --git a/__tests__/plugin-types.test.ts b/__tests__/plugin-types.test.ts new file mode 100644 index 000000000000..6a6b1fbe1b33 --- /dev/null +++ b/__tests__/plugin-types.test.ts @@ -0,0 +1,36 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import {describe, expect, it} from 'vitest'; +import {fileURLToPath} from 'node:url'; +import ts from 'typescript'; + +describe('plugin types', () => { + it('supports devServer without a consumer importing webpack-dev-server', () => { + const fixture = fileURLToPath( + new URL('./__fixtures__/configureWebpack/index.ts', import.meta.url), + ); + // Compile separately: other tests import webpack-dev-server, which augments + // webpack Configuration and would hide missing imports in our public types. + const program = ts.createProgram([fixture], { + strict: true, + noEmit: true, + skipLibCheck: true, + types: [], + target: ts.ScriptTarget.ESNext, + module: ts.ModuleKind.ESNext, + moduleResolution: ts.ModuleResolutionKind.Bundler, + esModuleInterop: true, + }); + const diagnostics = ts + .getPreEmitDiagnostics(program) + .map((diagnostic) => + ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'), + ); + expect(diagnostics).toEqual([]); + }); +}); diff --git a/packages/docusaurus-types/package.json b/packages/docusaurus-types/package.json index 30d9a61a4b37..eb329558ba61 100644 --- a/packages/docusaurus-types/package.json +++ b/packages/docusaurus-types/package.json @@ -22,6 +22,7 @@ "mdast-util-directive": "catalog:", "utility-types": "catalog:", "webpack": "catalog:", + "webpack-dev-server": "catalog:", "webpack-merge": "catalog:" }, "peerDependencies": { diff --git a/packages/docusaurus-types/src/plugin.d.ts b/packages/docusaurus-types/src/plugin.d.ts index ba777a47d4e3..9a0a1111abc7 100644 --- a/packages/docusaurus-types/src/plugin.d.ts +++ b/packages/docusaurus-types/src/plugin.d.ts @@ -7,6 +7,8 @@ import type {CodeTranslations, TranslationFile} from './i18n'; import type {RuleSetRule, Configuration as WebpackConfiguration} from 'webpack'; +// Load the devServer augmentation of webpack.Configuration. +import type {} from 'webpack-dev-server'; import type {CustomizeRuleString} from 'webpack-merge/dist/types'; import type {Command} from 'commander'; import type Joi from 'joi'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6ccc188d29c9..6cd6517a15da 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2647,6 +2647,9 @@ importers: webpack: specifier: 'catalog:' version: 5.111.0(@swc/core@1.16.2)(@swc/html@1.16.2)(clean-css@5.3.3)(cssnano@7.1.9(postcss@8.5.28))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.28)(sharp@0.35.5(@types/node@26.6.1))(svgo@4.1.0)(uglify-js@3.19.3) + webpack-dev-server: + specifier: 'catalog:' + version: 6.0.0(supports-color@10.2.2)(webpack@5.111.0(@swc/core@1.16.2)(@swc/html@1.16.2)(clean-css@5.3.3)(cssnano@7.1.9(postcss@8.5.28))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.28)(sharp@0.35.5(@types/node@26.6.1))(svgo@4.1.0)(uglify-js@3.19.3)) webpack-merge: specifier: 'catalog:' version: 6.0.1