fix: make Docusaurus PnP strict mode compatible (#6047)

Co-authored-by: Kristoffer K. <merceyz@users.noreply.github.com>
This commit is contained in:
Joshua Chen 2021-12-08 21:26:24 +08:00 committed by GitHub
parent 68b75bf855
commit e07ebadf6c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
65 changed files with 304 additions and 269 deletions

View file

@ -0,0 +1,33 @@
/**
* 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 {getFileLoaderUtils} from '../webpackUtils';
describe('getFileLoaderUtils()', () => {
test('plugin svgo/removeViewBox should be disabled', () => {
const {oneOf} = getFileLoaderUtils().rules.svg();
expect(oneOf[0].use).toContainEqual(
expect.objectContaining({
loader: require.resolve('@svgr/webpack'),
options: expect.objectContaining({
svgoConfig: {
plugins: [
{
name: 'preset-default',
params: {
overrides: {
removeViewBox: false,
},
},
},
],
},
}),
}),
);
});
});

View file

@ -0,0 +1,38 @@
/**
* 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.
*/
export const NODE_MAJOR_VERSION = parseInt(
process.versions.node.split('.')[0],
10,
);
export const NODE_MINOR_VERSION = parseInt(
process.versions.node.split('.')[1],
10,
);
// Can be overridden with cli option --out-dir
export const DEFAULT_BUILD_DIR_NAME = 'build';
// Can be overridden with cli option --config
export const DEFAULT_CONFIG_FILE_NAME = 'docusaurus.config.js';
export const BABEL_CONFIG_FILE_NAME =
process.env.DOCUSAURUS_BABEL_CONFIG_FILE_NAME || 'babel.config.js';
export const GENERATED_FILES_DIR_NAME =
process.env.DOCUSAURUS_GENERATED_FILES_DIR_NAME || '.docusaurus';
export const SRC_DIR_NAME = 'src';
export const STATIC_DIR_NAME = 'static';
export const OUTPUT_STATIC_ASSETS_DIR_NAME = 'assets'; // files handled by webpack, hashed (can be cached aggressively)
export const THEME_PATH = `${SRC_DIR_NAME}/theme`;
export const DEFAULT_PORT = 3000;
export const DEFAULT_PLUGIN_ID = 'default';
// Temporary fix for https://github.com/facebook/docusaurus/issues/5493
export const WEBPACK_URL_LOADER_LIMIT =
process.env.WEBPACK_URL_LOADER_LIMIT ?? 10000;

View file

@ -23,7 +23,9 @@ import resolvePathnameUnsafe from 'resolve-pathname';
import {posixPath as posixPathImport} from './posixPath';
import {simpleHash, docuHash} from './hashUtils';
import {normalizeUrl} from './normalizeUrl';
import {DEFAULT_PLUGIN_ID} from './constants';
export * from './constants';
export * from './mdxUtils';
export * from './normalizeUrl';
export * from './tags';
@ -41,6 +43,7 @@ export {
createMatcher,
createAbsoluteFilePathMatcher,
} from './globUtils';
export * from './webpackUtils';
const fileHash = new Map();
export async function generate(
@ -282,7 +285,7 @@ export function getPluginI18nPath({
siteDir,
locale,
pluginName,
pluginId = 'default', // TODO duplicated constant
pluginId = DEFAULT_PLUGIN_ID,
subPaths = [],
}: {
siteDir: string;
@ -298,10 +301,7 @@ export function getPluginI18nPath({
locale,
// Make it convenient to use for single-instance
// ie: return "docs", not "docs-default" nor "docs/default"
`${pluginName}${
// TODO duplicate constant :(
pluginId === 'default' ? '' : `-${pluginId}`
}`,
`${pluginName}${pluginId === DEFAULT_PLUGIN_ID ? '' : `-${pluginId}`}`,
...subPaths,
);
}

View file

@ -0,0 +1,144 @@
/**
* 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 {RuleSetRule} from 'webpack';
import path from 'path';
import {posixPath} from './posixPath';
import {
WEBPACK_URL_LOADER_LIMIT,
OUTPUT_STATIC_ASSETS_DIR_NAME,
} from './constants';
type AssetFolder = 'images' | 'files' | 'fonts' | 'medias';
type FileLoaderUtils = {
loaders: {
file: (options: {folder: AssetFolder}) => RuleSetRule;
url: (options: {folder: AssetFolder}) => RuleSetRule;
inlineMarkdownImageFileLoader: string;
inlineMarkdownLinkFileLoader: string;
};
rules: {
images: () => RuleSetRule;
fonts: () => RuleSetRule;
media: () => RuleSetRule;
svg: () => RuleSetRule;
otherAssets: () => RuleSetRule;
};
};
// Inspired by https://github.com/gatsbyjs/gatsby/blob/8e6e021014da310b9cc7d02e58c9b3efe938c665/packages/gatsby/src/utils/webpack-utils.ts#L447
export function getFileLoaderUtils(): FileLoaderUtils {
// files/images < urlLoaderLimit will be inlined as base64 strings directly in the html
const urlLoaderLimit = WEBPACK_URL_LOADER_LIMIT;
// defines the path/pattern of the assets handled by webpack
const fileLoaderFileName = (folder: AssetFolder) =>
`${OUTPUT_STATIC_ASSETS_DIR_NAME}/${folder}/[name]-[hash].[ext]`;
const loaders: FileLoaderUtils['loaders'] = {
file: (options: {folder: AssetFolder}) => ({
loader: require.resolve(`file-loader`),
options: {
name: fileLoaderFileName(options.folder),
},
}),
url: (options: {folder: AssetFolder}) => ({
loader: require.resolve('url-loader'),
options: {
limit: urlLoaderLimit,
name: fileLoaderFileName(options.folder),
fallback: require.resolve('file-loader'),
},
}),
// TODO find a better solution to 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: `!${posixPath(
require.resolve('url-loader'),
)}?limit=${urlLoaderLimit}&name=${fileLoaderFileName(
'images',
)}&fallback=${posixPath(require.resolve('file-loader'))}!`,
inlineMarkdownLinkFileLoader: `!${posixPath(
require.resolve('file-loader'),
)}?name=${fileLoaderFileName('files')}!`,
};
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|jpg|jpeg|png|gif|webp)(\?.*)?$/,
}),
fonts: () => ({
use: [loaders.url({folder: 'fonts'})],
test: /\.(woff|woff2|eot|ttf|otf)$/,
}),
/**
* 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|webm|ogv|wav|mp3|m4a|aac|oga|flac)$/,
}),
svg: () => ({
test: /\.svg?$/,
oneOf: [
{
use: [
{
loader: require.resolve('@svgr/webpack'),
options: {
prettier: false,
svgo: true,
svgoConfig: {
plugins: [
{
name: 'preset-default',
params: {
overrides: {
removeViewBox: false,
},
},
},
],
},
titleProp: true,
ref: ![path],
},
},
],
// We don't want to use SVGR loader for non-React source code
// ie we don't want to use SVGR for CSS files...
issuer: {
and: [/\.(ts|tsx|js|jsx|md|mdx)$/],
},
},
{
use: [loaders.url({folder: 'images'})],
},
],
}),
otherAssets: () => ({
use: [loaders.file({folder: 'files'})],
test: /\.(pdf|doc|docx|xls|xlsx|zip|rar)$/,
}),
};
return {loaders, rules};
}