mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-29 18:27:56 +02:00
refactor(core): prepare codebase for swappable bundler (#10497)
This commit is contained in:
parent
611842af91
commit
2495d059de
24 changed files with 430 additions and 121 deletions
|
@ -21,6 +21,7 @@ import {sortRoutes} from '@docusaurus/core/src/server/plugins/routeConfig';
|
|||
import {posixPath} from '@docusaurus/utils';
|
||||
import {normalizePluginOptions} from '@docusaurus/utils-validation';
|
||||
|
||||
import {fromPartial} from '@total-typescript/shoehorn';
|
||||
import pluginContentDocs from '../index';
|
||||
import {toSidebarsProp} from '../props';
|
||||
import {DefaultSidebarItemsGenerator} from '../sidebars/generator';
|
||||
|
@ -288,8 +289,11 @@ describe('simple website', () => {
|
|||
},
|
||||
},
|
||||
isServer: false,
|
||||
utils: createConfigureWebpackUtils({
|
||||
siteConfig: {webpack: {jsLoader: 'babel'}},
|
||||
configureWebpackUtils: await createConfigureWebpackUtils({
|
||||
siteConfig: {
|
||||
webpack: {jsLoader: 'babel'},
|
||||
future: {experimental_faster: fromPartial({})},
|
||||
},
|
||||
}),
|
||||
content,
|
||||
});
|
||||
|
|
17
packages/docusaurus-types/src/bundler.d.ts
vendored
Normal file
17
packages/docusaurus-types/src/bundler.d.ts
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* 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 webpack from 'webpack';
|
||||
|
||||
// We use Webpack and Rspack interchangeably because most Rspack APIs are
|
||||
// compatible with Webpack. So it's ok to use Webpack types for Rspack too.
|
||||
// When compatibility doesn't work, use "CurrentBundler.name"
|
||||
// See https://github.com/facebook/docusaurus/pull/10402
|
||||
export type CurrentBundler = {
|
||||
name: 'webpack' | 'rspack';
|
||||
instance: typeof webpack;
|
||||
};
|
1
packages/docusaurus-types/src/config.d.ts
vendored
1
packages/docusaurus-types/src/config.d.ts
vendored
|
@ -127,6 +127,7 @@ export type FasterConfig = {
|
|||
swcJsLoader: boolean;
|
||||
swcJsMinimizer: boolean;
|
||||
mdxCrossCompilerCache: boolean;
|
||||
rspackBundler: boolean;
|
||||
};
|
||||
|
||||
export type FutureConfig = {
|
||||
|
|
2
packages/docusaurus-types/src/index.d.ts
vendored
2
packages/docusaurus-types/src/index.d.ts
vendored
|
@ -73,6 +73,8 @@ export {
|
|||
HtmlTags,
|
||||
} from './plugin';
|
||||
|
||||
export {CurrentBundler} from './bundler';
|
||||
|
||||
export {
|
||||
RouteConfig,
|
||||
PluginRouteConfig,
|
||||
|
|
4
packages/docusaurus-types/src/plugin.d.ts
vendored
4
packages/docusaurus-types/src/plugin.d.ts
vendored
|
@ -15,6 +15,7 @@ import type {ThemeConfig} from './config';
|
|||
import type {LoadContext, Props} from './context';
|
||||
import type {SwizzleConfig} from './swizzle';
|
||||
import type {RouteConfig} from './routing';
|
||||
import type {CurrentBundler} from './bundler';
|
||||
|
||||
export type PluginOptions = {id?: string} & {[key: string]: unknown};
|
||||
|
||||
|
@ -54,6 +55,7 @@ export type PluginContentLoadedActions = {
|
|||
};
|
||||
|
||||
export type ConfigureWebpackUtils = {
|
||||
currentBundler: CurrentBundler;
|
||||
getStyleLoaders: (
|
||||
isServer: boolean,
|
||||
cssOptions: {[key: string]: unknown},
|
||||
|
@ -130,7 +132,7 @@ export type Plugin<Content = unknown> = {
|
|||
configureWebpack?: (
|
||||
config: WebpackConfiguration,
|
||||
isServer: boolean,
|
||||
utils: ConfigureWebpackUtils,
|
||||
configureWebpackUtils: ConfigureWebpackUtils,
|
||||
content: Content,
|
||||
) => WebpackConfiguration & {
|
||||
mergeStrategy?: {
|
||||
|
|
|
@ -34,7 +34,12 @@ import defaultSSRTemplate from '../templates/ssr.html.template';
|
|||
import type {SSGParams} from '../ssg';
|
||||
|
||||
import type {Manifest} from 'react-loadable-ssr-addon-v5-slorber';
|
||||
import type {LoadedPlugin, Props, RouterType} from '@docusaurus/types';
|
||||
import type {
|
||||
ConfigureWebpackUtils,
|
||||
LoadedPlugin,
|
||||
Props,
|
||||
RouterType,
|
||||
} from '@docusaurus/types';
|
||||
import type {SiteCollectedData} from '../common';
|
||||
|
||||
export type BuildCLIOptions = Pick<
|
||||
|
@ -165,6 +170,8 @@ async function buildLocale({
|
|||
|
||||
const router = siteConfig.future.experimental_router;
|
||||
|
||||
const configureWebpackUtils = await createConfigureWebpackUtils({siteConfig});
|
||||
|
||||
// We can build the 2 configs in parallel
|
||||
const [{clientConfig, clientManifestPath}, {serverConfig, serverBundlePath}] =
|
||||
await PerfLogger.async('Creating webpack configs', () =>
|
||||
|
@ -172,9 +179,11 @@ async function buildLocale({
|
|||
getBuildClientConfig({
|
||||
props,
|
||||
cliOptions,
|
||||
configureWebpackUtils,
|
||||
}),
|
||||
getBuildServerConfig({
|
||||
props,
|
||||
configureWebpackUtils,
|
||||
}),
|
||||
]),
|
||||
);
|
||||
|
@ -324,15 +333,18 @@ async function executeBrokenLinksCheck({
|
|||
async function getBuildClientConfig({
|
||||
props,
|
||||
cliOptions,
|
||||
configureWebpackUtils,
|
||||
}: {
|
||||
props: Props;
|
||||
cliOptions: BuildCLIOptions;
|
||||
configureWebpackUtils: ConfigureWebpackUtils;
|
||||
}) {
|
||||
const {plugins} = props;
|
||||
const result = await createBuildClientConfig({
|
||||
props,
|
||||
minify: cliOptions.minify ?? true,
|
||||
faster: props.siteConfig.future.experimental_faster,
|
||||
configureWebpackUtils,
|
||||
bundleAnalyzer: cliOptions.bundleAnalyzer ?? false,
|
||||
});
|
||||
let {config} = result;
|
||||
|
@ -340,26 +352,29 @@ async function getBuildClientConfig({
|
|||
plugins,
|
||||
config,
|
||||
isServer: false,
|
||||
utils: await createConfigureWebpackUtils({
|
||||
siteConfig: props.siteConfig,
|
||||
}),
|
||||
configureWebpackUtils,
|
||||
});
|
||||
return {clientConfig: config, clientManifestPath: result.clientManifestPath};
|
||||
}
|
||||
|
||||
async function getBuildServerConfig({props}: {props: Props}) {
|
||||
async function getBuildServerConfig({
|
||||
props,
|
||||
configureWebpackUtils,
|
||||
}: {
|
||||
props: Props;
|
||||
configureWebpackUtils: ConfigureWebpackUtils;
|
||||
}) {
|
||||
const {plugins} = props;
|
||||
const result = await createServerConfig({
|
||||
props,
|
||||
configureWebpackUtils,
|
||||
});
|
||||
let {config} = result;
|
||||
config = executePluginsConfigureWebpack({
|
||||
plugins,
|
||||
config,
|
||||
isServer: true,
|
||||
utils: await createConfigureWebpackUtils({
|
||||
siteConfig: props.siteConfig,
|
||||
}),
|
||||
configureWebpackUtils,
|
||||
});
|
||||
return {serverConfig: config, serverBundlePath: result.serverBundlePath};
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import {
|
|||
} from '../../webpack/configure';
|
||||
import {createStartClientConfig} from '../../webpack/client';
|
||||
import type {StartCLIOptions} from './start';
|
||||
import type {Props} from '@docusaurus/types';
|
||||
import type {ConfigureWebpackUtils, Props} from '@docusaurus/types';
|
||||
import type {Compiler} from 'webpack';
|
||||
import type {OpenUrlContext} from './utils';
|
||||
|
||||
|
@ -127,23 +127,26 @@ async function getStartClientConfig({
|
|||
props,
|
||||
minify,
|
||||
poll,
|
||||
configureWebpackUtils,
|
||||
}: {
|
||||
props: Props;
|
||||
minify: boolean;
|
||||
poll: number | boolean | undefined;
|
||||
configureWebpackUtils: ConfigureWebpackUtils;
|
||||
}) {
|
||||
const {plugins, siteConfig} = props;
|
||||
const {plugins} = props;
|
||||
let {clientConfig: config} = await createStartClientConfig({
|
||||
props,
|
||||
minify,
|
||||
faster: props.siteConfig.future.experimental_faster,
|
||||
poll,
|
||||
configureWebpackUtils,
|
||||
});
|
||||
config = executePluginsConfigureWebpack({
|
||||
plugins,
|
||||
config,
|
||||
isServer: false,
|
||||
utils: await createConfigureWebpackUtils({siteConfig}),
|
||||
configureWebpackUtils,
|
||||
});
|
||||
return config;
|
||||
}
|
||||
|
@ -157,10 +160,15 @@ export async function createWebpackDevServer({
|
|||
cliOptions: StartCLIOptions;
|
||||
openUrlContext: OpenUrlContext;
|
||||
}): Promise<WebpackDevServer> {
|
||||
const configureWebpackUtils = await createConfigureWebpackUtils({
|
||||
siteConfig: props.siteConfig,
|
||||
});
|
||||
|
||||
const config = await getStartClientConfig({
|
||||
props,
|
||||
minify: cliOptions.minify ?? true,
|
||||
poll: cliOptions.poll,
|
||||
configureWebpackUtils,
|
||||
});
|
||||
|
||||
const compiler = webpack(config);
|
||||
|
|
|
@ -10,6 +10,7 @@ exports[`loadSiteConfig website with .cjs siteConfig 1`] = `
|
|||
"future": {
|
||||
"experimental_faster": {
|
||||
"mdxCrossCompilerCache": false,
|
||||
"rspackBundler": false,
|
||||
"swcJsLoader": false,
|
||||
"swcJsMinimizer": false,
|
||||
},
|
||||
|
@ -76,6 +77,7 @@ exports[`loadSiteConfig website with ts + js config 1`] = `
|
|||
"future": {
|
||||
"experimental_faster": {
|
||||
"mdxCrossCompilerCache": false,
|
||||
"rspackBundler": false,
|
||||
"swcJsLoader": false,
|
||||
"swcJsMinimizer": false,
|
||||
},
|
||||
|
@ -142,6 +144,7 @@ exports[`loadSiteConfig website with valid JS CJS config 1`] = `
|
|||
"future": {
|
||||
"experimental_faster": {
|
||||
"mdxCrossCompilerCache": false,
|
||||
"rspackBundler": false,
|
||||
"swcJsLoader": false,
|
||||
"swcJsMinimizer": false,
|
||||
},
|
||||
|
@ -208,6 +211,7 @@ exports[`loadSiteConfig website with valid JS ESM config 1`] = `
|
|||
"future": {
|
||||
"experimental_faster": {
|
||||
"mdxCrossCompilerCache": false,
|
||||
"rspackBundler": false,
|
||||
"swcJsLoader": false,
|
||||
"swcJsMinimizer": false,
|
||||
},
|
||||
|
@ -274,6 +278,7 @@ exports[`loadSiteConfig website with valid TypeScript CJS config 1`] = `
|
|||
"future": {
|
||||
"experimental_faster": {
|
||||
"mdxCrossCompilerCache": false,
|
||||
"rspackBundler": false,
|
||||
"swcJsLoader": false,
|
||||
"swcJsMinimizer": false,
|
||||
},
|
||||
|
@ -340,6 +345,7 @@ exports[`loadSiteConfig website with valid TypeScript ESM config 1`] = `
|
|||
"future": {
|
||||
"experimental_faster": {
|
||||
"mdxCrossCompilerCache": false,
|
||||
"rspackBundler": false,
|
||||
"swcJsLoader": false,
|
||||
"swcJsMinimizer": false,
|
||||
},
|
||||
|
@ -406,6 +412,7 @@ exports[`loadSiteConfig website with valid async config 1`] = `
|
|||
"future": {
|
||||
"experimental_faster": {
|
||||
"mdxCrossCompilerCache": false,
|
||||
"rspackBundler": false,
|
||||
"swcJsLoader": false,
|
||||
"swcJsMinimizer": false,
|
||||
},
|
||||
|
@ -474,6 +481,7 @@ exports[`loadSiteConfig website with valid async config creator function 1`] = `
|
|||
"future": {
|
||||
"experimental_faster": {
|
||||
"mdxCrossCompilerCache": false,
|
||||
"rspackBundler": false,
|
||||
"swcJsLoader": false,
|
||||
"swcJsMinimizer": false,
|
||||
},
|
||||
|
@ -542,6 +550,7 @@ exports[`loadSiteConfig website with valid config creator function 1`] = `
|
|||
"future": {
|
||||
"experimental_faster": {
|
||||
"mdxCrossCompilerCache": false,
|
||||
"rspackBundler": false,
|
||||
"swcJsLoader": false,
|
||||
"swcJsMinimizer": false,
|
||||
},
|
||||
|
@ -613,6 +622,7 @@ exports[`loadSiteConfig website with valid siteConfig 1`] = `
|
|||
"future": {
|
||||
"experimental_faster": {
|
||||
"mdxCrossCompilerCache": false,
|
||||
"rspackBundler": false,
|
||||
"swcJsLoader": false,
|
||||
"swcJsMinimizer": false,
|
||||
},
|
||||
|
|
|
@ -80,6 +80,7 @@ exports[`load loads props for site with custom i18n path 1`] = `
|
|||
"future": {
|
||||
"experimental_faster": {
|
||||
"mdxCrossCompilerCache": false,
|
||||
"rspackBundler": false,
|
||||
"swcJsLoader": false,
|
||||
"swcJsMinimizer": false,
|
||||
},
|
||||
|
|
|
@ -49,6 +49,7 @@ describe('normalizeConfig', () => {
|
|||
swcJsLoader: true,
|
||||
swcJsMinimizer: true,
|
||||
mdxCrossCompilerCache: true,
|
||||
rspackBundler: true,
|
||||
},
|
||||
experimental_storage: {
|
||||
type: 'sessionStorage',
|
||||
|
@ -745,6 +746,7 @@ describe('future', () => {
|
|||
swcJsLoader: true,
|
||||
swcJsMinimizer: true,
|
||||
mdxCrossCompilerCache: true,
|
||||
rspackBundler: true,
|
||||
},
|
||||
experimental_storage: {
|
||||
type: 'sessionStorage',
|
||||
|
@ -1095,6 +1097,7 @@ describe('future', () => {
|
|||
swcJsLoader: true,
|
||||
swcJsMinimizer: true,
|
||||
mdxCrossCompilerCache: true,
|
||||
rspackBundler: true,
|
||||
};
|
||||
expect(
|
||||
normalizeConfig({
|
||||
|
@ -1348,5 +1351,76 @@ describe('future', () => {
|
|||
`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('rspackBundler', () => {
|
||||
it('accepts - undefined', () => {
|
||||
const faster: Partial<FasterConfig> = {
|
||||
rspackBundler: undefined,
|
||||
};
|
||||
expect(
|
||||
normalizeConfig({
|
||||
future: {
|
||||
experimental_faster: faster,
|
||||
},
|
||||
}),
|
||||
).toEqual(fasterContaining({rspackBundler: false}));
|
||||
});
|
||||
|
||||
it('accepts - true', () => {
|
||||
const faster: Partial<FasterConfig> = {
|
||||
rspackBundler: true,
|
||||
};
|
||||
expect(
|
||||
normalizeConfig({
|
||||
future: {
|
||||
experimental_faster: faster,
|
||||
},
|
||||
}),
|
||||
).toEqual(fasterContaining({rspackBundler: true}));
|
||||
});
|
||||
|
||||
it('accepts - false', () => {
|
||||
const faster: Partial<FasterConfig> = {
|
||||
rspackBundler: false,
|
||||
};
|
||||
expect(
|
||||
normalizeConfig({
|
||||
future: {
|
||||
experimental_faster: faster,
|
||||
},
|
||||
}),
|
||||
).toEqual(fasterContaining({rspackBundler: false}));
|
||||
});
|
||||
|
||||
it('rejects - null', () => {
|
||||
// @ts-expect-error: invalid
|
||||
const faster: Partial<FasterConfig> = {rspackBundler: 42};
|
||||
expect(() =>
|
||||
normalizeConfig({
|
||||
future: {
|
||||
experimental_faster: faster,
|
||||
},
|
||||
}),
|
||||
).toThrowErrorMatchingInlineSnapshot(`
|
||||
""future.experimental_faster.rspackBundler" must be a boolean
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
it('rejects - number', () => {
|
||||
// @ts-expect-error: invalid
|
||||
const faster: Partial<FasterConfig> = {rspackBundler: 42};
|
||||
expect(() =>
|
||||
normalizeConfig({
|
||||
future: {
|
||||
experimental_faster: faster,
|
||||
},
|
||||
}),
|
||||
).toThrowErrorMatchingInlineSnapshot(`
|
||||
""future.experimental_faster.rspackBundler" must be a boolean
|
||||
"
|
||||
`);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -45,6 +45,7 @@ export const DEFAULT_FASTER_CONFIG: FasterConfig = {
|
|||
swcJsLoader: false,
|
||||
swcJsMinimizer: false,
|
||||
mdxCrossCompilerCache: false,
|
||||
rspackBundler: false,
|
||||
};
|
||||
|
||||
// When using the "faster: true" shortcut
|
||||
|
@ -52,6 +53,7 @@ export const DEFAULT_FASTER_CONFIG_TRUE: FasterConfig = {
|
|||
swcJsLoader: true,
|
||||
swcJsMinimizer: true,
|
||||
mdxCrossCompilerCache: true,
|
||||
rspackBundler: true,
|
||||
};
|
||||
|
||||
export const DEFAULT_FUTURE_CONFIG: FutureConfig = {
|
||||
|
@ -222,6 +224,7 @@ const FASTER_CONFIG_SCHEMA = Joi.alternatives()
|
|||
mdxCrossCompilerCache: Joi.boolean().default(
|
||||
DEFAULT_FASTER_CONFIG.mdxCrossCompilerCache,
|
||||
),
|
||||
rspackBundler: Joi.boolean().default(DEFAULT_FASTER_CONFIG.rspackBundler),
|
||||
}),
|
||||
Joi.boolean()
|
||||
.required()
|
||||
|
|
|
@ -15,8 +15,15 @@ import {
|
|||
DEFAULT_FASTER_CONFIG,
|
||||
DEFAULT_FUTURE_CONFIG,
|
||||
} from '../../server/configValidation';
|
||||
import {createConfigureWebpackUtils} from '../configure';
|
||||
import type {Props} from '@docusaurus/types';
|
||||
|
||||
function createTestConfigureWebpackUtils() {
|
||||
return createConfigureWebpackUtils({
|
||||
siteConfig: {webpack: {jsLoader: 'babel'}, future: DEFAULT_FUTURE_CONFIG},
|
||||
});
|
||||
}
|
||||
|
||||
describe('babel transpilation exclude logic', () => {
|
||||
it('always transpiles client dir files', () => {
|
||||
const clientFiles = [
|
||||
|
@ -115,6 +122,7 @@ describe('base webpack config', () => {
|
|||
isServer: true,
|
||||
minify: true,
|
||||
faster: DEFAULT_FASTER_CONFIG,
|
||||
configureWebpackUtils: await createTestConfigureWebpackUtils(),
|
||||
})
|
||||
).resolve?.alias ?? {}) as {[alias: string]: string};
|
||||
// Make aliases relative so that test work on all computers
|
||||
|
@ -125,7 +133,8 @@ describe('base webpack config', () => {
|
|||
});
|
||||
|
||||
it('uses svg rule', async () => {
|
||||
const fileLoaderUtils = utils.getFileLoaderUtils();
|
||||
const isServer = true;
|
||||
const fileLoaderUtils = utils.getFileLoaderUtils(isServer);
|
||||
const mockSvg = jest.spyOn(fileLoaderUtils.rules, 'svg');
|
||||
jest
|
||||
.spyOn(utils, 'getFileLoaderUtils')
|
||||
|
@ -136,6 +145,7 @@ describe('base webpack config', () => {
|
|||
isServer: false,
|
||||
minify: false,
|
||||
faster: DEFAULT_FASTER_CONFIG,
|
||||
configureWebpackUtils: await createTestConfigureWebpackUtils(),
|
||||
});
|
||||
expect(mockSvg).toHaveBeenCalled();
|
||||
});
|
||||
|
|
|
@ -9,12 +9,25 @@ import webpack from 'webpack';
|
|||
|
||||
import {createBuildClientConfig, createStartClientConfig} from '../client';
|
||||
import {loadSetup} from '../../server/__tests__/testUtils';
|
||||
import {createConfigureWebpackUtils} from '../configure';
|
||||
import {
|
||||
DEFAULT_FASTER_CONFIG,
|
||||
DEFAULT_FUTURE_CONFIG,
|
||||
} from '../../server/configValidation';
|
||||
|
||||
function createTestConfigureWebpackUtils() {
|
||||
return createConfigureWebpackUtils({
|
||||
siteConfig: {webpack: {jsLoader: 'babel'}, future: DEFAULT_FUTURE_CONFIG},
|
||||
});
|
||||
}
|
||||
|
||||
describe('webpack dev config', () => {
|
||||
it('simple start', async () => {
|
||||
const {props} = await loadSetup('simple-site');
|
||||
const {clientConfig} = await createStartClientConfig({
|
||||
props,
|
||||
faster: DEFAULT_FASTER_CONFIG,
|
||||
configureWebpackUtils: await createTestConfigureWebpackUtils(),
|
||||
minify: false,
|
||||
poll: false,
|
||||
});
|
||||
|
@ -25,6 +38,8 @@ describe('webpack dev config', () => {
|
|||
const {props} = await loadSetup('simple-site');
|
||||
const {config} = await createBuildClientConfig({
|
||||
props,
|
||||
faster: DEFAULT_FASTER_CONFIG,
|
||||
configureWebpackUtils: await createTestConfigureWebpackUtils(),
|
||||
minify: false,
|
||||
bundleAnalyzer: false,
|
||||
});
|
||||
|
@ -35,6 +50,8 @@ describe('webpack dev config', () => {
|
|||
const {props} = await loadSetup('custom-site');
|
||||
const {clientConfig} = await createStartClientConfig({
|
||||
props,
|
||||
faster: DEFAULT_FASTER_CONFIG,
|
||||
configureWebpackUtils: await createTestConfigureWebpackUtils(),
|
||||
minify: false,
|
||||
poll: false,
|
||||
});
|
||||
|
@ -45,6 +62,8 @@ describe('webpack dev config', () => {
|
|||
const {props} = await loadSetup('custom-site');
|
||||
const {config} = await createBuildClientConfig({
|
||||
props,
|
||||
faster: DEFAULT_FASTER_CONFIG,
|
||||
configureWebpackUtils: await createTestConfigureWebpackUtils(),
|
||||
minify: false,
|
||||
bundleAnalyzer: false,
|
||||
});
|
||||
|
|
|
@ -14,17 +14,22 @@ import {
|
|||
executePluginsConfigureWebpack,
|
||||
createConfigureWebpackUtils,
|
||||
} from '../configure';
|
||||
import {DEFAULT_FUTURE_CONFIG} from '../../server/configValidation';
|
||||
import type {Configuration} from 'webpack';
|
||||
import type {LoadedPlugin, Plugin} from '@docusaurus/types';
|
||||
|
||||
const utils = createConfigureWebpackUtils({
|
||||
siteConfig: {webpack: {jsLoader: 'babel'}},
|
||||
});
|
||||
function createTestConfigureWebpackUtils() {
|
||||
return createConfigureWebpackUtils({
|
||||
siteConfig: {webpack: {jsLoader: 'babel'}, future: DEFAULT_FUTURE_CONFIG},
|
||||
});
|
||||
}
|
||||
|
||||
const isServer = false;
|
||||
|
||||
describe('extending generated webpack config', () => {
|
||||
it('direct mutation on generated webpack config object', async () => {
|
||||
const utils = await createTestConfigureWebpackUtils();
|
||||
|
||||
// Fake generated webpack config
|
||||
let config: Configuration = {
|
||||
output: {
|
||||
|
@ -52,7 +57,7 @@ describe('extending generated webpack config', () => {
|
|||
configureWebpack,
|
||||
config,
|
||||
isServer,
|
||||
utils,
|
||||
configureWebpackUtils: utils,
|
||||
content: {
|
||||
content: 42,
|
||||
},
|
||||
|
@ -69,6 +74,8 @@ describe('extending generated webpack config', () => {
|
|||
});
|
||||
|
||||
it('webpack-merge with user webpack config object', async () => {
|
||||
const utils = await createTestConfigureWebpackUtils();
|
||||
|
||||
let config: Configuration = {
|
||||
output: {
|
||||
path: __dirname,
|
||||
|
@ -88,7 +95,7 @@ describe('extending generated webpack config', () => {
|
|||
configureWebpack,
|
||||
config,
|
||||
isServer,
|
||||
utils,
|
||||
configureWebpackUtils: utils,
|
||||
content: {
|
||||
content: 42,
|
||||
},
|
||||
|
@ -105,6 +112,8 @@ describe('extending generated webpack config', () => {
|
|||
});
|
||||
|
||||
it('webpack-merge with custom strategy', async () => {
|
||||
const utils = await createTestConfigureWebpackUtils();
|
||||
|
||||
const config: Configuration = {
|
||||
module: {
|
||||
rules: [{use: 'xxx'}, {use: 'yyy'}],
|
||||
|
@ -126,7 +135,7 @@ describe('extending generated webpack config', () => {
|
|||
configureWebpack: createConfigureWebpack(),
|
||||
config,
|
||||
isServer,
|
||||
utils,
|
||||
configureWebpackUtils: utils,
|
||||
content: {content: 42},
|
||||
});
|
||||
expect(defaultStrategyMergeConfig).toEqual({
|
||||
|
@ -139,7 +148,7 @@ describe('extending generated webpack config', () => {
|
|||
configureWebpack: createConfigureWebpack({'module.rules': 'prepend'}),
|
||||
config,
|
||||
isServer,
|
||||
utils,
|
||||
configureWebpackUtils: utils,
|
||||
content: {content: 42},
|
||||
});
|
||||
expect(prependRulesStrategyConfig).toEqual({
|
||||
|
@ -154,7 +163,7 @@ describe('extending generated webpack config', () => {
|
|||
}),
|
||||
config,
|
||||
isServer,
|
||||
utils,
|
||||
configureWebpackUtils: utils,
|
||||
content: {content: 42},
|
||||
});
|
||||
expect(uselessMergeStrategyConfig).toEqual({
|
||||
|
@ -293,11 +302,13 @@ describe('executePluginsConfigureWebpack', () => {
|
|||
});
|
||||
}
|
||||
|
||||
it('can merge Webpack aliases of 2 plugins into base config', () => {
|
||||
it('can merge Webpack aliases of 2 plugins into base config', async () => {
|
||||
const utils = await createTestConfigureWebpackUtils();
|
||||
|
||||
const config = executePluginsConfigureWebpack({
|
||||
config: {resolve: {alias: {'initial-alias': 'initial-alias-value'}}},
|
||||
isServer,
|
||||
utils,
|
||||
configureWebpackUtils: utils,
|
||||
plugins: [
|
||||
fakePlugin({
|
||||
configureWebpack: () => {
|
||||
|
@ -328,11 +339,13 @@ describe('executePluginsConfigureWebpack', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it('can configurePostCSS() for all loaders added through configureWebpack()', () => {
|
||||
it('can configurePostCSS() for all loaders added through configureWebpack()', async () => {
|
||||
const utils = await createTestConfigureWebpackUtils();
|
||||
|
||||
const config = executePluginsConfigureWebpack({
|
||||
config: {},
|
||||
isServer,
|
||||
utils,
|
||||
configureWebpackUtils: utils,
|
||||
plugins: [
|
||||
fakePlugin({
|
||||
configurePostCss: (postCssOptions) => {
|
||||
|
|
|
@ -10,6 +10,14 @@ import webpack from 'webpack';
|
|||
|
||||
import createServerConfig from '../server';
|
||||
import {loadSetup} from '../../server/__tests__/testUtils';
|
||||
import {createConfigureWebpackUtils} from '../configure';
|
||||
import {DEFAULT_FUTURE_CONFIG} from '../../server/configValidation';
|
||||
|
||||
function createTestConfigureWebpackUtils() {
|
||||
return createConfigureWebpackUtils({
|
||||
siteConfig: {webpack: {jsLoader: 'babel'}, future: DEFAULT_FUTURE_CONFIG},
|
||||
});
|
||||
}
|
||||
|
||||
describe('webpack production config', () => {
|
||||
it('simple', async () => {
|
||||
|
@ -17,6 +25,7 @@ describe('webpack production config', () => {
|
|||
const {props} = await loadSetup('simple-site');
|
||||
const {config} = await createServerConfig({
|
||||
props,
|
||||
configureWebpackUtils: await createTestConfigureWebpackUtils(),
|
||||
});
|
||||
webpack.validate(config);
|
||||
});
|
||||
|
@ -26,6 +35,7 @@ describe('webpack production config', () => {
|
|||
const {props} = await loadSetup('custom-site');
|
||||
const {config} = await createServerConfig({
|
||||
props,
|
||||
configureWebpackUtils: await createTestConfigureWebpackUtils(),
|
||||
});
|
||||
webpack.validate(config);
|
||||
});
|
||||
|
|
|
@ -7,17 +7,17 @@
|
|||
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
||||
import {md5Hash, getFileLoaderUtils} from '@docusaurus/utils';
|
||||
import {
|
||||
createJsLoaderFactory,
|
||||
getStyleLoaders,
|
||||
getCustomBabelConfigFilePath,
|
||||
} from './utils';
|
||||
import {createJsLoaderFactory, getCustomBabelConfigFilePath} from './utils';
|
||||
import {getMinimizers} from './minification';
|
||||
import {loadThemeAliases, loadDocusaurusAliases} from './aliases';
|
||||
import {getCSSExtractPlugin} from './currentBundler';
|
||||
import type {Configuration} from 'webpack';
|
||||
import type {FasterConfig, Props} from '@docusaurus/types';
|
||||
import type {
|
||||
ConfigureWebpackUtils,
|
||||
FasterConfig,
|
||||
Props,
|
||||
} from '@docusaurus/types';
|
||||
|
||||
const CSS_REGEX = /\.css$/i;
|
||||
const CSS_MODULE_REGEX = /\.module\.css$/i;
|
||||
|
@ -58,11 +58,13 @@ export async function createBaseConfig({
|
|||
isServer,
|
||||
minify,
|
||||
faster,
|
||||
configureWebpackUtils,
|
||||
}: {
|
||||
props: Props;
|
||||
isServer: boolean;
|
||||
minify: boolean;
|
||||
faster: FasterConfig;
|
||||
configureWebpackUtils: ConfigureWebpackUtils;
|
||||
}): Promise<Configuration> {
|
||||
const {
|
||||
outDir,
|
||||
|
@ -88,6 +90,10 @@ export async function createBaseConfig({
|
|||
|
||||
const createJsLoader = await createJsLoaderFactory({siteConfig});
|
||||
|
||||
const CSSExtractPlugin = await getCSSExtractPlugin({
|
||||
currentBundler: configureWebpackUtils.currentBundler,
|
||||
});
|
||||
|
||||
return {
|
||||
mode,
|
||||
name,
|
||||
|
@ -224,7 +230,7 @@ export async function createBaseConfig({
|
|||
{
|
||||
test: CSS_REGEX,
|
||||
exclude: CSS_MODULE_REGEX,
|
||||
use: getStyleLoaders(isServer, {
|
||||
use: configureWebpackUtils.getStyleLoaders(isServer, {
|
||||
importLoaders: 1,
|
||||
sourceMap: !isProd,
|
||||
}),
|
||||
|
@ -233,7 +239,7 @@ export async function createBaseConfig({
|
|||
// using the extension .module.css
|
||||
{
|
||||
test: CSS_MODULE_REGEX,
|
||||
use: getStyleLoaders(isServer, {
|
||||
use: configureWebpackUtils.getStyleLoaders(isServer, {
|
||||
modules: {
|
||||
// Using the same CSS Module class pattern in dev/prod on purpose
|
||||
// See https://github.com/facebook/docusaurus/pull/10423
|
||||
|
@ -247,7 +253,7 @@ export async function createBaseConfig({
|
|||
],
|
||||
},
|
||||
plugins: [
|
||||
new MiniCssExtractPlugin({
|
||||
new CSSExtractPlugin({
|
||||
filename: isProd
|
||||
? 'assets/css/[name].[contenthash:8].css'
|
||||
: '[name].css',
|
||||
|
|
|
@ -17,7 +17,11 @@ import ChunkAssetPlugin from './plugins/ChunkAssetPlugin';
|
|||
import CleanWebpackPlugin from './plugins/CleanWebpackPlugin';
|
||||
import ForceTerminatePlugin from './plugins/ForceTerminatePlugin';
|
||||
import {createStaticDirectoriesCopyPlugin} from './plugins/StaticDirectoriesCopyPlugin';
|
||||
import type {FasterConfig, Props} from '@docusaurus/types';
|
||||
import type {
|
||||
ConfigureWebpackUtils,
|
||||
FasterConfig,
|
||||
Props,
|
||||
} from '@docusaurus/types';
|
||||
import type {Configuration} from 'webpack';
|
||||
|
||||
async function createBaseClientConfig({
|
||||
|
@ -25,17 +29,20 @@ async function createBaseClientConfig({
|
|||
hydrate,
|
||||
minify,
|
||||
faster,
|
||||
configureWebpackUtils,
|
||||
}: {
|
||||
props: Props;
|
||||
hydrate: boolean;
|
||||
minify: boolean;
|
||||
faster: FasterConfig;
|
||||
configureWebpackUtils: ConfigureWebpackUtils;
|
||||
}): Promise<Configuration> {
|
||||
const baseConfig = await createBaseConfig({
|
||||
props,
|
||||
isServer: false,
|
||||
minify,
|
||||
faster,
|
||||
configureWebpackUtils,
|
||||
});
|
||||
|
||||
return merge(baseConfig, {
|
||||
|
@ -57,7 +64,10 @@ async function createBaseClientConfig({
|
|||
new WebpackBar({
|
||||
name: 'Client',
|
||||
}),
|
||||
await createStaticDirectoriesCopyPlugin({props}),
|
||||
await createStaticDirectoriesCopyPlugin({
|
||||
props,
|
||||
currentBundler: configureWebpackUtils.currentBundler,
|
||||
}),
|
||||
].filter(Boolean),
|
||||
});
|
||||
}
|
||||
|
@ -68,11 +78,13 @@ export async function createStartClientConfig({
|
|||
minify,
|
||||
poll,
|
||||
faster,
|
||||
configureWebpackUtils,
|
||||
}: {
|
||||
props: Props;
|
||||
minify: boolean;
|
||||
poll: number | boolean | undefined;
|
||||
faster: FasterConfig;
|
||||
configureWebpackUtils: ConfigureWebpackUtils;
|
||||
}): Promise<{clientConfig: Configuration}> {
|
||||
const {siteConfig, headTags, preBodyTags, postBodyTags} = props;
|
||||
|
||||
|
@ -82,6 +94,7 @@ export async function createStartClientConfig({
|
|||
minify,
|
||||
hydrate: false,
|
||||
faster,
|
||||
configureWebpackUtils,
|
||||
}),
|
||||
{
|
||||
watchOptions: {
|
||||
|
@ -116,11 +129,13 @@ export async function createBuildClientConfig({
|
|||
props,
|
||||
minify,
|
||||
faster,
|
||||
configureWebpackUtils,
|
||||
bundleAnalyzer,
|
||||
}: {
|
||||
props: Props;
|
||||
minify: boolean;
|
||||
faster: FasterConfig;
|
||||
configureWebpackUtils: ConfigureWebpackUtils;
|
||||
bundleAnalyzer: boolean;
|
||||
}): Promise<{config: Configuration; clientManifestPath: string}> {
|
||||
// Apply user webpack config.
|
||||
|
@ -137,7 +152,13 @@ export async function createBuildClientConfig({
|
|||
);
|
||||
|
||||
const config: Configuration = merge(
|
||||
await createBaseClientConfig({props, minify, faster, hydrate}),
|
||||
await createBaseClientConfig({
|
||||
props,
|
||||
minify,
|
||||
faster,
|
||||
configureWebpackUtils,
|
||||
hydrate,
|
||||
}),
|
||||
{
|
||||
plugins: [
|
||||
new ForceTerminatePlugin(),
|
||||
|
|
|
@ -10,8 +10,8 @@ import {
|
|||
customizeArray,
|
||||
customizeObject,
|
||||
} from 'webpack-merge';
|
||||
import {createJsLoaderFactory, getStyleLoaders} from './utils';
|
||||
|
||||
import {createJsLoaderFactory, createStyleLoadersFactory} from './utils';
|
||||
import {getCurrentBundler} from './currentBundler';
|
||||
import type {Configuration, RuleSetRule} from 'webpack';
|
||||
import type {
|
||||
Plugin,
|
||||
|
@ -27,11 +27,16 @@ import type {
|
|||
export async function createConfigureWebpackUtils({
|
||||
siteConfig,
|
||||
}: {
|
||||
siteConfig: Parameters<typeof createJsLoaderFactory>[0]['siteConfig'];
|
||||
siteConfig: Parameters<typeof createJsLoaderFactory>[0]['siteConfig'] &
|
||||
Parameters<typeof getCurrentBundler>[0]['siteConfig'];
|
||||
}): Promise<ConfigureWebpackUtils> {
|
||||
const currentBundler = await getCurrentBundler({siteConfig});
|
||||
const getStyleLoaders = await createStyleLoadersFactory({currentBundler});
|
||||
const getJSLoader = await createJsLoaderFactory({siteConfig});
|
||||
return {
|
||||
currentBundler,
|
||||
getStyleLoaders,
|
||||
getJSLoader: await createJsLoaderFactory({siteConfig}),
|
||||
getJSLoader,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -48,18 +53,18 @@ export function applyConfigureWebpack({
|
|||
configureWebpack,
|
||||
config,
|
||||
isServer,
|
||||
utils,
|
||||
configureWebpackUtils,
|
||||
content,
|
||||
}: {
|
||||
configureWebpack: NonNullable<Plugin['configureWebpack']>;
|
||||
config: Configuration;
|
||||
isServer: boolean;
|
||||
utils: ConfigureWebpackUtils;
|
||||
configureWebpackUtils: ConfigureWebpackUtils;
|
||||
content: unknown;
|
||||
}): Configuration {
|
||||
if (typeof configureWebpack === 'function') {
|
||||
const {mergeStrategy, ...res} =
|
||||
configureWebpack(config, isServer, utils, content) ?? {};
|
||||
configureWebpack(config, isServer, configureWebpackUtils, content) ?? {};
|
||||
const customizeRules = mergeStrategy ?? {};
|
||||
return mergeWithCustomize({
|
||||
customizeArray: customizeArray(customizeRules),
|
||||
|
@ -134,12 +139,12 @@ export function executePluginsConfigureWebpack({
|
|||
plugins,
|
||||
config: configInput,
|
||||
isServer,
|
||||
utils,
|
||||
configureWebpackUtils,
|
||||
}: {
|
||||
plugins: LoadedPlugin[];
|
||||
config: Configuration;
|
||||
isServer: boolean;
|
||||
utils: ConfigureWebpackUtils;
|
||||
configureWebpackUtils: ConfigureWebpackUtils;
|
||||
}): Configuration {
|
||||
let config = configInput;
|
||||
|
||||
|
@ -151,7 +156,7 @@ export function executePluginsConfigureWebpack({
|
|||
configureWebpack: configureWebpack.bind(plugin), // The plugin lifecycle may reference `this`.
|
||||
config,
|
||||
isServer,
|
||||
utils,
|
||||
configureWebpackUtils,
|
||||
content: plugin.content,
|
||||
});
|
||||
}
|
||||
|
|
66
packages/docusaurus/src/webpack/currentBundler.ts
Normal file
66
packages/docusaurus/src/webpack/currentBundler.ts
Normal file
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* 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 webpack from 'webpack';
|
||||
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
||||
import CopyWebpackPlugin from 'copy-webpack-plugin';
|
||||
import logger from '@docusaurus/logger';
|
||||
import type {CurrentBundler, DocusaurusConfig} from '@docusaurus/types';
|
||||
|
||||
// We inject a site config slice because the Rspack flag might change place
|
||||
type SiteConfigSlice = {
|
||||
future: {
|
||||
experimental_faster: Pick<
|
||||
DocusaurusConfig['future']['experimental_faster'],
|
||||
'rspackBundler'
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
function isRspack(siteConfig: SiteConfigSlice): boolean {
|
||||
return siteConfig.future.experimental_faster.rspackBundler;
|
||||
}
|
||||
|
||||
export async function getCurrentBundler({
|
||||
siteConfig,
|
||||
}: {
|
||||
siteConfig: SiteConfigSlice;
|
||||
}): Promise<CurrentBundler> {
|
||||
if (isRspack(siteConfig)) {
|
||||
// TODO add support for Rspack
|
||||
logger.error(
|
||||
'Rspack bundler is not supported yet, will use Webpack instead',
|
||||
);
|
||||
}
|
||||
return {
|
||||
name: 'webpack',
|
||||
instance: webpack,
|
||||
};
|
||||
}
|
||||
|
||||
export async function getCSSExtractPlugin({
|
||||
currentBundler,
|
||||
}: {
|
||||
currentBundler: CurrentBundler;
|
||||
}): Promise<typeof MiniCssExtractPlugin> {
|
||||
if (currentBundler.name === 'rspack') {
|
||||
throw new Error('Rspack bundler is not supported yet');
|
||||
}
|
||||
return MiniCssExtractPlugin;
|
||||
}
|
||||
|
||||
export async function getCopyPlugin({
|
||||
currentBundler,
|
||||
}: {
|
||||
currentBundler: CurrentBundler;
|
||||
}): Promise<typeof CopyWebpackPlugin> {
|
||||
if (currentBundler.name === 'rspack') {
|
||||
throw new Error('Rspack bundler is not supported yet');
|
||||
}
|
||||
// https://github.com/webpack-contrib/copy-webpack-plugin
|
||||
return CopyWebpackPlugin;
|
||||
}
|
|
@ -7,14 +7,21 @@
|
|||
|
||||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import CopyWebpackPlugin from 'copy-webpack-plugin';
|
||||
import type {Props} from '@docusaurus/types';
|
||||
import {getCopyPlugin} from '../currentBundler';
|
||||
import type {CurrentBundler, Props} from '@docusaurus/types';
|
||||
import type {WebpackPluginInstance} from 'webpack';
|
||||
|
||||
export async function createStaticDirectoriesCopyPlugin({
|
||||
props,
|
||||
currentBundler,
|
||||
}: {
|
||||
props: Props;
|
||||
}): Promise<CopyWebpackPlugin | undefined> {
|
||||
currentBundler: CurrentBundler;
|
||||
}): Promise<WebpackPluginInstance | undefined> {
|
||||
const CopyPlugin = await getCopyPlugin({
|
||||
currentBundler,
|
||||
});
|
||||
|
||||
const {
|
||||
outDir,
|
||||
siteDir,
|
||||
|
@ -44,7 +51,7 @@ export async function createStaticDirectoriesCopyPlugin({
|
|||
return undefined;
|
||||
}
|
||||
|
||||
return new CopyWebpackPlugin({
|
||||
return new CopyPlugin({
|
||||
patterns: staticDirectories.map((dir) => ({
|
||||
from: dir,
|
||||
to: outDir,
|
||||
|
|
|
@ -10,19 +10,22 @@ import merge from 'webpack-merge';
|
|||
import {NODE_MAJOR_VERSION, NODE_MINOR_VERSION} from '@docusaurus/utils';
|
||||
import WebpackBar from 'webpackbar';
|
||||
import {createBaseConfig} from './base';
|
||||
import type {Props} from '@docusaurus/types';
|
||||
import type {ConfigureWebpackUtils, Props} from '@docusaurus/types';
|
||||
import type {Configuration} from 'webpack';
|
||||
|
||||
export default async function createServerConfig(params: {
|
||||
export default async function createServerConfig({
|
||||
props,
|
||||
configureWebpackUtils,
|
||||
}: {
|
||||
props: Props;
|
||||
configureWebpackUtils: ConfigureWebpackUtils;
|
||||
}): Promise<{config: Configuration; serverBundlePath: string}> {
|
||||
const {props} = params;
|
||||
|
||||
const baseConfig = await createBaseConfig({
|
||||
props,
|
||||
isServer: true,
|
||||
minify: false,
|
||||
faster: props.siteConfig.future.experimental_faster,
|
||||
configureWebpackUtils,
|
||||
});
|
||||
|
||||
const outputFilename = 'server.bundle.js';
|
||||
|
|
|
@ -10,11 +10,15 @@ import path from 'path';
|
|||
import crypto from 'crypto';
|
||||
import logger from '@docusaurus/logger';
|
||||
import {BABEL_CONFIG_FILE_NAME} from '@docusaurus/utils';
|
||||
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
||||
import webpack, {type Configuration, type RuleSetRule} from 'webpack';
|
||||
import webpack, {type Configuration} from 'webpack';
|
||||
import formatWebpackMessages from 'react-dev-utils/formatWebpackMessages';
|
||||
import {importSwcJsLoaderFactory} from '../faster';
|
||||
import type {ConfigureWebpackUtils, DocusaurusConfig} from '@docusaurus/types';
|
||||
import {getCSSExtractPlugin} from './currentBundler';
|
||||
import type {
|
||||
ConfigureWebpackUtils,
|
||||
CurrentBundler,
|
||||
DocusaurusConfig,
|
||||
} from '@docusaurus/types';
|
||||
import type {TransformOptions} from '@babel/core';
|
||||
|
||||
export function formatStatsErrorMessage(
|
||||
|
@ -42,68 +46,75 @@ export function printStatsWarnings(
|
|||
}
|
||||
}
|
||||
|
||||
// Utility method to get style loaders
|
||||
export function getStyleLoaders(
|
||||
isServer: boolean,
|
||||
cssOptionsArg: {
|
||||
[key: string]: unknown;
|
||||
} = {},
|
||||
): RuleSetRule[] {
|
||||
const cssOptions: {[key: string]: unknown} = {
|
||||
// TODO turn esModule on later, see https://github.com/facebook/docusaurus/pull/6424
|
||||
esModule: false,
|
||||
...cssOptionsArg,
|
||||
};
|
||||
export async function createStyleLoadersFactory({
|
||||
currentBundler,
|
||||
}: {
|
||||
currentBundler: CurrentBundler;
|
||||
}): Promise<ConfigureWebpackUtils['getStyleLoaders']> {
|
||||
const CssExtractPlugin = await getCSSExtractPlugin({currentBundler});
|
||||
|
||||
// On the server we don't really need to extract/emit CSS
|
||||
// We only need to transform CSS module imports to a styles object
|
||||
if (isServer) {
|
||||
return cssOptions.modules
|
||||
? [
|
||||
{
|
||||
loader: require.resolve('css-loader'),
|
||||
options: cssOptions,
|
||||
},
|
||||
]
|
||||
: // Ignore regular CSS files
|
||||
[{loader: require.resolve('null-loader')}];
|
||||
}
|
||||
return function getStyleLoaders(
|
||||
isServer: boolean,
|
||||
cssOptionsArg: {
|
||||
[key: string]: unknown;
|
||||
} = {},
|
||||
) {
|
||||
const cssOptions: {[key: string]: unknown} = {
|
||||
// TODO turn esModule on later, see https://github.com/facebook/docusaurus/pull/6424
|
||||
esModule: false,
|
||||
...cssOptionsArg,
|
||||
};
|
||||
|
||||
return [
|
||||
{
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
options: {
|
||||
esModule: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: require.resolve('css-loader'),
|
||||
options: cssOptions,
|
||||
},
|
||||
// On the server we don't really need to extract/emit CSS
|
||||
// We only need to transform CSS module imports to a styles object
|
||||
if (isServer) {
|
||||
return cssOptions.modules
|
||||
? [
|
||||
{
|
||||
loader: require.resolve('css-loader'),
|
||||
options: cssOptions,
|
||||
},
|
||||
]
|
||||
: // Ignore regular CSS files
|
||||
[{loader: require.resolve('null-loader')}];
|
||||
}
|
||||
|
||||
// TODO apart for configurePostCss(), do we really need this loader?
|
||||
// Note: using postcss here looks inefficient/duplicate
|
||||
// But in practice, it's not a big deal because css-loader also uses postcss
|
||||
// and is able to reuse the parsed AST from postcss-loader
|
||||
// See https://github.com/webpack-contrib/css-loader/blob/master/src/index.js#L159
|
||||
{
|
||||
// Options for PostCSS as we reference these options twice
|
||||
// Adds vendor prefixing based on your specified browser support in
|
||||
// package.json
|
||||
loader: require.resolve('postcss-loader'),
|
||||
options: {
|
||||
postcssOptions: {
|
||||
// Necessary for external CSS imports to work
|
||||
// https://github.com/facebook/create-react-app/issues/2677
|
||||
ident: 'postcss',
|
||||
plugins: [
|
||||
// eslint-disable-next-line global-require
|
||||
require('autoprefixer'),
|
||||
],
|
||||
return [
|
||||
{
|
||||
loader: CssExtractPlugin.loader,
|
||||
options: {
|
||||
esModule: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
{
|
||||
loader: require.resolve('css-loader'),
|
||||
options: cssOptions,
|
||||
},
|
||||
|
||||
// TODO apart for configurePostCss(), do we really need this loader?
|
||||
// Note: using postcss here looks inefficient/duplicate
|
||||
// But in practice, it's not a big deal because css-loader also uses postcss
|
||||
// and is able to reuse the parsed AST from postcss-loader
|
||||
// See https://github.com/webpack-contrib/css-loader/blob/master/src/index.js#L159
|
||||
{
|
||||
// Options for PostCSS as we reference these options twice
|
||||
// Adds vendor prefixing based on your specified browser support in
|
||||
// package.json
|
||||
loader: require.resolve('postcss-loader'),
|
||||
options: {
|
||||
postcssOptions: {
|
||||
// Necessary for external CSS imports to work
|
||||
// https://github.com/facebook/create-react-app/issues/2677
|
||||
ident: 'postcss',
|
||||
plugins: [
|
||||
// eslint-disable-next-line global-require
|
||||
require('autoprefixer'),
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
export async function getCustomBabelConfigFilePath(
|
||||
|
|
|
@ -313,6 +313,7 @@ rmiz
|
|||
rsdoctor
|
||||
Rsdoctor
|
||||
RSDOCTOR
|
||||
rspack
|
||||
Rspack
|
||||
rtcts
|
||||
rtlcss
|
||||
|
|
|
@ -5082,7 +5082,7 @@ cacheable-request@^10.2.8:
|
|||
normalize-url "^8.0.0"
|
||||
responselike "^3.0.0"
|
||||
|
||||
call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.7:
|
||||
call-bind@^1.0.2, call-bind@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9"
|
||||
integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==
|
||||
|
@ -8260,7 +8260,7 @@ get-caller-file@^2.0.5:
|
|||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||
|
||||
get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1, get-intrinsic@^1.2.4:
|
||||
get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1, get-intrinsic@^1.2.4:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd"
|
||||
integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==
|
||||
|
@ -12816,7 +12816,7 @@ object-hash@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9"
|
||||
integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==
|
||||
|
||||
object-inspect@^1.12.3, object-inspect@^1.13.1, object-inspect@^1.9.0:
|
||||
object-inspect@^1.12.3, object-inspect@^1.13.1:
|
||||
version "1.13.2"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff"
|
||||
integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==
|
||||
|
|
Loading…
Add table
Reference in a new issue