mirror of
https://github.com/facebook/docusaurus.git
synced 2025-07-23 03:29:11 +02:00
feat(v2): implement client modules API (#1554)
* feat(v2): load client modules * docs(v2): update plugins API * misc(v2): change to import
This commit is contained in:
parent
90138d52c2
commit
c06ccc0a07
9 changed files with 174 additions and 3 deletions
|
@ -8,12 +8,15 @@
|
|||
import React from 'react';
|
||||
import {renderRoutes} from 'react-router-config';
|
||||
|
||||
import Head from '@docusaurus/Head';
|
||||
import routes from '@generated/routes';
|
||||
import siteConfig from '@generated/docusaurus.config';
|
||||
|
||||
import Head from '@docusaurus/Head';
|
||||
import DocusaurusContext from '@docusaurus/context';
|
||||
import PendingNavigation from './PendingNavigation';
|
||||
|
||||
import '@generated/client-modules';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<DocusaurusContext.Provider value={{siteConfig}}>
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
module.exports = function() {
|
||||
return {
|
||||
name: 'plugin-empty',
|
||||
};
|
||||
};
|
|
@ -0,0 +1,8 @@
|
|||
module.exports = function() {
|
||||
return {
|
||||
name: 'plugin-foo-bar',
|
||||
getClientModules() {
|
||||
return ['foo', 'bar'];
|
||||
},
|
||||
};
|
||||
};
|
|
@ -0,0 +1,8 @@
|
|||
module.exports = function() {
|
||||
return {
|
||||
plugin: 'plugin-hello-world',
|
||||
getClientModules() {
|
||||
return ['hello', 'world'];
|
||||
},
|
||||
};
|
||||
};
|
|
@ -0,0 +1,94 @@
|
|||
/**
|
||||
* Copyright (c) 2017-present, Facebook, Inc.
|
||||
*
|
||||
* 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 {loadClientModules} from '../index';
|
||||
import {LoadContext} from '../../index';
|
||||
|
||||
const pluginEmpty = require('./__fixtures__/plugin-empty');
|
||||
const pluginFooBar = require('./__fixtures__/plugin-foo-bar');
|
||||
const pluginHelloWorld = require('./__fixtures__/plugin-hello-world');
|
||||
|
||||
describe('loadClientModules', () => {
|
||||
test('empty', () => {
|
||||
const clientModules = loadClientModules([pluginEmpty()]);
|
||||
expect(clientModules).toMatchInlineSnapshot(`Array []`);
|
||||
});
|
||||
|
||||
test('non-empty', () => {
|
||||
const clientModules = loadClientModules([pluginFooBar()]);
|
||||
expect(clientModules).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"foo",
|
||||
"bar",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('multiple non-empty', () => {
|
||||
const clientModules = loadClientModules([
|
||||
pluginFooBar(),
|
||||
pluginHelloWorld(),
|
||||
]);
|
||||
expect(clientModules).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"foo",
|
||||
"bar",
|
||||
"hello",
|
||||
"world",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('multiple non-empty different order', () => {
|
||||
const clientModules = loadClientModules([
|
||||
pluginHelloWorld(),
|
||||
pluginFooBar(),
|
||||
]);
|
||||
expect(clientModules).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"hello",
|
||||
"world",
|
||||
"foo",
|
||||
"bar",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('empty and non-empty', () => {
|
||||
const clientModules = loadClientModules([
|
||||
pluginHelloWorld(),
|
||||
pluginEmpty(),
|
||||
pluginFooBar(),
|
||||
]);
|
||||
expect(clientModules).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"hello",
|
||||
"world",
|
||||
"foo",
|
||||
"bar",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('empty and non-empty different order', () => {
|
||||
const clientModules = loadClientModules([
|
||||
pluginHelloWorld(),
|
||||
pluginFooBar(),
|
||||
pluginEmpty(),
|
||||
]);
|
||||
expect(clientModules).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"hello",
|
||||
"world",
|
||||
"foo",
|
||||
"bar",
|
||||
]
|
||||
`);
|
||||
});
|
||||
});
|
24
packages/docusaurus/src/server/client-modules/index.ts
Normal file
24
packages/docusaurus/src/server/client-modules/index.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* Copyright (c) 2017-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {Plugin} from '../plugins';
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
export function loadClientModules(plugins: Plugin<any>[]): string[] {
|
||||
return _.compact(
|
||||
_.flatten<string | null>(
|
||||
plugins.map(plugin => {
|
||||
if (!plugin.getClientModules) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return plugin.getClientModules();
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
|
@ -17,6 +17,8 @@ import {loadThemeAlias} from './themes';
|
|||
import {loadPlugins} from './plugins';
|
||||
import {loadRoutes} from './routes';
|
||||
import {loadPresets} from './presets';
|
||||
import {loadClientModules} from './client-modules';
|
||||
|
||||
import {GENERATED_FILES_DIR_NAME, CONFIG_FILE_NAME} from '../constants';
|
||||
|
||||
export interface CLIOptions {
|
||||
|
@ -96,6 +98,16 @@ export async function load(
|
|||
}),
|
||||
});
|
||||
|
||||
// Load client modules.
|
||||
const clientModules = loadClientModules(plugins);
|
||||
const genClientModules = generate(
|
||||
generatedFilesDir,
|
||||
'client-modules.js',
|
||||
`export default [\n${clientModules
|
||||
.map(module => ` require(${JSON.stringify(module)}),`)
|
||||
.join('\n')}\n];\n`,
|
||||
);
|
||||
|
||||
// Routing
|
||||
const {
|
||||
registry,
|
||||
|
@ -128,6 +140,7 @@ ${Object.keys(registry)
|
|||
const genRoutes = generate(generatedFilesDir, 'routes.js', routesConfig);
|
||||
|
||||
await Promise.all([
|
||||
genClientModules,
|
||||
genSiteConfig,
|
||||
genRegistry,
|
||||
genRoutesChunkNames,
|
||||
|
|
|
@ -26,6 +26,7 @@ export interface Plugin<T> {
|
|||
configureWebpack?(config: Configuration, isServer: boolean): Configuration;
|
||||
getThemePath?(): string;
|
||||
getPathsToWatch?(): string[];
|
||||
getClientModules?(): string[];
|
||||
}
|
||||
|
||||
export interface PluginConfig {
|
||||
|
|
|
@ -66,8 +66,12 @@ module.exports = function(context, opts) {
|
|||
const options = {...DEFAULT_OPTIONS, ...options};
|
||||
|
||||
return {
|
||||
// Namespace used for directories to cache the intermediate data for each plugin.
|
||||
name: 'docusaurus-cool-plugin',
|
||||
// A compulsory field used as the namespace for directories to cache
|
||||
// the intermediate data for each plugin.
|
||||
// If you're writing your own local plugin, you will want it to
|
||||
// be unique in order not to potentially conflict with imported plugins.
|
||||
// A good way will be to add your own project name within.
|
||||
name: 'docusaurus-my-project-cool-plugin',
|
||||
|
||||
async loadContent() {
|
||||
// The loadContent hook is executed after siteConfig and env has been loaded
|
||||
|
@ -107,6 +111,17 @@ module.exports = function(context, opts) {
|
|||
getPathsToWatch() {
|
||||
// Path to watch
|
||||
},
|
||||
|
||||
getThemePath() {
|
||||
// Returns the path to the directory where the theme components can
|
||||
// be found.
|
||||
},
|
||||
|
||||
getClientModules() {
|
||||
// Return an array of paths to the modules that are to be imported
|
||||
// in the client bundle. These modules are imported globally before
|
||||
// React even renders the initial UI.
|
||||
},
|
||||
};
|
||||
};
|
||||
```
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue