Files
react-test/docs/next.config.ts
how2ice 005cf56baf
Some checks failed
No response / noResponse (push) Has been cancelled
CI / Continuous releases (push) Has been cancelled
CI / test-dev (macos-latest) (push) Has been cancelled
CI / test-dev (ubuntu-latest) (push) Has been cancelled
CI / test-dev (windows-latest) (push) Has been cancelled
Maintenance / main (push) Has been cancelled
init project
2025-12-12 14:26:25 +09:00

287 lines
11 KiB
TypeScript

// @ts-check
import * as path from 'path';
import * as url from 'url';
import * as fs from 'fs';
// @ts-ignore
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
import { createRequire } from 'module';
import { NextConfig } from 'next';
import { findPages } from './src/modules/utils/find';
import { LANGUAGES, LANGUAGES_SSR, LANGUAGES_IGNORE_PAGES, LANGUAGES_IN_PROGRESS } from './config';
const currentDirectory = url.fileURLToPath(new URL('.', import.meta.url));
const require = createRequire(import.meta.url);
const withDocsInfra = require('./nextConfigDocsInfra');
const workspaceRoot = path.join(currentDirectory, '../');
const l10nPRInNetlify = /^l10n_/.test(process.env.HEAD || '') && process.env.NETLIFY === 'true';
const vercelDeploy = Boolean(process.env.VERCEL);
const isDeployPreview = Boolean(process.env.PULL_REQUEST_ID);
// For crowdin PRs we want to build all locales for testing.
const buildOnlyEnglishLocale = isDeployPreview && !l10nPRInNetlify && !vercelDeploy;
const pkgContent = fs.readFileSync(path.resolve(workspaceRoot, 'package.json'), 'utf8');
const pkg = JSON.parse(pkgContent);
export default withDocsInfra({
webpack: (config: NextConfig, options): NextConfig => {
const plugins = config.plugins.slice();
if (process.env.DOCS_STATS_ENABLED && !options.isServer) {
plugins.push(
// For all options see https://github.com/th0r/webpack-bundle-analyzer#as-plugin
new BundleAnalyzerPlugin({
analyzerMode: 'static',
generateStatsFile: true,
analyzerPort: options.isServer ? 8888 : 8889,
reportTitle: `${options.isServer ? 'server' : 'client'} docs bundle`,
// Will be available at `.next/${statsFilename}`
statsFilename: `stats-${options.isServer ? 'server' : 'client'}.json`,
}),
);
}
// If a module is an webpack "external" the webpack aliases configured are not used.
// Next.js includes node_modules in webpack externals, some of those have dependencies
// on the aliases we defined above.
// So we need tell webpack to not consider those packages as externals.
if (
options.isServer &&
// Next.js executes this twice on the server with React 18 (once per runtime).
// We only care about Node runtime at this point.
(options.nextRuntime === undefined || options.nextRuntime === 'nodejs')
) {
const externals = config.externals.slice(0, -1);
const nextExternals = config.externals.at(-1);
config.externals = [
// @ts-ignore
(ctx, callback) => {
const { request } = ctx;
const hasDependencyOnRepoPackages = [
'material-ui-popup-state',
// Assume any X dependencies depend on a package defined in this repository.
'@mui/x-',
'@toolpad/core',
].some((dep) => request.startsWith(dep));
if (hasDependencyOnRepoPackages) {
return callback(null);
}
return nextExternals(ctx, callback);
},
...externals,
];
}
// @ts-ignore
config.module.rules.forEach((rule) => {
rule.resourceQuery = { not: [/raw/] };
});
return {
...config,
plugins,
resolve: {
...config.resolve,
// resolve .tsx first
alias: {
...config.resolve.alias,
// for 3rd party packages with dependencies in this repository
'@mui/material$': path.resolve(workspaceRoot, 'packages/mui-material/src/index.js'),
'@mui/material/package.json': path.resolve(
workspaceRoot,
'packages/mui-material/package.json',
),
'@mui/material': path.resolve(workspaceRoot, 'packages/mui-material/src'),
'@mui/docs': path.resolve(workspaceRoot, 'packages/mui-docs/src'),
'@mui/icons-material$': path.resolve(
workspaceRoot,
'packages/mui-icons-material/lib/esm/index.js',
),
'@mui/icons-material': path.resolve(workspaceRoot, 'packages/mui-icons-material/lib/esm'),
'@mui/lab': path.resolve(workspaceRoot, 'packages/mui-lab/src'),
'@mui/styled-engine': path.resolve(workspaceRoot, 'packages/mui-styled-engine/src'),
'@mui/system/package.json': path.resolve(
workspaceRoot,
'packages/mui-system/package.json',
),
'@mui/system': path.resolve(workspaceRoot, 'packages/mui-system/src'),
'@mui/private-theming': path.resolve(workspaceRoot, 'packages/mui-private-theming/src'),
'@mui/utils': path.resolve(workspaceRoot, 'packages/mui-utils/src'),
'@mui/material-nextjs': path.resolve(workspaceRoot, 'packages/mui-material-nextjs/src'),
'@mui/joy/package.json': path.resolve(workspaceRoot, 'packages/mui-joy/package.json'),
'@mui/joy': path.resolve(workspaceRoot, 'packages/mui-joy/src'),
},
extensions: [
'.tsx',
// @ts-ignore
...config.resolve.extensions.filter((extension) => extension !== '.tsx'),
],
},
module: {
...config.module,
rules: config.module.rules.concat([
{
test: /\.md$/,
oneOf: [
{
resourceQuery: /muiMarkdown/,
use: [
options.defaultLoaders.babel,
{
loader: require.resolve('@mui/internal-markdown/loader'),
options: {
workspaceRoot,
ignoreLanguagePages: LANGUAGES_IGNORE_PAGES,
languagesInProgress: LANGUAGES_IN_PROGRESS,
packages: [
{
productId: 'material-ui',
paths: [
path.join(workspaceRoot, 'packages/mui-lab/src'),
path.join(workspaceRoot, 'packages/mui-material/src'),
],
},
{
productId: 'joy-ui',
paths: [path.join(workspaceRoot, 'packages/mui-joy/src')],
},
],
env: {
SOURCE_CODE_REPO: options.config.env.SOURCE_CODE_REPO,
LIB_VERSION: options.config.env.LIB_VERSION,
},
},
},
],
},
{
// used in some /getting-started/templates
type: 'asset/source',
},
],
},
// required to transpile ../packages/
{
test: /\.(js|mjs|tsx|ts)$/,
resourceQuery: { not: [/raw/] },
include: [workspaceRoot],
exclude: /(node_modules|mui-icons-material)/,
use: options.defaultLoaders.babel,
},
{
resourceQuery: /raw/,
type: 'asset/source',
},
]),
},
};
},
env: {
// docs-infra
LIB_VERSION: pkg.version,
SOURCE_CODE_REPO: 'https://github.com/mui/material-ui',
SOURCE_GITHUB_BRANCH: 'master', // #target-branch-reference
GITHUB_TEMPLATE_DOCS_FEEDBACK: '4.docs-feedback.yml',
BUILD_ONLY_ENGLISH_LOCALE: String(buildOnlyEnglishLocale),
// MUI Core related
GITHUB_AUTH: process.env.GITHUB_AUTH
? `Basic ${Buffer.from(process.env.GITHUB_AUTH).toString('base64')}`
: '',
MUI_CHAT_API_BASE_URL: 'https://chat-backend.mui.com',
MUI_CHAT_SCOPES: process.env.DEPLOY_ENV === 'production' ? '' : 'material-ui', // Use comma separated list of `productId` (see `_app.js`) to enable MUI Chat on demos
},
// Ensure CSS from the Data Grid packages is included in the build:
// https://github.com/mui/mui-x/issues/17427#issuecomment-2813967605
transpilePackages: ['@mui/x-data-grid', '@mui/x-data-grid-pro', '@mui/x-data-grid-premium'],
distDir: 'export',
// Next.js provides a `defaultPathMap` argument, we could simplify the logic.
// However, we don't in order to prevent any regression in the `findPages()` method.
// @ts-ignore
exportPathMap: () => {
const pages = findPages();
const map = {};
// @ts-ignore
function traverse(pages2, userLanguage) {
const prefix = userLanguage === 'en' ? '' : `/${userLanguage}`;
// @ts-ignore
pages2.forEach((page) => {
// The experiments pages are only meant for experiments, they shouldn't leak to production.
if (
(page.pathname.startsWith('/experiments/') || page.pathname === '/experiments') &&
process.env.DEPLOY_ENV === 'production'
) {
return;
}
// The blog is not translated
if (userLanguage !== 'en' && LANGUAGES_IGNORE_PAGES(page.pathname)) {
return;
}
if (!page.children) {
// map api-docs to api
// i: /api-docs/* > /api/* (old structure)
// ii: /*/api-docs/* > /*/api/* (for new structure)
// @ts-ignore
map[`${prefix}${page.pathname.replace(/^(\/[^/]+)?\/api-docs\/(.*)/, '$1/api/$2')}`] = {
page: page.pathname,
query: {
userLanguage,
},
};
return;
}
traverse(page.children, userLanguage);
});
}
// We want to speed-up the build of pull requests.
// For this, consider only English language on deploy previews, except for crowdin PRs.
if (buildOnlyEnglishLocale) {
// eslint-disable-next-line no-console
console.log('Considering only English for SSR');
traverse(pages, 'en');
} else {
// eslint-disable-next-line no-console
console.log('Considering various locales for SSR');
LANGUAGES_SSR.forEach((userLanguage) => {
traverse(pages, userLanguage);
});
}
return map;
},
redirects: async () => {
return [
{
source: '/base-ui/',
destination: 'https://base-ui.com',
permanent: true,
},
];
},
// Used to signal we run pnpm build
...(process.env.NODE_ENV === 'production'
? {
output: 'export',
}
: {
// rewrites has no effect when run `next export` for production
rewrites: async () => {
return [
{ source: `/:lang(${LANGUAGES.join('|')})?/:rest*`, destination: '/:rest*' },
// Make sure to include the trailing slash if `trailingSlash` option is set
{ source: '/api/:rest*/', destination: '/api-docs/:rest*/' },
{ source: `/static/x/:rest*`, destination: 'http://0.0.0.0:3001/static/x/:rest*' },
];
},
}),
} satisfies NextConfig);