mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-30 18:58:36 +02:00
166 lines
5 KiB
TypeScript
166 lines
5 KiB
TypeScript
/**
|
|
* 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 path from 'path';
|
|
import {escapePath} from './pathUtils';
|
|
import {
|
|
WEBPACK_URL_LOADER_LIMIT,
|
|
OUTPUT_STATIC_ASSETS_DIR_NAME,
|
|
} from './constants';
|
|
import type {RuleSetRule, LoaderContext} from 'webpack';
|
|
|
|
export type WebpackCompilerName = 'server' | 'client';
|
|
|
|
export function getWebpackLoaderCompilerName(
|
|
context: LoaderContext<unknown>,
|
|
): WebpackCompilerName {
|
|
// eslint-disable-next-line no-underscore-dangle
|
|
const compilerName = context._compiler?.name;
|
|
switch (compilerName) {
|
|
case 'server':
|
|
case 'client':
|
|
return compilerName;
|
|
default:
|
|
throw new Error(
|
|
`Cannot get valid Docusaurus webpack compiler name. Found compilerName=${compilerName}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
type AssetFolder = 'images' | 'files' | 'fonts' | 'medias';
|
|
|
|
type FileLoaderUtils = {
|
|
loaders: {
|
|
file: (options: {folder: AssetFolder}) => RuleSetRule;
|
|
url: (options: {folder: AssetFolder}) => RuleSetRule;
|
|
inlineMarkdownImageFileLoader: string;
|
|
inlineMarkdownAssetImageFileLoader: string;
|
|
inlineMarkdownLinkFileLoader: string;
|
|
};
|
|
rules: {
|
|
images: () => RuleSetRule;
|
|
svgs: () => RuleSetRule;
|
|
fonts: () => RuleSetRule;
|
|
media: () => RuleSetRule;
|
|
otherAssets: () => RuleSetRule;
|
|
};
|
|
};
|
|
|
|
// TODO this historical code is quite messy
|
|
// We should try to get rid of it and move to assets pipeline
|
|
function createFileLoaderUtils({
|
|
isServer,
|
|
}: {
|
|
isServer: boolean;
|
|
}): FileLoaderUtils {
|
|
// Files/images < urlLoaderLimit will be inlined as base64 strings directly in
|
|
// the html
|
|
const urlLoaderLimit = WEBPACK_URL_LOADER_LIMIT;
|
|
|
|
const fileLoaderFileName = (folder: AssetFolder) =>
|
|
path.posix.join(
|
|
OUTPUT_STATIC_ASSETS_DIR_NAME,
|
|
folder,
|
|
'[name]-[contenthash].[ext]',
|
|
);
|
|
|
|
const loaders: FileLoaderUtils['loaders'] = {
|
|
file: (options: {folder: AssetFolder}) => ({
|
|
loader: require.resolve(`file-loader`),
|
|
options: {
|
|
name: fileLoaderFileName(options.folder),
|
|
emitFile: !isServer,
|
|
},
|
|
}),
|
|
url: (options: {folder: AssetFolder}) => ({
|
|
loader: require.resolve('url-loader'),
|
|
options: {
|
|
limit: urlLoaderLimit,
|
|
name: fileLoaderFileName(options.folder),
|
|
fallback: require.resolve('file-loader'),
|
|
emitFile: !isServer,
|
|
},
|
|
}),
|
|
|
|
// TODO avoid conflicts with the ideal-image plugin
|
|
// TODO this may require a little breaking change for ideal-image users?
|
|
// Maybe with the ideal image plugin, all md images should be "ideal"?
|
|
// This is used to force url-loader+file-loader on markdown images
|
|
// https://webpack.js.org/concepts/loaders/#inline
|
|
inlineMarkdownImageFileLoader: `!${escapePath(
|
|
require.resolve('url-loader'),
|
|
)}?limit=${urlLoaderLimit}&name=${fileLoaderFileName(
|
|
'images',
|
|
)}&fallback=${escapePath(require.resolve('file-loader'))}${
|
|
isServer ? `&emitFile=false` : ''
|
|
}!`,
|
|
inlineMarkdownAssetImageFileLoader: `!${escapePath(
|
|
require.resolve('file-loader'),
|
|
)}?name=${fileLoaderFileName('images')}${
|
|
isServer ? `&emitFile=false` : ''
|
|
}!`,
|
|
inlineMarkdownLinkFileLoader: `!${escapePath(
|
|
require.resolve('file-loader'),
|
|
)}?name=${fileLoaderFileName('files')}${
|
|
isServer ? `&emitFile=false` : ''
|
|
}!`,
|
|
};
|
|
|
|
const rules: FileLoaderUtils['rules'] = {
|
|
/**
|
|
* Loads image assets, inlines images via a data URI if they are below
|
|
* the size threshold
|
|
*/
|
|
images: () => ({
|
|
use: [loaders.url({folder: 'images'})],
|
|
test: /\.(?:ico|jpe?g|png|gif|webp|avif)(?:\?.*)?$/i,
|
|
}),
|
|
|
|
/**
|
|
* The SVG rule is isolated on purpose: our SVGR plugin enhances it
|
|
* See https://github.com/facebook/docusaurus/pull/10820
|
|
*/
|
|
svgs: () => ({
|
|
use: [loaders.url({folder: 'images'})],
|
|
test: /\.svg$/i,
|
|
}),
|
|
|
|
fonts: () => ({
|
|
use: [loaders.url({folder: 'fonts'})],
|
|
test: /\.(?:woff2?|eot|ttf|otf)$/i,
|
|
}),
|
|
|
|
/**
|
|
* Loads audio and video and inlines them via a data URI if they are below
|
|
* the size threshold
|
|
*/
|
|
media: () => ({
|
|
use: [loaders.url({folder: 'medias'})],
|
|
test: /\.(?:mp4|avi|mov|mkv|mpg|mpeg|vob|wmv|m4v|webm|ogv|wav|mp3|m4a|aac|oga|flac)$/i,
|
|
}),
|
|
|
|
otherAssets: () => ({
|
|
use: [loaders.file({folder: 'files'})],
|
|
test: /\.(?:pdf|docx?|xlsx?|zip|rar)$/i,
|
|
}),
|
|
};
|
|
|
|
return {loaders, rules};
|
|
}
|
|
|
|
const FileLoaderUtilsMap = {
|
|
server: createFileLoaderUtils({isServer: true}),
|
|
client: createFileLoaderUtils({isServer: false}),
|
|
};
|
|
|
|
/**
|
|
* Returns unified loader configurations to be used for various file types.
|
|
* Inspired by https://github.com/gatsbyjs/gatsby/blob/8e6e021014da310b9cc7d02e58c9b3efe938c665/packages/gatsby/src/utils/webpack-utils.ts#L447
|
|
*/
|
|
export function getFileLoaderUtils(isServer: boolean): FileLoaderUtils {
|
|
return isServer ? FileLoaderUtilsMap.server : FileLoaderUtilsMap.client;
|
|
}
|