mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-29 10:17:55 +02:00
feat(v2): Allow customization of js loader, replace babel by esbuild in Docusaurus website (#4766)
* feat(v2): Allow customization of js loader
* Change API
* use esbuild for Docusaurus website
* Enable isolatedModules: true
* Revert "Enable isolatedModules: true"
This reverts commit e656c350
Co-authored-by: slorber <lorber.sebastien@gmail.com>
This commit is contained in:
parent
c8812cf3b5
commit
3548686f59
12 changed files with 113 additions and 11 deletions
|
@ -3,6 +3,7 @@
|
|||
"compilerOptions": {
|
||||
"incremental": true,
|
||||
"tsBuildInfoFile": "./lib/.tsbuildinfo",
|
||||
"module": "esnext",
|
||||
"rootDir": "src",
|
||||
"outDir": "lib"
|
||||
}
|
||||
|
|
3
packages/docusaurus-types/src/index.d.ts
vendored
3
packages/docusaurus-types/src/index.d.ts
vendored
|
@ -63,6 +63,9 @@ export interface DocusaurusConfig {
|
|||
}
|
||||
)[];
|
||||
titleDelimiter?: string;
|
||||
webpack?: {
|
||||
jsLoader: 'babel' | ((isServer: boolean) => RuleSetRule);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -187,12 +187,14 @@ async function buildLocale({
|
|||
configureWebpack.bind(plugin), // The plugin lifecycle may reference `this`.
|
||||
clientConfig,
|
||||
false,
|
||||
props.siteConfig.webpack?.jsLoader,
|
||||
);
|
||||
|
||||
serverConfig = applyConfigureWebpack(
|
||||
configureWebpack.bind(plugin), // The plugin lifecycle may reference `this`.
|
||||
serverConfig,
|
||||
true,
|
||||
props.siteConfig.webpack?.jsLoader,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -153,6 +153,7 @@ export default async function start(
|
|||
configureWebpack.bind(plugin), // The plugin lifecycle may reference `this`.
|
||||
config,
|
||||
false,
|
||||
props.siteConfig.webpack?.jsLoader,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -134,6 +134,11 @@ const ConfigSchema = Joi.object({
|
|||
tagline: Joi.string().allow(''),
|
||||
titleDelimiter: Joi.string().default('|'),
|
||||
noIndex: Joi.bool().default(false),
|
||||
webpack: Joi.object({
|
||||
jsLoader: Joi.alternatives()
|
||||
.try(Joi.string().equal('babel'), Joi.function())
|
||||
.optional(),
|
||||
}).optional(),
|
||||
});
|
||||
|
||||
// TODO move to @docusaurus/utils-validation
|
||||
|
|
|
@ -81,6 +81,7 @@ describe('base webpack config', () => {
|
|||
const props = {
|
||||
outDir: '',
|
||||
siteDir: '',
|
||||
siteConfig: {},
|
||||
baseUrl: '',
|
||||
generatedFilesDir: '',
|
||||
routesPaths: '',
|
||||
|
|
|
@ -5,10 +5,11 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {validate, Configuration} from 'webpack';
|
||||
import {validate, Configuration, RuleSetRule} from 'webpack';
|
||||
import path from 'path';
|
||||
|
||||
import {
|
||||
getCustomizableJSLoader,
|
||||
applyConfigureWebpack,
|
||||
applyConfigurePostCss,
|
||||
getFileLoaderUtils,
|
||||
|
@ -18,6 +19,40 @@ import {
|
|||
ConfigureWebpackFnMergeStrategy,
|
||||
} from '@docusaurus/types';
|
||||
|
||||
describe('customize JS loader', () => {
|
||||
test('getCustomizableJSLoader defaults to babel loader', () => {
|
||||
expect(getCustomizableJSLoader()({isServer: true}).loader).toBe(
|
||||
require.resolve('babel-loader'),
|
||||
);
|
||||
expect(getCustomizableJSLoader()({isServer: false}).loader).toBe(
|
||||
require.resolve('babel-loader'),
|
||||
);
|
||||
});
|
||||
|
||||
test('getCustomizableJSLoader accepts loaders with preset', () => {
|
||||
expect(getCustomizableJSLoader('babel')({isServer: true}).loader).toBe(
|
||||
require.resolve('babel-loader'),
|
||||
);
|
||||
expect(getCustomizableJSLoader('babel')({isServer: false}).loader).toBe(
|
||||
require.resolve('babel-loader'),
|
||||
);
|
||||
});
|
||||
|
||||
test('getCustomizableJSLoader allows customization', () => {
|
||||
const customJSLoader = (isServer: boolean): RuleSetRule => ({
|
||||
loader: 'my-fast-js-loader',
|
||||
options: String(isServer),
|
||||
});
|
||||
|
||||
expect(getCustomizableJSLoader(customJSLoader)({isServer: true})).toEqual(
|
||||
customJSLoader(true),
|
||||
);
|
||||
expect(getCustomizableJSLoader(customJSLoader)({isServer: false})).toEqual(
|
||||
customJSLoader(false),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('extending generated webpack config', () => {
|
||||
test('direct mutation on generated webpack config object', async () => {
|
||||
// fake generated webpack config
|
||||
|
|
|
@ -11,7 +11,7 @@ import path from 'path';
|
|||
import {Configuration} from 'webpack';
|
||||
import {Props} from '@docusaurus/types';
|
||||
import {
|
||||
getJSLoader,
|
||||
getCustomizableJSLoader,
|
||||
getStyleLoaders,
|
||||
getFileLoaderUtils,
|
||||
getCustomBabelConfigFilePath,
|
||||
|
@ -73,6 +73,7 @@ export function createBaseConfig(
|
|||
const {
|
||||
outDir,
|
||||
siteDir,
|
||||
siteConfig,
|
||||
baseUrl,
|
||||
generatedFilesDir,
|
||||
routesPaths,
|
||||
|
@ -205,7 +206,7 @@ export function createBaseConfig(
|
|||
test: /\.(j|t)sx?$/,
|
||||
exclude: excludeJS,
|
||||
use: [
|
||||
getJSLoader({
|
||||
getCustomizableJSLoader(siteConfig.webpack?.jsLoader)({
|
||||
isServer,
|
||||
babelOptions: getCustomBabelConfigFilePath(siteDir),
|
||||
}),
|
||||
|
|
|
@ -137,7 +137,7 @@ export function getBabelOptions({
|
|||
|
||||
// Name is generic on purpose
|
||||
// we want to support multiple js loader implementations (babel + esbuild)
|
||||
export function getJSLoader({
|
||||
function getDefaultBabelLoader({
|
||||
isServer,
|
||||
babelOptions,
|
||||
}: {
|
||||
|
@ -150,6 +150,19 @@ export function getJSLoader({
|
|||
};
|
||||
}
|
||||
|
||||
export const getCustomizableJSLoader = (
|
||||
jsLoader: 'babel' | ((isServer: boolean) => RuleSetRule) = 'babel',
|
||||
) => ({
|
||||
isServer,
|
||||
babelOptions,
|
||||
}: {
|
||||
isServer: boolean;
|
||||
babelOptions?: TransformOptions | string;
|
||||
}): RuleSetRule =>
|
||||
jsLoader === 'babel'
|
||||
? getDefaultBabelLoader({isServer, babelOptions})
|
||||
: jsLoader(isServer);
|
||||
|
||||
// TODO remove this before end of 2021?
|
||||
const warnBabelLoaderOnce = memoize(function () {
|
||||
console.warn(
|
||||
|
@ -163,7 +176,7 @@ const getBabelLoaderDeprecated = function getBabelLoaderDeprecated(
|
|||
babelOptions?: TransformOptions | string,
|
||||
) {
|
||||
warnBabelLoaderOnce();
|
||||
return getJSLoader({isServer, babelOptions});
|
||||
return getDefaultBabelLoader({isServer, babelOptions});
|
||||
};
|
||||
|
||||
// TODO remove this before end of 2021 ?
|
||||
|
@ -184,17 +197,19 @@ function getCacheLoaderDeprecated() {
|
|||
* @param configureWebpack a webpack config or a function to modify config
|
||||
* @param config initial webpack config
|
||||
* @param isServer indicates if this is a server webpack configuration
|
||||
* @param jsLoader custom js loader config
|
||||
* @returns final/ modified webpack config
|
||||
*/
|
||||
export function applyConfigureWebpack(
|
||||
configureWebpack: ConfigureWebpackFn,
|
||||
config: Configuration,
|
||||
isServer: boolean,
|
||||
jsLoader?: 'babel' | ((isServer: boolean) => RuleSetRule),
|
||||
): Configuration {
|
||||
// Export some utility functions
|
||||
const utils: ConfigureWebpackUtils = {
|
||||
getStyleLoaders,
|
||||
getJSLoader,
|
||||
getJSLoader: getCustomizableJSLoader(jsLoader),
|
||||
getBabelLoader: getBabelLoaderDeprecated,
|
||||
getCacheLoader: getCacheLoaderDeprecated,
|
||||
};
|
||||
|
|
|
@ -63,6 +63,16 @@ const isVersioningDisabled = !!process.env.DISABLE_VERSIONING || isI18nStaging;
|
|||
: // Production locales
|
||||
['en', 'fr', 'ko', 'zh-CN'],
|
||||
},
|
||||
webpack: {
|
||||
jsLoader: (isServer) => ({
|
||||
loader: require.resolve('esbuild-loader'),
|
||||
options: {
|
||||
loader: 'tsx',
|
||||
format: isServer ? 'cjs' : undefined,
|
||||
target: isServer ? 'node12' : 'es2017',
|
||||
},
|
||||
}),
|
||||
},
|
||||
onBrokenLinks: 'throw',
|
||||
onBrokenMarkdownLinks: 'warn',
|
||||
favicon: 'img/docusaurus.ico',
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
"@docusaurus/theme-live-codeblock": "2.0.0-beta.0",
|
||||
"clsx": "^1.1.1",
|
||||
"color": "^3.1.3",
|
||||
"esbuild-loader": "2.13.0",
|
||||
"netlify-plugin-cache": "^1.0.3",
|
||||
"npm-to-yarn": "^1.0.0-2",
|
||||
"react": "^17.0.1",
|
||||
|
|
37
yarn.lock
37
yarn.lock
|
@ -8060,6 +8060,23 @@ es6-promisify@^5.0.0:
|
|||
dependencies:
|
||||
es6-promise "^4.0.3"
|
||||
|
||||
esbuild-loader@2.13.0:
|
||||
version "2.13.0"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-loader/-/esbuild-loader-2.13.0.tgz#f5a3602a89a3b728506ae3e1887304fffeef9270"
|
||||
integrity sha512-gC9lML8RGkTSWG2pJVEOZRLMoIluq1Jd7OzzVkOZKMzbMDMWDhXEwXLs60n+aglnAYa9GVrD/UXjTHkM51nBsg==
|
||||
dependencies:
|
||||
esbuild "^0.11.19"
|
||||
joycon "^3.0.1"
|
||||
json5 "^2.2.0"
|
||||
loader-utils "^2.0.0"
|
||||
type-fest "^1.0.1"
|
||||
webpack-sources "^2.2.0"
|
||||
|
||||
esbuild@^0.11.19:
|
||||
version "0.11.20"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.11.20.tgz#7cefa1aee8b372c184e42457885f7ce5d3e62a1e"
|
||||
integrity sha512-QOZrVpN/Yz74xfat0H6euSgn3RnwLevY1mJTEXneukz1ln9qB+ieaerRMzSeETpz/UJWsBMzRVR/andBht5WKw==
|
||||
|
||||
escalade@^3.0.2, escalade@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||
|
@ -11823,6 +11840,11 @@ joi@^17.3.0, joi@^17.4.0:
|
|||
"@sideway/formula" "^3.0.0"
|
||||
"@sideway/pinpoint" "^2.0.0"
|
||||
|
||||
joycon@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.0.1.tgz#9074c9b08ccf37a6726ff74a18485f85efcaddaf"
|
||||
integrity sha512-SJcJNBg32dGgxhPtM0wQqxqV0ax9k/9TaUskGDSJkSFSQOEWWvQ3zzWdGQRIUry2j1zA5+ReH13t0Mf3StuVZA==
|
||||
|
||||
jpeg-js@^0.3.4:
|
||||
version "0.3.6"
|
||||
resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.3.6.tgz#c40382aac9506e7d1f2d856eb02f6c7b2a98b37c"
|
||||
|
@ -11981,10 +12003,10 @@ json5@^1.0.1:
|
|||
dependencies:
|
||||
minimist "^1.2.0"
|
||||
|
||||
json5@^2.1.2:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43"
|
||||
integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==
|
||||
json5@^2.1.2, json5@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3"
|
||||
integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==
|
||||
dependencies:
|
||||
minimist "^1.2.5"
|
||||
|
||||
|
@ -19210,6 +19232,11 @@ type-fest@^0.8.0, type-fest@^0.8.1:
|
|||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
|
||||
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
|
||||
|
||||
type-fest@^1.0.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.1.1.tgz#210251e7f57357a1457269e6b34837fed067ac2c"
|
||||
integrity sha512-RPDKc5KrIyKTP7Fk75LruUagqG6b+OTgXlCR2Z0aQDJFeIvL4/mhahSEtHmmVzXu4gmA0srkF/8FCH3WOWxTWA==
|
||||
|
||||
type-is@~1.6.17, type-is@~1.6.18:
|
||||
version "1.6.18"
|
||||
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
|
||||
|
@ -19996,7 +20023,7 @@ webpack-sources@^1.1.0, webpack-sources@^1.4.3:
|
|||
source-list-map "^2.0.0"
|
||||
source-map "~0.6.1"
|
||||
|
||||
webpack-sources@^2.1.1:
|
||||
webpack-sources@^2.1.1, webpack-sources@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.2.0.tgz#058926f39e3d443193b6c31547229806ffd02bac"
|
||||
integrity sha512-bQsA24JLwcnWGArOKUxYKhX3Mz/nK1Xf6hxullKERyktjNMC4x8koOeaDNTA2fEJ09BdWLbM/iTW0ithREUP0w==
|
||||
|
|
Loading…
Add table
Reference in a new issue