mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-10 15:47:23 +02:00
fix(v2): fix recent baseurl issues (#3093)
* try to fix the baseUrl related issues * fix some newly detected broken links * fix baseurl and broken link issues * try to configure netlify to use baseUrl deployment * add proper netlify settings? * add proper netlify settings? * add proper netlify settings? * test commit * try to fix the redirects * cleanup working conf * minor redirect fix
This commit is contained in:
parent
27f384a67c
commit
811c7ae4e9
30 changed files with 2639 additions and 146 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -27,3 +27,6 @@ packages/docusaurus-plugin-debug/lib/
|
|||
packages/docusaurus-plugin-sitemap/lib/
|
||||
packages/docusaurus-plugin-ideal-image/lib/
|
||||
packages/docusaurus-theme-classic/lib/
|
||||
|
||||
website/netlifyDeploy
|
||||
_redirects
|
||||
|
|
26
netlify.toml
Normal file
26
netlify.toml
Normal file
|
@ -0,0 +1,26 @@
|
|||
|
||||
# Note: this file's config override the Netlify UI admin config
|
||||
|
||||
# default/production build
|
||||
[build]
|
||||
base = "/"
|
||||
command = "yarn netlify:build:production"
|
||||
publish = "website/build"
|
||||
|
||||
# we build deploy previews with a /build/ baseUrl on purpose
|
||||
# permits to test that baseUrl works fine (this often breaks!)
|
||||
[context.deploy-preview]
|
||||
command = "yarn netlify:build:deployPreview"
|
||||
publish = "website/netlifyDeploy"
|
||||
|
||||
# TODO this does not seem to work
|
||||
# workaroud: a _redirect file is created in website/netlifyDeploy
|
||||
# can't we have context-based redirects with Netlify? :'(
|
||||
[[context.deploy-preview.redirects]]
|
||||
from = "/build/*"
|
||||
to = "/build/404.html"
|
||||
status = 200
|
||||
[[context.deploy-preview.redirects]]
|
||||
from = "/*"
|
||||
to = "/build/"
|
||||
|
12
package.json
12
package.json
|
@ -7,20 +7,29 @@
|
|||
"packages/docusaurus-init/templates/*"
|
||||
],
|
||||
"scripts": {
|
||||
"testBaseUrl": "yarn build:v2:baseUrl && yarn serve:v2:baseUrl",
|
||||
"start": "yarn build:packages && yarn start:v2",
|
||||
"start:v1": "yarn workspace docusaurus-1-website start",
|
||||
"start:v2": "yarn workspace docusaurus-2-website start",
|
||||
"start:v2:watch": "nodemon --watch \"./packages/*/lib/**/*.*\" --exec \"yarn start:v2\"",
|
||||
"start:v2:baseUrl": "BASE_URL='/build/' yarn start:v2",
|
||||
"build": "yarn build:packages && yarn build:v2",
|
||||
"build:packages": "lerna run build --no-private",
|
||||
"build:v1": "yarn workspace docusaurus-1-website build",
|
||||
"build:v2": "yarn workspace docusaurus-2-website build",
|
||||
"build:v2:baseUrl": "BASE_URL='/build/' yarn build:v2",
|
||||
"serve:v1": "serve website-1.x/build/docusaurus",
|
||||
"serve:v2": "serve website/build",
|
||||
"serve:v2:baseUrl": "serve website",
|
||||
"serve:v2:ssl": "yarn serve:v2:ssl:gencert && yarn serve:v2:ssl:message && yarn serve:v2:ssl:serve",
|
||||
"serve:v2:ssl:gencert": "openssl req -x509 -nodes -days 365 -newkey rsa:4096 -subj \"/C=US/ST=Docusaurus/L=Anywhere/O=Dis/CN=localhost\" -keyout ./website/.docusaurus/selfsigned.key -out ./website/.docusaurus/selfsigned.crt",
|
||||
"serve:v2:ssl:message": "echo '\n\n\nServing Docusaurus with HTTPS on localhost requires to disable the Chrome security: chrome://flags/#allow-insecure-localhost\n\n\n'",
|
||||
"serve:v2:ssl:serve": "serve website/build --ssl-cert ./website/.docusaurus/selfsigned.crt --ssl-key ./website/.docusaurus/selfsigned.key",
|
||||
"netlify:build:production": "yarn build:v2",
|
||||
"netlify:build:deployPreview": "yarn build:v2:baseUrl && yarn netlify:build:deployPreview:moveBuild && yarn netlify:build:deployPreview:redirects",
|
||||
"netlify:build:deployPreview:moveBuild": "yarn rimraf website/netlifyDeploy && mkdir website/netlifyDeploy && mv website/build website/netlifyDeploy",
|
||||
"netlify:build:deployPreview:redirects": "echo 'Writing Netlify baseUrl deployPreview _redirects file' && echo '/build/* /build/404.html 200' >> website/netlifyDeploy/_redirects && echo '/* /build/' >> website/netlifyDeploy/_redirects",
|
||||
"netlify:test": "yarn netlify:build:deployPreview && yarn netlify dev --debug",
|
||||
"changelog": "lerna-changelog",
|
||||
"postinstall": "yarn build:packages",
|
||||
"prettier": "prettier --config .prettierrc --write \"**/*.{js,ts}\"",
|
||||
|
@ -37,8 +46,8 @@
|
|||
"clear": "yarn rimraf website/.docusaurus && rimraf -rf website/node_modules/.cache && yarn lerna exec 'yarn rimraf lib' --ignore docusaurus"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.9.0",
|
||||
"@babel/cli": "^7.9.0",
|
||||
"@babel/core": "^7.9.0",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.9.0",
|
||||
"@babel/preset-typescript": "^7.9.0",
|
||||
|
@ -88,6 +97,7 @@
|
|||
"lerna": "^3.19.0",
|
||||
"lerna-changelog": "^1.0.1",
|
||||
"lint-staged": "^10.1.2",
|
||||
"netlify-cli": "^2.58.0",
|
||||
"nodemon": "^2.0.4",
|
||||
"prettier": "^2.0.2",
|
||||
"react": "^16.8.4",
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/mdx-loader": "^2.0.0-alpha.58",
|
||||
"@docusaurus/core": "^2.0.0-alpha.58",
|
||||
"@docusaurus/types": "^2.0.0-alpha.58",
|
||||
"@docusaurus/utils": "^2.0.0-alpha.58",
|
||||
"@docusaurus/core": "2.0.0-alpha.58",
|
||||
"@hapi/joi": "^17.1.1",
|
||||
"feed": "^4.1.0",
|
||||
"fs-extra": "^8.1.0",
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/mdx-loader": "^2.0.0-alpha.58",
|
||||
"@docusaurus/core": "^2.0.0-alpha.58",
|
||||
"@docusaurus/types": "^2.0.0-alpha.58",
|
||||
"@docusaurus/utils": "^2.0.0-alpha.58",
|
||||
"execa": "^3.4.0",
|
||||
|
@ -33,8 +34,7 @@
|
|||
"lodash.pickby": "^4.6.0",
|
||||
"lodash.sortby": "^4.6.0",
|
||||
"remark-admonitions": "^1.2.1",
|
||||
"shelljs": "^0.8.4",
|
||||
"@docusaurus/core": "^2.0.0-alpha.58"
|
||||
"shelljs": "^0.8.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.4",
|
||||
|
|
|
@ -178,7 +178,7 @@ Object {
|
|||
"pluginName": Object {
|
||||
"pluginId": Object {
|
||||
"latestVersionName": null,
|
||||
"path": "docs",
|
||||
"path": "/docs",
|
||||
"versions": Array [
|
||||
Object {
|
||||
"docs": Array [
|
||||
|
@ -469,7 +469,7 @@ Object {
|
|||
"pluginName": Object {
|
||||
"pluginId": Object {
|
||||
"latestVersionName": "1.0.1",
|
||||
"path": "docs",
|
||||
"path": "/docs",
|
||||
"versions": Array [
|
||||
Object {
|
||||
"docs": Array [
|
||||
|
|
|
@ -20,12 +20,12 @@ describe('docsClientUtils', () => {
|
|||
test('getActivePlugin', () => {
|
||||
const data: Record<string, GlobalPluginData> = {
|
||||
pluginIosId: {
|
||||
path: 'ios',
|
||||
path: '/ios',
|
||||
latestVersionName: 'xyz',
|
||||
versions: [],
|
||||
},
|
||||
pluginAndroidId: {
|
||||
path: 'android',
|
||||
path: '/android',
|
||||
latestVersionName: 'xyz',
|
||||
versions: [],
|
||||
},
|
||||
|
|
|
@ -30,7 +30,7 @@ export const getActivePlugin = (
|
|||
const activeEntry = Object.entries(allPluginDatas).find(
|
||||
([_id, pluginData]) => {
|
||||
return !!matchPath(pathname, {
|
||||
path: `/${pluginData.path}`,
|
||||
path: pluginData.path,
|
||||
exact: false,
|
||||
strict: false,
|
||||
});
|
||||
|
|
|
@ -323,7 +323,7 @@ Available document ids=
|
|||
const {addRoute, createData, setGlobalData} = actions;
|
||||
|
||||
const pluginInstanceGlobalData: GlobalPluginData = {
|
||||
path: options.path,
|
||||
path: normalizeUrl([baseUrl, options.path]),
|
||||
latestVersionName: versioning.latestVersion,
|
||||
// Initialized empty, will be mutated
|
||||
versions: [],
|
||||
|
|
|
@ -24,10 +24,6 @@ export default {
|
|||
return children;
|
||||
},
|
||||
a: (props: ComponentProps<'a'>): JSX.Element => {
|
||||
if (/\.[^./]+$/.test(props.href || '')) {
|
||||
// eslint-disable-next-line jsx-a11y/anchor-has-content
|
||||
return <a {...props} />;
|
||||
}
|
||||
return <Link {...props} />;
|
||||
},
|
||||
pre: (props: ComponentProps<'div'>): JSX.Element => (
|
||||
|
|
|
@ -28,10 +28,8 @@ function NavLink({
|
|||
activeClassName?: string;
|
||||
prependBaseUrlToHref?: string;
|
||||
} & ComponentProps<'a'>) {
|
||||
const toUrl = useBaseUrl(to);
|
||||
const activeBaseUrl = useBaseUrl(activeBasePath);
|
||||
const normalizedHref = useBaseUrl(href, {forcePrependBaseUrl: true});
|
||||
|
||||
return (
|
||||
<Link
|
||||
{...(href
|
||||
|
@ -43,7 +41,7 @@ function NavLink({
|
|||
: {
|
||||
isNavLink: true,
|
||||
activeClassName,
|
||||
to: toUrl,
|
||||
to,
|
||||
...(activeBasePath || activeBaseRegex
|
||||
? {
|
||||
isActive: (_match, location) =>
|
||||
|
|
|
@ -11,6 +11,7 @@ import {NavLink, Link as RRLink} from 'react-router-dom';
|
|||
import isInternalUrl from './isInternalUrl';
|
||||
import ExecutionEnvironment from './ExecutionEnvironment';
|
||||
import {useLinksCollector} from '../LinksCollector';
|
||||
import {useBaseUrlUtils} from './useBaseUrl';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
|
@ -21,15 +22,37 @@ declare global {
|
|||
interface Props {
|
||||
readonly isNavLink?: boolean;
|
||||
readonly to?: string;
|
||||
readonly activeClassName?: string;
|
||||
readonly href?: string;
|
||||
readonly activeClassName?: string;
|
||||
readonly children?: ReactNode;
|
||||
|
||||
// escape hatch in case broken links check is annoying for a specific link
|
||||
readonly 'data-noBrokenLinkCheck'?: boolean;
|
||||
}
|
||||
|
||||
function Link({isNavLink, activeClassName, ...props}: Props): JSX.Element {
|
||||
function Link({
|
||||
isNavLink,
|
||||
to,
|
||||
href,
|
||||
activeClassName,
|
||||
'data-noBrokenLinkCheck': noBrokenLinkCheck,
|
||||
...props
|
||||
}: Props): JSX.Element {
|
||||
const {withBaseUrl} = useBaseUrlUtils();
|
||||
const linksCollector = useLinksCollector();
|
||||
const {to, href} = props;
|
||||
const targetLink = to || href;
|
||||
|
||||
// IMPORTANT: using to or href should not change anything
|
||||
// For example, MDX links will ALWAYS give us the href props
|
||||
// Using one prop or the other should not be used to distinguish
|
||||
// internal links (/docs/myDoc) from external links (https://github.com)
|
||||
const targetLinkUnprefixed = to || href;
|
||||
|
||||
// Automatically apply base url in links
|
||||
const targetLink =
|
||||
typeof targetLinkUnprefixed !== 'undefined'
|
||||
? withBaseUrl(targetLinkUnprefixed)
|
||||
: undefined;
|
||||
|
||||
const isInternal = isInternalUrl(targetLink);
|
||||
const preloaded = useRef(false);
|
||||
const LinkComponent = isNavLink ? NavLink : RRLink;
|
||||
|
@ -89,10 +112,7 @@ function Link({isNavLink, activeClassName, ...props}: Props): JSX.Element {
|
|||
const isAnchorLink = targetLink?.startsWith('#') ?? false;
|
||||
const isRegularHtmlLink = !targetLink || !isInternal || isAnchorLink;
|
||||
|
||||
if (targetLink && isInternal && !isAnchorLink) {
|
||||
if (targetLink && targetLink.startsWith('/http')) {
|
||||
console.log('collectLink', props);
|
||||
}
|
||||
if (targetLink && isInternal && !isAnchorLink && !noBrokenLinkCheck) {
|
||||
linksCollector.collectLink(targetLink);
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,8 @@ describe('useBaseUrl', () => {
|
|||
expect(useBaseUrl('/hello/byebye', {absolute: true})).toEqual(
|
||||
'https://v2.docusaurus.io/docusaurus/hello/byebye',
|
||||
);
|
||||
expect(useBaseUrl('/docusaurus/')).toEqual('/docusaurus/');
|
||||
expect(useBaseUrl('/docusaurus/hello')).toEqual('/docusaurus/hello');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -125,5 +127,7 @@ describe('useBaseUrlUtils().withBaseUrl()', () => {
|
|||
expect(withBaseUrl('/hello/byebye', {absolute: true})).toEqual(
|
||||
'https://v2.docusaurus.io/docusaurus/hello/byebye',
|
||||
);
|
||||
expect(withBaseUrl('/docusaurus/')).toEqual('/docusaurus/');
|
||||
expect(withBaseUrl('/docusaurus/hello')).toEqual('/docusaurus/hello');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,11 +6,9 @@
|
|||
*/
|
||||
|
||||
import useDocusaurusContext from './useDocusaurusContext';
|
||||
import isInternalUrl from './isInternalUrl';
|
||||
import {hasProtocol} from './isInternalUrl';
|
||||
|
||||
type BaseUrlOptions = Partial<{
|
||||
// note: if the url has a protocol, we never prepend it
|
||||
// (it never makes any sense to do so)
|
||||
forcePrependBaseUrl: boolean;
|
||||
absolute: boolean;
|
||||
}>;
|
||||
|
@ -25,7 +23,8 @@ function addBaseUrl(
|
|||
return url;
|
||||
}
|
||||
|
||||
if (!isInternalUrl(url)) {
|
||||
// it never makes sense to add a base url to an url with a protocol
|
||||
if (hasProtocol(url)) {
|
||||
return url;
|
||||
}
|
||||
|
||||
|
@ -33,7 +32,11 @@ function addBaseUrl(
|
|||
return baseUrl + url;
|
||||
}
|
||||
|
||||
const basePath = baseUrl + url.replace(/^\//, '');
|
||||
// sometimes we try to add baseurl to an url that already has a baseurl
|
||||
// we should avoid adding the baseurl twice
|
||||
const shouldAddBaseUrl = !url.startsWith(baseUrl);
|
||||
|
||||
const basePath = shouldAddBaseUrl ? baseUrl + url.replace(/^\//, '') : url;
|
||||
|
||||
return absolute ? siteUrl + basePath : basePath;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ export default async function build(
|
|||
outDir,
|
||||
generatedFilesDir,
|
||||
plugins,
|
||||
siteConfig: {onBrokenLinks},
|
||||
siteConfig: {baseUrl, onBrokenLinks},
|
||||
routes,
|
||||
} = props;
|
||||
|
||||
|
@ -139,7 +139,13 @@ export default async function build(
|
|||
}),
|
||||
);
|
||||
|
||||
handleBrokenLinks({allCollectedLinks, routes, onBrokenLinks});
|
||||
await handleBrokenLinks({
|
||||
allCollectedLinks,
|
||||
routes,
|
||||
onBrokenLinks,
|
||||
outDir,
|
||||
baseUrl,
|
||||
});
|
||||
|
||||
const relativeDir = path.relative(process.cwd(), outDir);
|
||||
console.log(
|
||||
|
|
|
@ -11,5 +11,6 @@ export const CONFIG_FILE_NAME = 'docusaurus.config.js';
|
|||
export const GENERATED_FILES_DIR_NAME = '.docusaurus';
|
||||
export const SRC_DIR_NAME = 'src';
|
||||
export const STATIC_DIR_NAME = 'static';
|
||||
export const STATIC_ASSETS_DIR_NAME = 'assets'; // webpack file-loader files
|
||||
export const THEME_PATH = `${SRC_DIR_NAME}/theme`;
|
||||
export const DEFAULT_PORT = 3000;
|
||||
|
|
|
@ -5,7 +5,8 @@ exports[`brokenLinks getBrokenLinksErrorMessage 1`] = `
|
|||
|
||||
- Page path = /docs/mySourcePage:
|
||||
-> link to ./myBrokenLink (resolved as: /docs/myBrokenLink)
|
||||
-> link to ../otherBrokenLink (resolved as: /otherBrokenLink),
|
||||
-> link to ../otherBrokenLink (resolved as: /otherBrokenLink)
|
||||
|
||||
|
||||
- Page path = /otherSourcePage:
|
||||
-> link to /badLink
|
||||
|
|
|
@ -8,8 +8,10 @@
|
|||
import {matchRoutes, RouteConfig as RRRouteConfig} from 'react-router-config';
|
||||
import resolvePathname from 'resolve-pathname';
|
||||
import chalk from 'chalk';
|
||||
import fs from 'fs-extra';
|
||||
import {mapValues, pickBy, flatMap} from 'lodash';
|
||||
import {RouteConfig, OnBrokenLinks} from '@docusaurus/types';
|
||||
import {removePrefix} from '@docusaurus/utils';
|
||||
|
||||
function toReactRouterRoutes(routes: RouteConfig[]): RRRouteConfig[] {
|
||||
// @ts-expect-error: types incompatible???
|
||||
|
@ -107,37 +109,79 @@ export function getBrokenLinksErrorMessage(
|
|||
|
||||
return (
|
||||
`Broken links found!` +
|
||||
`${Object.entries(allBrokenLinks).map(([pagePath, brokenLinks]) =>
|
||||
pageBrokenLinksMessage(pagePath, brokenLinks),
|
||||
)}
|
||||
`${Object.entries(allBrokenLinks)
|
||||
.map(([pagePath, brokenLinks]) =>
|
||||
pageBrokenLinksMessage(pagePath, brokenLinks),
|
||||
)
|
||||
.join('\n')}
|
||||
`
|
||||
);
|
||||
}
|
||||
|
||||
export function handleBrokenLinks({
|
||||
// If a file actually exist on the file system, we know the link is valid
|
||||
// even if docusaurus does not know about this file, so we don't report it
|
||||
async function filterExistingFileLinks({
|
||||
baseUrl,
|
||||
outDir,
|
||||
allCollectedLinks,
|
||||
}: {
|
||||
baseUrl: string;
|
||||
outDir: string;
|
||||
allCollectedLinks: Record<string, string[]>;
|
||||
}): Promise<Record<string, string[]>> {
|
||||
// not easy to make this async :'(
|
||||
function linkFileDoesNotExist(link: string): boolean {
|
||||
const filePath = `${outDir}/${removePrefix(link, baseUrl)}`;
|
||||
const exists = fs.existsSync(filePath);
|
||||
return !exists;
|
||||
}
|
||||
|
||||
return mapValues(allCollectedLinks, (links) => {
|
||||
return links.filter(linkFileDoesNotExist);
|
||||
});
|
||||
}
|
||||
|
||||
export async function handleBrokenLinks({
|
||||
allCollectedLinks,
|
||||
onBrokenLinks,
|
||||
routes,
|
||||
baseUrl,
|
||||
outDir,
|
||||
}: {
|
||||
allCollectedLinks: Record<string, string[]>;
|
||||
onBrokenLinks: OnBrokenLinks;
|
||||
routes: RouteConfig[];
|
||||
baseUrl: string;
|
||||
outDir: string;
|
||||
}) {
|
||||
if (onBrokenLinks === 'ignore') {
|
||||
return;
|
||||
}
|
||||
const allBrokenLinks = getAllBrokenLinks({allCollectedLinks, routes});
|
||||
|
||||
// If we link to a file like /myFile.zip, and the file actually exist for the file system
|
||||
// it is not a broken link, it may simply be a link to an existing static file...
|
||||
const allCollectedLinksFiltered = await filterExistingFileLinks({
|
||||
allCollectedLinks,
|
||||
baseUrl,
|
||||
outDir,
|
||||
});
|
||||
|
||||
const allBrokenLinks = getAllBrokenLinks({
|
||||
allCollectedLinks: allCollectedLinksFiltered,
|
||||
routes,
|
||||
});
|
||||
|
||||
const errorMessage = getBrokenLinksErrorMessage(allBrokenLinks);
|
||||
if (errorMessage) {
|
||||
const finalMessage = `${errorMessage}\nNote: it's possible to ignore broken links with the 'onBrokenLinks' Docusaurus configuration.\n\n`;
|
||||
|
||||
// Useful to ensure the CI fails in case of broken link
|
||||
if (onBrokenLinks === 'throw') {
|
||||
throw new Error(
|
||||
`${errorMessage}\nNote: it's possible to ignore broken links with the 'onBrokenLinks' Docusaurus configuration.`,
|
||||
);
|
||||
throw new Error(finalMessage);
|
||||
} else if (onBrokenLinks === 'error') {
|
||||
console.error(chalk.red(errorMessage));
|
||||
console.error(chalk.red(finalMessage));
|
||||
} else if (onBrokenLinks === 'log') {
|
||||
console.log(chalk.blue(errorMessage));
|
||||
console.log(chalk.blue(finalMessage));
|
||||
} else {
|
||||
throw new Error(`unexpected onBrokenLinks value=${onBrokenLinks}`);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import webpack, {Configuration, Loader, RuleSetRule, Stats} from 'webpack';
|
|||
import {TransformOptions} from '@babel/core';
|
||||
import {ConfigureWebpackFn} from '@docusaurus/types';
|
||||
import {version as cacheLoaderVersion} from 'cache-loader/package.json';
|
||||
import {STATIC_ASSETS_DIR_NAME} from '../constants';
|
||||
|
||||
// Utility method to get style loaders
|
||||
export function getStyleLoaders(
|
||||
|
@ -174,14 +175,12 @@ export function compile(config: Configuration[]): Promise<void> {
|
|||
|
||||
// Inspired by https://github.com/gatsbyjs/gatsby/blob/8e6e021014da310b9cc7d02e58c9b3efe938c665/packages/gatsby/src/utils/webpack-utils.ts#L447
|
||||
export function getFileLoaderUtils() {
|
||||
const assetsRelativeRoot = 'assets/';
|
||||
|
||||
const loaders = {
|
||||
file: (options = {}) => {
|
||||
return {
|
||||
loader: require.resolve(`file-loader`),
|
||||
options: {
|
||||
name: `${assetsRelativeRoot}[name]-[hash].[ext]`,
|
||||
name: `${STATIC_ASSETS_DIR_NAME}/[name]-[hash].[ext]`,
|
||||
...options,
|
||||
},
|
||||
};
|
||||
|
@ -191,7 +190,7 @@ export function getFileLoaderUtils() {
|
|||
loader: require.resolve(`url-loader`),
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: `${assetsRelativeRoot}[name]-[hash].[ext]`,
|
||||
name: `${STATIC_ASSETS_DIR_NAME}[name]-[hash].[ext]`,
|
||||
fallback: require.resolve(`file-loader`),
|
||||
...options,
|
||||
},
|
||||
|
|
|
@ -964,6 +964,7 @@ or
|
|||
|
||||

|
||||
```
|
||||
|
||||
The ES imports syntax also works:
|
||||
|
||||
```mdx
|
||||
|
|
|
@ -47,4 +47,4 @@ For themes that supports TypeScript theme components, you can add the `--typescr
|
|||
npm run swizzle @docusaurus/theme-classic Footer --typescript
|
||||
```
|
||||
|
||||
At this moment, the only official Docusaurus theme that supports TypeScript theme components is `@docusaurus/theme-classic`. If you are a Docusaurus theme package author who wants to add TypeScript support, see the [Lifecycle APIs docs](./lifecycle-apis#gettypescriptthemepath).
|
||||
At this moment, the only official Docusaurus theme that supports TypeScript theme components is `@docusaurus/theme-classic`. If you are a Docusaurus theme package author who wants to add TypeScript support, see the [Lifecycle APIs docs](./lifecycle-apis.md#gettypescriptthemepath).
|
||||
|
|
|
@ -61,7 +61,7 @@ npm run docusaurus docs:version 1.1.0
|
|||
When tagging a new version, the document versioning mechanism will:
|
||||
|
||||
- Copy the full `docs/` folder contents into a new `versioned_docs/version-<version>/` folder.
|
||||
- Create a versioned sidebars file based from your current [sidebar](sidebar.md) configuration (if it exists) - saved as `versioned_sidebars/version-<version>-sidebars.json`.
|
||||
- Create a versioned sidebars file based from your current [sidebar](docs.md#sidebar) configuration (if it exists) - saved as `versioned_sidebars/version-<version>-sidebars.json`.
|
||||
- Append the new version number to `versions.json`.
|
||||
|
||||
## Files
|
||||
|
|
|
@ -14,12 +14,14 @@ const allDocHomesPaths = [
|
|||
...versions.slice(1).map((version) => `/docs/${version}/`),
|
||||
];
|
||||
|
||||
const baseUrl = process.env.BASE_URL || '/';
|
||||
|
||||
module.exports = {
|
||||
title: 'Docusaurus',
|
||||
tagline: 'Build optimized websites quickly, focus on your content',
|
||||
organizationName: 'facebook',
|
||||
projectName: 'docusaurus',
|
||||
baseUrl: '/',
|
||||
baseUrl,
|
||||
url: 'https://v2.docusaurus.io',
|
||||
onBrokenLinks: 'throw',
|
||||
favicon: 'img/docusaurus.ico',
|
||||
|
@ -189,7 +191,7 @@ module.exports = {
|
|||
activeBaseRegex: `docs/next/(support|team|resources)`,
|
||||
},
|
||||
{
|
||||
to: 'versions',
|
||||
to: '/versions',
|
||||
label: 'All versions',
|
||||
position: 'right',
|
||||
},
|
||||
|
|
|
@ -63,7 +63,7 @@ npm run docusaurus docs:version 1.1.0
|
|||
When tagging a new version, the document versioning mechanism will:
|
||||
|
||||
- Copy the full `docs/` folder contents into a new `versioned_docs/version-<version>/` folder.
|
||||
- Create a versioned sidebars file based from your current [sidebar](sidebar.md) configuration (if it exists). Saved it as `versioned_sidebars/version-<version>-sidebars.json`.
|
||||
- Create a versioned sidebars file based from your current sidebar configuration (if it exists). Saved it as `versioned_sidebars/version-<version>-sidebars.json`.
|
||||
- Append the new version number into `versions.json`.
|
||||
|
||||
## Files
|
||||
|
|
|
@ -61,7 +61,7 @@ npm run docusaurus docs:version 1.1.0
|
|||
When tagging a new version, the document versioning mechanism will:
|
||||
|
||||
- Copy the full `docs/` folder contents into a new `versioned_docs/version-<version>/` folder.
|
||||
- Create a versioned sidebars file based from your current [sidebar](sidebar.md) configuration (if it exists). Saved it as `versioned_sidebars/version-<version>-sidebars.json`.
|
||||
- Create a versioned sidebars file based from your current [sidebar](docs.md#sidebar) configuration (if it exists). Saved it as `versioned_sidebars/version-<version>-sidebars.json`.
|
||||
- Append the new version number into `versions.json`.
|
||||
|
||||
## Files
|
||||
|
|
|
@ -61,7 +61,7 @@ npm run docusaurus docs:version 1.1.0
|
|||
When tagging a new version, the document versioning mechanism will:
|
||||
|
||||
- Copy the full `docs/` folder contents into a new `versioned_docs/version-<version>/` folder.
|
||||
- Create a versioned sidebars file based from your current [sidebar](sidebar.md) configuration (if it exists) - saved as `versioned_sidebars/version-<version>-sidebars.json`.
|
||||
- Create a versioned sidebars file based from your current [sidebar](docs.md#sidebar) configuration (if it exists) - saved as `versioned_sidebars/version-<version>-sidebars.json`.
|
||||
- Append the new version number to `versions.json`.
|
||||
|
||||
## Files
|
||||
|
|
|
@ -61,7 +61,7 @@ npm run docusaurus docs:version 1.1.0
|
|||
When tagging a new version, the document versioning mechanism will:
|
||||
|
||||
- Copy the full `docs/` folder contents into a new `versioned_docs/version-<version>/` folder.
|
||||
- Create a versioned sidebars file based from your current [sidebar](sidebar.md) configuration (if it exists) - saved as `versioned_sidebars/version-<version>-sidebars.json`.
|
||||
- Create a versioned sidebars file based from your current [sidebar](docs.md#sidebar) configuration (if it exists) - saved as `versioned_sidebars/version-<version>-sidebars.json`.
|
||||
- Append the new version number to `versions.json`.
|
||||
|
||||
## Files
|
||||
|
|
|
@ -61,7 +61,7 @@ npm run docusaurus docs:version 1.1.0
|
|||
When tagging a new version, the document versioning mechanism will:
|
||||
|
||||
- Copy the full `docs/` folder contents into a new `versioned_docs/version-<version>/` folder.
|
||||
- Create a versioned sidebars file based from your current [sidebar](sidebar.md) configuration (if it exists) - saved as `versioned_sidebars/version-<version>-sidebars.json`.
|
||||
- Create a versioned sidebars file based from your current [sidebar](docs.md#sidebar) configuration (if it exists) - saved as `versioned_sidebars/version-<version>-sidebars.json`.
|
||||
- Append the new version number to `versions.json`.
|
||||
|
||||
## Files
|
||||
|
|
|
@ -61,7 +61,7 @@ npm run docusaurus docs:version 1.1.0
|
|||
When tagging a new version, the document versioning mechanism will:
|
||||
|
||||
- Copy the full `docs/` folder contents into a new `versioned_docs/version-<version>/` folder.
|
||||
- Create a versioned sidebars file based from your current [sidebar](sidebar.md) configuration (if it exists) - saved as `versioned_sidebars/version-<version>-sidebars.json`.
|
||||
- Create a versioned sidebars file based from your current [sidebar](docs.md#sidebar) configuration (if it exists) - saved as `versioned_sidebars/version-<version>-sidebars.json`.
|
||||
- Append the new version number to `versions.json`.
|
||||
|
||||
## Files
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue