feat(v2): add --config option to CLI (#4308)

* feat: add --config & --generated-files-dir option to CLI

* revert --generated-files-dir option + some refactors

Co-authored-by: slorber <lorber.sebastien@gmail.com>
This commit is contained in:
Long Ho 2021-03-02 11:34:23 -05:00 committed by GitHub
parent 9413ba920e
commit f46adffa17
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 225 additions and 169 deletions

View file

@ -131,19 +131,25 @@ export type HostPortCLIOptions = {
port?: string;
};
export type StartCLIOptions = HostPortCLIOptions & {
hotOnly: boolean;
open: boolean;
poll: boolean | number;
locale?: string;
export type ConfigOptions = {
config: string;
};
export type ServeCLIOptions = HostPortCLIOptions & {
build: boolean;
dir: string;
};
export type StartCLIOptions = HostPortCLIOptions &
ConfigOptions & {
hotOnly: boolean;
open: boolean;
poll: boolean | number;
locale?: string;
};
export type BuildOptions = {
export type ServeCLIOptions = HostPortCLIOptions &
ConfigOptions & {
dir: string;
build: boolean;
};
export type BuildOptions = ConfigOptions & {
bundleAnalyzer: boolean;
outDir: string;
minify: boolean;
@ -158,6 +164,7 @@ export interface LoadContext {
siteDir: string;
generatedFilesDir: string;
siteConfig: DocusaurusConfig;
siteConfigPath: string;
outDir: string;
baseUrl: string;
i18n: I18n;

View file

@ -109,6 +109,10 @@ cli
'--out-dir <dir>',
'The full path for the new output directory, relative to the current workspace (default: build).',
)
.option(
'--config <config>',
'Path to docusaurus config file, default to `[siteDir]/docusaurus.config.js`',
)
.option(
'-l, --locale <locale>',
'Build the site in a specified locale. Build all known locales otherwise.',
@ -117,10 +121,11 @@ cli
'--no-minify',
'Build website without minimizing JS bundles (default: false)',
)
.action((siteDir = '.', {bundleAnalyzer, outDir, locale, minify}) => {
.action((siteDir = '.', {bundleAnalyzer, config, outDir, locale, minify}) => {
wrapCommand(build)(path.resolve(siteDir), {
bundleAnalyzer,
outDir,
config,
locale,
minify,
});
@ -155,12 +160,20 @@ cli
'--out-dir <dir>',
'The full path for the new output directory, relative to the current workspace (default: build).',
)
.option(
'--config <config>',
'Path to docusaurus config file, default to `[siteDir]/docusaurus.config.js`',
)
.option(
'--skip-build',
'Skip building website before deploy it (default: false)',
)
.action((siteDir = '.', {outDir, skipBuild}) => {
wrapCommand(deploy)(path.resolve(siteDir), {outDir, skipBuild});
.action((siteDir = '.', {outDir, skipBuild, config}) => {
wrapCommand(deploy)(path.resolve(siteDir), {
outDir,
config,
skipBuild,
});
});
cli
@ -173,21 +186,28 @@ cli
'--hot-only',
'Do not fallback to page refresh if hot reload fails (default: false)',
)
.option(
'--config <config>',
'Path to docusaurus config file, default to `[siteDir]/docusaurus.config.js`',
)
.option('--no-open', 'Do not open page in the browser (default: false)')
.option(
'--poll [interval]',
'Use polling rather than watching for reload (default: false). Can specify a poll interval in milliseconds.',
)
.action((siteDir = '.', {port, host, locale, hotOnly, open, poll}) => {
wrapCommand(start)(path.resolve(siteDir), {
port,
host,
locale,
hotOnly,
open,
poll,
});
});
.action(
(siteDir = '.', {port, host, locale, config, hotOnly, open, poll}) => {
wrapCommand(start)(path.resolve(siteDir), {
port,
host,
locale,
config,
hotOnly,
open,
poll,
});
},
);
cli
.command('serve [siteDir]')
@ -196,6 +216,10 @@ cli
'--dir <dir>',
'The full path for the new output directory, relative to the current workspace (default: build).',
)
.option(
'--config <config>',
'Path to docusaurus config file, default to `[siteDir]/docusaurus.config.js`',
)
.option('-p, --port <port>', 'use specified port (default: 3000)')
.option('--build', 'Build website before serving (default: false)')
.option('-h, --host <host>', 'use specified host (default: localhost')
@ -207,12 +231,14 @@ cli
port = 3000,
host = 'localhost',
build: buildSite = false,
config,
},
) => {
wrapCommand(serve)(path.resolve(siteDir), {
dir,
port,
build: buildSite,
config,
host,
});
},
@ -236,6 +262,10 @@ cli
'--override',
'By default, we only append missing translation messages to existing translation files. This option allows to override existing translation messages. Make sure to commit or backup your existing translations, as they may be overridden.',
)
.option(
'--config <config>',
'Path to docusaurus config file, default to `[siteDir]/docusaurus.config.js`',
)
.option(
'--messagePrefix <messagePrefix>',
'Allows to init new written messages with a given prefix. This might help you to highlight untranslated message to make them stand out in the UI.',
@ -243,11 +273,12 @@ cli
.action(
(
siteDir = '.',
{locale = undefined, override = false, messagePrefix = ''},
{locale = undefined, override = false, messagePrefix = '', config},
) => {
wrapCommand(writeTranslations)(path.resolve(siteDir), {
locale,
override,
config,
messagePrefix,
});
},

View file

@ -14,7 +14,7 @@ import {Configuration, Plugin} from 'webpack';
import {BundleAnalyzerPlugin} from 'webpack-bundle-analyzer';
import merge from 'webpack-merge';
import {STATIC_DIR_NAME} from '../constants';
import {load} from '../server';
import {load, loadContext} from '../server';
import {handleBrokenLinks} from '../server/brokenLinks';
import {BuildCLIOptions, Props} from '@docusaurus/types';
@ -28,7 +28,6 @@ import {
import CleanWebpackPlugin from '../webpack/plugins/CleanWebpackPlugin';
import {loadI18n} from '../server/i18n';
import {mapAsyncSequencial} from '@docusaurus/utils';
import loadConfig from '../server/config';
export default async function build(
siteDir: string,
@ -59,8 +58,13 @@ export default async function build(
throw e;
}
}
const i18n = await loadI18n(loadConfig(siteDir), {
const context = await loadContext(siteDir, {
customOutDir: cliOptions.outDir,
customConfigFilePath: cliOptions.config,
locale: cliOptions.locale,
localizePath: cliOptions.locale ? false : undefined,
});
const i18n = await loadI18n(context.siteConfig, {
locale: cliOptions.locale,
});
if (cliOptions.locale) {
@ -112,6 +116,7 @@ async function buildLocale({
const props: Props = await load(siteDir, {
customOutDir: cliOptions.outDir,
customConfigFilePath: cliOptions.config,
locale,
localizePath: cliOptions.locale ? false : undefined,
});

View file

@ -7,7 +7,7 @@
import fs from 'fs-extra';
import path from 'path';
import chalk = require('chalk');
import {BUILD_DIR_NAME, GENERATED_FILES_DIR_NAME} from '../constants';
import {DEFAULT_BUILD_DIR_NAME, GENERATED_FILES_DIR_NAME} from '../constants';
function removePath(fsPath: string) {
return fs
@ -24,7 +24,7 @@ function removePath(fsPath: string) {
export default async function clear(siteDir: string): Promise<unknown> {
return Promise.all([
removePath(path.join(siteDir, GENERATED_FILES_DIR_NAME)),
removePath(path.join(siteDir, BUILD_DIR_NAME)),
removePath(path.join(siteDir, DEFAULT_BUILD_DIR_NAME)),
removePath(path.join(siteDir, 'node_modules/.cache/cache-loader')),
]);
}

View file

@ -6,14 +6,13 @@
*/
import fs from 'fs-extra';
import path from 'path';
import shell from 'shelljs';
import chalk from 'chalk';
import {CONFIG_FILE_NAME, GENERATED_FILES_DIR_NAME} from '../constants';
import {loadContext} from '../server';
import loadConfig from '../server/config';
import build from './build';
import {BuildCLIOptions} from '@docusaurus/types';
import path from 'path';
import os from 'os';
// GIT_PASS env variable should not appear in logs
function obfuscateGitPass(str) {
@ -42,10 +41,10 @@ export default async function deploy(
siteDir: string,
cliOptions: Partial<BuildCLIOptions> = {},
): Promise<void> {
const {outDir} = await loadContext(siteDir, {
const {outDir, siteConfig, siteConfigPath} = await loadContext(siteDir, {
customConfigFilePath: cliOptions.config,
customOutDir: cliOptions.outDir,
});
const tempDir = path.join(siteDir, GENERATED_FILES_DIR_NAME);
console.log('Deploy command invoked ...');
if (!shell.which('git')) {
@ -62,14 +61,13 @@ export default async function deploy(
process.env.CURRENT_BRANCH ||
shell.exec('git rev-parse --abbrev-ref HEAD').stdout.trim();
const siteConfig = loadConfig(siteDir);
const organizationName =
process.env.ORGANIZATION_NAME ||
process.env.CIRCLE_PROJECT_USERNAME ||
siteConfig.organizationName;
if (!organizationName) {
throw new Error(
`Missing project organization name. Did you forget to define 'organizationName' in ${CONFIG_FILE_NAME}? You may also export it via the ORGANIZATION_NAME environment variable.`,
`Missing project organization name. Did you forget to define 'organizationName' in ${siteConfigPath}? You may also export it via the ORGANIZATION_NAME environment variable.`,
);
}
console.log(`${chalk.cyan('organizationName:')} ${organizationName}`);
@ -80,7 +78,7 @@ export default async function deploy(
siteConfig.projectName;
if (!projectName) {
throw new Error(
`Missing project name. Did you forget to define 'projectName' in ${CONFIG_FILE_NAME}? You may also export it via the PROJECT_NAME environment variable.`,
`Missing project name. Did you forget to define 'projectName' in ${siteConfigPath}? You may also export it via the PROJECT_NAME environment variable.`,
);
}
console.log(`${chalk.cyan('projectName:')} ${projectName}`);
@ -141,22 +139,16 @@ export default async function deploy(
// out to deployment branch.
const currentCommit = shellExecLog('git rev-parse HEAD').stdout.trim();
const runDeploy = (outputDirectory) => {
if (shell.cd(tempDir).code !== 0) {
throw new Error(
`Temp dir ${GENERATED_FILES_DIR_NAME} does not exists. Run build website first.`,
);
const runDeploy = async (outputDirectory) => {
const fromPath = outputDirectory;
const toPath = await fs.mkdtemp(
path.join(os.tmpdir(), `${projectName}-${deploymentBranch}`),
);
if (shellExecLog(`git clone ${remoteBranch} ${toPath}`).code !== 0) {
throw new Error(`Error: git clone failed in ${toPath}`);
}
if (
shellExecLog(
`git clone ${remoteBranch} ${projectName}-${deploymentBranch}`,
).code !== 0
) {
throw new Error('Error: git clone failed');
}
shell.cd(`${projectName}-${deploymentBranch}`);
shell.cd(toPath);
// If the default branch is the one we're deploying to, then we'll fail
// to create it. This is the case of a cross-repo publish, where we clone
@ -183,63 +175,50 @@ export default async function deploy(
}
shellExecLog('git rm -rf .');
try {
await fs.copy(fromPath, toPath);
} catch (error) {
throw new Error(
`Error: Copying build assets from "${fromPath}" to "${toPath}" failed with error '${error}'`,
);
}
shell.cd(toPath);
shellExecLog('git add --all');
shell.cd('../..');
const fromPath = outputDirectory;
const toPath = path.join(
GENERATED_FILES_DIR_NAME,
`${projectName}-${deploymentBranch}`,
);
fs.copy(fromPath, toPath, (error) => {
if (error) {
throw new Error(
`Error: Copying build assets failed with error '${error}'`,
);
const commitMessage =
process.env.CUSTOM_COMMIT_MESSAGE ||
`Deploy website - based on ${currentCommit}`;
const commitResults = shellExecLog(`git commit -m "${commitMessage}"`);
if (
shellExecLog(`git push --force origin ${deploymentBranch}`).code !== 0
) {
throw new Error('Error: Git push failed');
} else if (commitResults.code === 0) {
// The commit might return a non-zero value when site is up to date.
let websiteURL = '';
if (githubHost === 'github.com') {
websiteURL = projectName.includes('.github.io')
? `https://${organizationName}.github.io/`
: `https://${organizationName}.github.io/${projectName}/`;
} else {
// GitHub enterprise hosting.
websiteURL = `https://${githubHost}/pages/${organizationName}/${projectName}/`;
}
shell.cd(toPath);
shellExecLog('git add --all');
const commitMessage =
process.env.CUSTOM_COMMIT_MESSAGE ||
`Deploy website - based on ${currentCommit}`;
const commitResults = shellExecLog(`git commit -m "${commitMessage}"`);
if (
shellExecLog(`git push --force origin ${deploymentBranch}`).code !== 0
) {
throw new Error('Error: Git push failed');
} else if (commitResults.code === 0) {
// The commit might return a non-zero value when site is up to date.
let websiteURL = '';
if (githubHost === 'github.com') {
websiteURL = projectName.includes('.github.io')
? `https://${organizationName}.github.io/`
: `https://${organizationName}.github.io/${projectName}/`;
} else {
// GitHub enterprise hosting.
websiteURL = `https://${githubHost}/pages/${organizationName}/${projectName}/`;
}
shell.echo(`Website is live at ${websiteURL}`);
shell.exit(0);
}
});
shell.echo(`Website is live at ${websiteURL}`);
shell.exit(0);
}
};
if (!cliOptions.skipBuild) {
// Clear Docusaurus 2 cache dir for deploy consistency.
fs.removeSync(tempDir);
// Build static html files, then push to deploymentBranch branch of specified repo.
build(siteDir, cliOptions, false)
.then(runDeploy)
.catch((buildError) => {
console.error(buildError);
process.exit(1);
});
try {
await runDeploy(await build(siteDir, cliOptions, false));
} catch (buildError) {
console.error(buildError);
process.exit(1);
}
} else {
// Push current build to deploymentBranch branch of specified repo.
runDeploy(outDir);
await runDeploy(outDir);
}
}

View file

@ -19,11 +19,14 @@ export default async function serve(
siteDir: string,
cliOptions: ServeCLIOptions,
): Promise<void> {
let dir = path.join(siteDir, cliOptions.dir);
let dir = path.isAbsolute(cliOptions.dir)
? cliOptions.dir
: path.join(siteDir, cliOptions.dir);
if (cliOptions.build) {
dir = await build(
siteDir,
{
config: cliOptions.config,
outDir: dir,
},
false,

View file

@ -22,7 +22,7 @@ import merge from 'webpack-merge';
import HotModuleReplacementPlugin from 'webpack/lib/HotModuleReplacementPlugin';
import {load} from '../server';
import {StartCLIOptions} from '@docusaurus/types';
import {CONFIG_FILE_NAME, STATIC_DIR_NAME} from '../constants';
import {STATIC_DIR_NAME} from '../constants';
import createClientConfig from '../webpack/client';
import {
applyConfigureWebpack,
@ -42,6 +42,7 @@ export default async function start(
function loadSite() {
return load(siteDir, {
customConfigFilePath: cliOptions.config,
locale: cliOptions.locale,
localizePath: undefined, // should this be configurable?
});
@ -97,7 +98,7 @@ export default async function start(
const pathsToWatch: string[] = [
...pluginPaths,
CONFIG_FILE_NAME,
props.siteConfigPath,
getTranslationsLocaleDirPath({
siteDir,
locale: props.i18n.currentLocale,

View file

@ -4,6 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {ConfigOptions} from '@docusaurus/types';
import {loadContext, loadPluginConfigs} from '../server';
import initPlugins, {InitPlugin} from '../server/plugins/init';
@ -47,9 +48,12 @@ async function writePluginTranslationFiles({
export default async function writeTranslations(
siteDir: string,
options: WriteTranslationsOptions & {locale?: string},
options: WriteTranslationsOptions & ConfigOptions & {locale?: string},
): Promise<void> {
const context = await loadContext(siteDir, {locale: options.locale});
const context = await loadContext(siteDir, {
customConfigFilePath: options.config,
locale: options.locale,
});
const pluginConfigs = loadPluginConfigs(context);
const plugins = initPlugins({
pluginConfigs,

View file

@ -5,10 +5,18 @@
* LICENSE file in the root directory of this source tree.
*/
export const BABEL_CONFIG_FILE_NAME = 'babel.config.js';
export const BUILD_DIR_NAME = 'build';
export const CONFIG_FILE_NAME = 'docusaurus.config.js';
export const GENERATED_FILES_DIR_NAME = '.docusaurus';
// 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)

View file

@ -6,8 +6,6 @@ exports[`loadConfig website with incomplete siteConfig 1`] = `
"
`;
exports[`loadConfig website with no siteConfig 1`] = `"docusaurus.config.js not found at packages/docusaurus/src/server/__tests__/__fixtures__/nonExisting/docusaurus.config.js"`;
exports[`loadConfig website with useless field (wrong field) in siteConfig 1`] = `
"\\"favicon\\" is required
These field(s) [\\"useLessField\\",] are not recognized in docusaurus.config.js.

View file

@ -10,31 +10,52 @@ import loadConfig from '../config';
describe('loadConfig', () => {
test('website with valid siteConfig', async () => {
const fixtures = path.join(__dirname, '__fixtures__');
const siteDir = path.join(fixtures, 'simple-site');
const siteDir = path.join(
__dirname,
'__fixtures__',
'simple-site',
'docusaurus.config.js',
);
const config = loadConfig(siteDir);
expect(config).toMatchSnapshot();
expect(config).not.toEqual({});
});
test('website with incomplete siteConfig', () => {
const siteDir = path.join(__dirname, '__fixtures__', 'bad-site');
const siteDir = path.join(
__dirname,
'__fixtures__',
'bad-site',
'docusaurus.config.js',
);
expect(() => {
loadConfig(siteDir);
}).toThrowErrorMatchingSnapshot();
});
test('website with useless field (wrong field) in siteConfig', () => {
const siteDir = path.join(__dirname, '__fixtures__', 'wrong-site');
const siteDir = path.join(
__dirname,
'__fixtures__',
'wrong-site',
'docusaurus.config.js',
);
expect(() => {
loadConfig(siteDir);
}).toThrowErrorMatchingSnapshot();
});
test('website with no siteConfig', () => {
const siteDir = path.join(__dirname, '__fixtures__', 'nonExisting');
const siteDir = path.join(
__dirname,
'__fixtures__',
'nonExisting',
'docusaurus.config.js',
);
expect(() => {
loadConfig(siteDir);
}).toThrowErrorMatchingSnapshot();
}).toThrowError(
/Config file "(.*?)__fixtures__[/\\]nonExisting[/\\]docusaurus.config.js" not found$/,
);
});
});

View file

@ -7,25 +7,12 @@
import fs from 'fs-extra';
import importFresh from 'import-fresh';
import path from 'path';
import {DocusaurusConfig} from '@docusaurus/types';
import {CONFIG_FILE_NAME} from '../constants';
import {validateConfig} from './configValidation';
import {toMessageRelativeFilePath} from '@docusaurus/utils';
export default function loadConfig(siteDir: string): DocusaurusConfig {
// TODO temporary undocumented env variable: we should be able to use a cli option instead!
const loadedConfigFileName =
process.env.DOCUSAURUS_CONFIG || CONFIG_FILE_NAME;
const configPath = path.resolve(siteDir, loadedConfigFileName);
export default function loadConfig(configPath: string): DocusaurusConfig {
if (!fs.existsSync(configPath)) {
throw new Error(
`${CONFIG_FILE_NAME} not found at ${toMessageRelativeFilePath(
configPath,
)}`,
);
throw new Error(`Config file "${configPath}" not found`);
}
const loadedConfig = importFresh(configPath) as Partial<DocusaurusConfig>;

View file

@ -6,7 +6,7 @@
*/
import {DocusaurusConfig, I18nConfig} from '@docusaurus/types';
import {CONFIG_FILE_NAME} from '../constants';
import {DEFAULT_CONFIG_FILE_NAME} from '../constants';
import Joi from 'joi';
import {
logValidationBugReportHint,
@ -164,7 +164,7 @@ export function validateConfig(
'',
);
formattedError = unknownFields
? `${formattedError}These field(s) [${unknownFields}] are not recognized in ${CONFIG_FILE_NAME}.\nIf you still want these fields to be in your configuration, put them in the 'customFields' attribute.\nSee https://v2.docusaurus.io/docs/docusaurus.config.js/#customfields`
? `${formattedError}These field(s) [${unknownFields}] are not recognized in ${DEFAULT_CONFIG_FILE_NAME}.\nIf you still want these fields to be in your configuration, put them in the 'customFields' attribute.\nSee https://v2.docusaurus.io/docs/docusaurus.config.js/#customfields`
: formattedError;
throw new Error(formattedError);
} else {

View file

@ -10,8 +10,8 @@ import path, {join} from 'path';
import chalk from 'chalk';
import ssrDefaultTemplate from '../client/templates/ssr.html.template';
import {
BUILD_DIR_NAME,
CONFIG_FILE_NAME,
DEFAULT_BUILD_DIR_NAME,
DEFAULT_CONFIG_FILE_NAME,
GENERATED_FILES_DIR_NAME,
THEME_PATH,
} from '../constants';
@ -40,6 +40,7 @@ import {mapValues} from 'lodash';
type LoadContextOptions = {
customOutDir?: string;
customConfigFilePath?: string;
locale?: string;
localizePath?: boolean; // undefined = only non-default locales paths are localized
};
@ -48,17 +49,23 @@ export async function loadContext(
siteDir: string,
options: LoadContextOptions = {},
): Promise<LoadContext> {
const {customOutDir, locale} = options;
const generatedFilesDir: string = path.resolve(
siteDir,
GENERATED_FILES_DIR_NAME,
);
const initialSiteConfig: DocusaurusConfig = loadConfig(siteDir);
const {customOutDir, locale, customConfigFilePath} = options;
const generatedFilesDir = path.isAbsolute(GENERATED_FILES_DIR_NAME)
? GENERATED_FILES_DIR_NAME
: path.resolve(siteDir, GENERATED_FILES_DIR_NAME);
const siteConfigPathUnresolved =
customConfigFilePath ?? DEFAULT_CONFIG_FILE_NAME;
const siteConfigPath = path.isAbsolute(siteConfigPathUnresolved)
? siteConfigPathUnresolved
: path.resolve(siteDir, siteConfigPathUnresolved);
const initialSiteConfig: DocusaurusConfig = loadConfig(siteConfigPath);
const {ssrTemplate} = initialSiteConfig;
const baseOutDir = customOutDir
? path.resolve(customOutDir)
: path.resolve(siteDir, BUILD_DIR_NAME);
: path.resolve(siteDir, DEFAULT_BUILD_DIR_NAME);
const i18n = await loadI18n(initialSiteConfig, {locale});
@ -93,6 +100,7 @@ export async function loadContext(
siteDir,
generatedFilesDir,
siteConfig,
siteConfigPath,
outDir,
baseUrl,
i18n,
@ -122,6 +130,7 @@ export async function load(
const {
generatedFilesDir,
siteConfig,
siteConfigPath,
outDir,
baseUrl,
i18n,
@ -149,7 +158,7 @@ export async function load(
// We want the generated config to have been normalized by the plugins!
const genSiteConfig = generate(
generatedFilesDir,
CONFIG_FILE_NAME,
DEFAULT_CONFIG_FILE_NAME,
`export default ${JSON.stringify(siteConfig, null, 2)};`,
);
@ -315,6 +324,7 @@ ${Object.keys(registry)
const props: Props = {
siteConfig,
siteConfigPath,
siteDir,
outDir,
baseUrl,

View file

@ -6,7 +6,6 @@
*/
import Module from 'module';
import {join} from 'path';
import importFresh from 'import-fresh';
import {
DocusaurusPluginVersionInformation,
@ -15,7 +14,7 @@ import {
PluginConfig,
PluginOptions,
} from '@docusaurus/types';
import {CONFIG_FILE_NAME, DEFAULT_PLUGIN_ID} from '../../constants';
import {DEFAULT_PLUGIN_ID} from '../../constants';
import {getPluginVersion} from '../versions';
import {ensureUniquePluginInstanceIds} from './pluginIds';
import {
@ -40,7 +39,7 @@ export default function initPlugins({
// We need to fallback to createRequireFromPath since createRequire is only available in node v12.
// See: https://nodejs.org/api/modules.html#modules_module_createrequire_filename
const createRequire = Module.createRequire || Module.createRequireFromPath;
const pluginRequire = createRequire(join(context.siteDir, CONFIG_FILE_NAME));
const pluginRequire = createRequire(context.siteConfigPath);
const plugins: InitPlugin[] = pluginConfigs
.map((pluginItem) => {

View file

@ -13,7 +13,7 @@ import {LoadContext} from '@docusaurus/types';
describe('loadPresets', () => {
test('no presets', () => {
const context = {
siteDir: __dirname,
siteConfigPath: __dirname,
siteConfig: {},
} as LoadContext;
const presets = loadPresets(context);
@ -27,7 +27,7 @@ describe('loadPresets', () => {
test('string form', () => {
const context = {
siteDir: __dirname,
siteConfigPath: __dirname,
siteConfig: {
presets: [path.join(__dirname, '__fixtures__/preset-bar.js')],
},
@ -52,7 +52,7 @@ describe('loadPresets', () => {
test('string form composite', () => {
const context = {
siteDir: __dirname,
siteConfigPath: __dirname,
siteConfig: {
presets: [
path.join(__dirname, '__fixtures__/preset-bar.js'),
@ -88,7 +88,7 @@ describe('loadPresets', () => {
test('array form', () => {
const context = {
siteDir: __dirname,
siteConfigPath: __dirname,
siteConfig: {
presets: [[path.join(__dirname, '__fixtures__/preset-bar.js')]],
},
@ -113,7 +113,7 @@ describe('loadPresets', () => {
test('array form with options', () => {
const context = {
siteDir: __dirname,
siteConfigPath: __dirname,
siteConfig: {
presets: [
[
@ -145,7 +145,7 @@ describe('loadPresets', () => {
test('array form composite', () => {
const context = {
siteDir: __dirname,
siteConfigPath: __dirname,
siteConfig: {
presets: [
[
@ -191,7 +191,7 @@ describe('loadPresets', () => {
test('mixed form', () => {
const context = {
siteDir: __dirname,
siteConfigPath: __dirname,
siteConfig: {
presets: [
[
@ -232,7 +232,7 @@ describe('loadPresets', () => {
test('mixed form with themes', () => {
const context = {
siteDir: __dirname,
siteConfigPath: __dirname,
siteConfig: {
presets: [
[

View file

@ -6,9 +6,7 @@
*/
import Module from 'module';
import {join} from 'path';
import importFresh from 'import-fresh';
import {CONFIG_FILE_NAME} from '../../constants';
import {
LoadContext,
PluginConfig,
@ -27,7 +25,7 @@ export default function loadPresets(
// We need to fallback to createRequireFromPath since createRequire is only available in node v12.
// See: https://nodejs.org/api/modules.html#modules_module_createrequire_filename
const createRequire = Module.createRequire || Module.createRequireFromPath;
const pluginRequire = createRequire(join(context.siteDir, CONFIG_FILE_NAME));
const pluginRequire = createRequire(context.siteConfigPath);
const presets: PresetConfig[] = (context.siteConfig || {}).presets || [];
const unflatPlugins: PluginConfig[][] = [];

View file

@ -30,7 +30,7 @@ import TOCInline from "@theme/TOCInline"
Below is a list of Docusaurus CLI commands and their usages:
### `docusaurus start`
### `docusaurus start [siteDir]`
Builds and serves a preview of your site locally with [Webpack Dev Server](https://webpack.js.org/configuration/dev-server).
@ -42,6 +42,7 @@ Builds and serves a preview of your site locally with [Webpack Dev Server](https
| `--host` | `localhost` | Specify a host to use. For example, if you want your server to be accessible externally, you can use `--host 0.0.0.0`. |
| `--hot-only` | `false` | Enables Hot Module Replacement without page refresh as fallback in case of build failures. More information [here](https://webpack.js.org/configuration/dev-server/#devserverhotonly). |
| `--no-open` | `false` | Do not open automatically the page in the browser. |
| `--config` | `undefined` | Path to docusaurus config file, default to `[siteDir]/docusaurus.config.js` |
| `--poll [optionalIntervalMs]` | `false` | Use polling of files rather than watching for live reload as a fallback in environments where watching doesn't work. More information [here](https://webpack.js.org/configuration/watch/#watchoptionspoll). |
:::important
@ -66,7 +67,7 @@ HTTPS=true SSL_CRT_FILE=localhost.pem SSL_KEY_FILE=localhost-key.pem yarn start
4. Open `https://localhost:3000/`
### `docusaurus build`
### `docusaurus build [siteDir]`
Compiles your site for production.
@ -76,6 +77,7 @@ Compiles your site for production.
| --- | --- | --- |
| `--bundle-analyzer` | `false` | Analyze your bundle with the [webpack bundle analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer). |
| `--out-dir` | `build` | The full path for the new output directory, relative to the current workspace. |
| `--config` | `undefined` | Path to docusaurus config file, default to `[siteDir]/docusaurus.config.js` |
| `--no-minify` | `false` | Build website without minimizing JS/CSS bundles. |
:::info
@ -84,7 +86,7 @@ For advanced minification of CSS bundle, we use the [advanced cssnano preset](ht
:::
### `docusaurus swizzle`
### `docusaurus swizzle [siteDir]`
:::caution
@ -133,7 +135,7 @@ TODO a separate section for swizzle tutorial.
To learn more about swizzling, check [here](#).
-->
### `docusaurus deploy`
### `docusaurus deploy [siteDir]`
Deploys your site with [GitHub Pages](https://pages.github.com/). Check out the docs on [deployment](deployment.mdx#deploying-to-github-pages) for more details.
@ -143,8 +145,9 @@ Deploys your site with [GitHub Pages](https://pages.github.com/). Check out the
| --- | --- | --- |
| `--out-dir` | `build` | The full path for the new output directory, relative to the current workspace. |
| `--skip-build` | `false` | Deploy website without building it. This may be useful when using custom deploy script. |
| `--config` | `undefined` | Path to docusaurus config file, default to `[siteDir]/docusaurus.config.js` |
### `docusaurus serve`
### `docusaurus serve [siteDir]`
Serve your built website locally.
@ -153,15 +156,16 @@ Serve your built website locally.
| `--port` | `3000` | Use specified port |
| `--dir` | `build` | The full path for the output directory, relative to the current workspace |
| `--build` | `false` | Build website before serving |
| `--config` | `undefined` | Path to docusaurus config file, default to `[siteDir]/docusaurus.config.js` |
| `--host` | `localhost` | Specify a host to use. For example, if you want your server to be accessible externally, you can use `--host 0.0.0.0`. |
### `docusaurus clear`
### `docusaurus clear [siteDir]`
Clear a Docusaurus site's generated assets, caches, build artifacts.
We recommend running this command before reporting bugs, after upgrading versions, or anytime you have issues with your Docusaurus site.
### `docusaurus write-translations`
### `docusaurus write-translations [siteDir]`
Write the JSON translation files that you will have to translate.
@ -171,4 +175,5 @@ By default, the files are written in `website/i18n/<defaultLocale>/...`.
| --- | --- | --- |
| `--locale` | `<defaultLocale>` | Define which locale folder you want to write translations the JSON files in |
| `--override` | `false` | Override existing translation messages |
| `--config` | `undefined` | Path to docusaurus config file, default to `[siteDir]/docusaurus.config.js` |
| `--messagePrefix` | `''` | Allows to add a prefix to each translation message, to help you highlight untranslated strings |

View file

@ -15,8 +15,8 @@
"build:baseUrl": "cross-env BASE_URL='/build/' yarn build",
"start:bootstrap": "cross-env DOCUSAURUS_PRESET=bootstrap yarn start",
"build:bootstrap": "cross-env DOCUSAURUS_PRESET=bootstrap yarn build",
"start:blogOnly": "cross-env DOCUSAURUS_CONFIG='docusaurus.config-blog-only.js' yarn start",
"build:blogOnly": "cross-env DOCUSAURUS_CONFIG='docusaurus.config-blog-only.js' yarn build",
"start:blogOnly": "cross-env yarn start --config=docusaurus.config-blog-only.js",
"build:blogOnly": "cross-env yarn build --config=docusaurus.config-blog-only.js",
"netlify:build:production": "yarn docusaurus write-translations && yarn netlify:crowdin:uploadSources && yarn netlify:crowdin:downloadTranslations && yarn build",
"netlify:build:deployPreview": "yarn docusaurus write-translations --locale fr --messagePrefix '(fr) ' && yarn netlify:build:deployPreview:v1:all && yarn netlify:build:deployPreview:classic && yarn netlify:build:deployPreview:bootstrap && yarn netlify:build:deployPreview:blogOnly",
"netlify:build:deployPreview:classic": "cross-env BASE_URL='/classic/' yarn build --out-dir netlifyDeployPreview/classic",