mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-10 07:37:19 +02:00
feat: allow user to modify generated webpack config
This commit is contained in:
parent
2b5ee3e869
commit
10b1a38762
9 changed files with 172 additions and 3 deletions
|
@ -6,6 +6,7 @@ const globby = require('globby');
|
||||||
const load = require('../load');
|
const load = require('../load');
|
||||||
const createServerConfig = require('../webpack/server');
|
const createServerConfig = require('../webpack/server');
|
||||||
const createClientConfig = require('../webpack/client');
|
const createClientConfig = require('../webpack/client');
|
||||||
|
const {applyConfigureWebpack} = require('../webpack/utils');
|
||||||
|
|
||||||
function compile(config) {
|
function compile(config) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
@ -36,8 +37,15 @@ module.exports = async function build(siteDir, cliOptions = {}) {
|
||||||
|
|
||||||
const props = await load(siteDir);
|
const props = await load(siteDir);
|
||||||
|
|
||||||
const serverConfig = createServerConfig(props).toConfig();
|
let serverConfig = createServerConfig(props).toConfig();
|
||||||
const clientConfig = createClientConfig(props).toConfig();
|
let clientConfig = createClientConfig(props).toConfig();
|
||||||
|
|
||||||
|
// apply user webpack config
|
||||||
|
const {
|
||||||
|
siteConfig: {configureWebpack}
|
||||||
|
} = props;
|
||||||
|
clientConfig = applyConfigureWebpack(configureWebpack, clientConfig, false);
|
||||||
|
serverConfig = applyConfigureWebpack(configureWebpack, serverConfig, true);
|
||||||
|
|
||||||
// Build the client bundles first.
|
// Build the client bundles first.
|
||||||
// We cannot run them in parallel because the server need to pickup the correct client bundle name
|
// We cannot run them in parallel because the server need to pickup the correct client bundle name
|
||||||
|
|
|
@ -13,6 +13,7 @@ const serve = require('webpack-serve');
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
const load = require('../load');
|
const load = require('../load');
|
||||||
const createClientConfig = require('../webpack/client');
|
const createClientConfig = require('../webpack/client');
|
||||||
|
const {applyConfigureWebpack} = require('../webpack/utils');
|
||||||
|
|
||||||
function getHost(reqHost) {
|
function getHost(reqHost) {
|
||||||
return reqHost || 'localhost';
|
return reqHost || 'localhost';
|
||||||
|
@ -72,6 +73,13 @@ module.exports = async function start(siteDir, cliOptions = {}) {
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
config = config.toConfig();
|
config = config.toConfig();
|
||||||
|
|
||||||
|
// apply user webpack config
|
||||||
|
const {
|
||||||
|
siteConfig: {configureWebpack}
|
||||||
|
} = props;
|
||||||
|
config = applyConfigureWebpack(configureWebpack, config, false);
|
||||||
|
|
||||||
const compiler = webpack(config);
|
const compiler = webpack(config);
|
||||||
|
|
||||||
// webpack-serve
|
// webpack-serve
|
||||||
|
|
|
@ -21,7 +21,9 @@ module.exports = function loadConfig(siteDir, deleteCache = true) {
|
||||||
const optionalFields = [
|
const optionalFields = [
|
||||||
'customDocsPath',
|
'customDocsPath',
|
||||||
'highlight',
|
'highlight',
|
||||||
'markdownPlugins'
|
'markdownPlugins',
|
||||||
|
'configureWebpack',
|
||||||
|
'chainWebpack'
|
||||||
];
|
];
|
||||||
const missingFields = requiredFields.filter(field => !config[field]);
|
const missingFields = requiredFields.filter(field => !config[field]);
|
||||||
if (missingFields && missingFields.length > 0) {
|
if (missingFields && missingFields.length > 0) {
|
||||||
|
|
|
@ -3,6 +3,7 @@ const webpackNiceLog = require('webpack-nicelog');
|
||||||
const {StatsWriterPlugin} = require('webpack-stats-plugin');
|
const {StatsWriterPlugin} = require('webpack-stats-plugin');
|
||||||
const cleanWebpackPlugin = require('clean-webpack-plugin');
|
const cleanWebpackPlugin = require('clean-webpack-plugin');
|
||||||
const createBaseConfig = require('./base');
|
const createBaseConfig = require('./base');
|
||||||
|
const {applyChainWebpack} = require('./utils');
|
||||||
|
|
||||||
module.exports = function createClientConfig(props) {
|
module.exports = function createClientConfig(props) {
|
||||||
const config = createBaseConfig(props);
|
const config = createBaseConfig(props);
|
||||||
|
@ -21,5 +22,9 @@ module.exports = function createClientConfig(props) {
|
||||||
|
|
||||||
// show compilation progress bar and build time
|
// show compilation progress bar and build time
|
||||||
config.plugin('niceLog').use(webpackNiceLog, [{name: 'Client'}]);
|
config.plugin('niceLog').use(webpackNiceLog, [{name: 'Client'}]);
|
||||||
|
|
||||||
|
// user extended webpack-chain config
|
||||||
|
applyChainWebpack(props.siteConfig.chainWebpack, config, false);
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,6 +2,7 @@ const path = require('path');
|
||||||
const staticSiteGenerator = require('static-site-generator-webpack-plugin');
|
const staticSiteGenerator = require('static-site-generator-webpack-plugin');
|
||||||
const webpackNiceLog = require('webpack-nicelog');
|
const webpackNiceLog = require('webpack-nicelog');
|
||||||
const createBaseConfig = require('./base');
|
const createBaseConfig = require('./base');
|
||||||
|
const {applyChainWebpack} = require('./utils');
|
||||||
|
|
||||||
module.exports = function createServerConfig(props) {
|
module.exports = function createServerConfig(props) {
|
||||||
const config = createBaseConfig(props, true);
|
const config = createBaseConfig(props, true);
|
||||||
|
@ -32,5 +33,8 @@ module.exports = function createServerConfig(props) {
|
||||||
.plugin('niceLog')
|
.plugin('niceLog')
|
||||||
.use(webpackNiceLog, [{name: 'Server', color: 'yellow'}]);
|
.use(webpackNiceLog, [{name: 'Server', color: 'yellow'}]);
|
||||||
|
|
||||||
|
// user extended webpack-chain config
|
||||||
|
applyChainWebpack(props.siteConfig.chainWebpack, config, true);
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
};
|
};
|
||||||
|
|
28
lib/webpack/utils.js
Normal file
28
lib/webpack/utils.js
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
const merge = require('webpack-merge');
|
||||||
|
|
||||||
|
// Modify the generated webpack config with normal webpack config
|
||||||
|
function applyConfigureWebpack(userConfig, config, isServer) {
|
||||||
|
if (typeof userConfig === 'object') {
|
||||||
|
return merge(config, userConfig);
|
||||||
|
}
|
||||||
|
if (typeof userConfig === 'function') {
|
||||||
|
const res = userConfig(config, isServer);
|
||||||
|
if (res && typeof res === 'object') {
|
||||||
|
return merge(config, res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modify the generated webpack config with webpack-chain API
|
||||||
|
function applyChainWebpack(userChainWebpack, config, isServer) {
|
||||||
|
if (userChainWebpack) {
|
||||||
|
userChainWebpack(config, isServer);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
applyConfigureWebpack,
|
||||||
|
applyChainWebpack
|
||||||
|
};
|
|
@ -81,6 +81,7 @@
|
||||||
"style-loader": "^0.22.1",
|
"style-loader": "^0.22.1",
|
||||||
"webpack": "^4.16.3",
|
"webpack": "^4.16.3",
|
||||||
"webpack-chain": "^4.8.0",
|
"webpack-chain": "^4.8.0",
|
||||||
|
"webpack-merge": "^4.1.4",
|
||||||
"webpack-nicelog": "^2.2.1",
|
"webpack-nicelog": "^2.2.1",
|
||||||
"webpack-serve": "^2.0.2",
|
"webpack-serve": "^2.0.2",
|
||||||
"webpack-stats-plugin": "^0.2.1"
|
"webpack-stats-plugin": "^0.2.1"
|
||||||
|
|
107
test/webpack/utils.test.js
Normal file
107
test/webpack/utils.test.js
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
import {validate} from 'webpack';
|
||||||
|
import path from 'path';
|
||||||
|
import Config from 'webpack-chain';
|
||||||
|
|
||||||
|
import {applyConfigureWebpack, applyChainWebpack} from '@lib/webpack/utils';
|
||||||
|
|
||||||
|
describe('extending generated webpack config', () => {
|
||||||
|
test('direct mutation on generated webpack config object', async () => {
|
||||||
|
// fake generated webpack config
|
||||||
|
let config = {
|
||||||
|
output: {
|
||||||
|
path: __dirname,
|
||||||
|
filename: 'bundle.js'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* eslint-disable */
|
||||||
|
const configureWebpack = (generatedConfig, isServer) => {
|
||||||
|
if (!isServer) {
|
||||||
|
generatedConfig.entry = 'entry.js';
|
||||||
|
generatedConfig.output = {
|
||||||
|
path: path.join(__dirname, 'dist'),
|
||||||
|
filename: 'new.bundle.js'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/* eslint-enable */
|
||||||
|
|
||||||
|
config = applyConfigureWebpack(configureWebpack, config, false);
|
||||||
|
expect(config).toEqual({
|
||||||
|
entry: 'entry.js',
|
||||||
|
output: {
|
||||||
|
path: path.join(__dirname, 'dist'),
|
||||||
|
filename: 'new.bundle.js'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const errors = validate(config);
|
||||||
|
|
||||||
|
console.log(errors);
|
||||||
|
expect(errors.length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('webpack-merge with user webpack config object', async () => {
|
||||||
|
// fake generated webpack config
|
||||||
|
let config = {
|
||||||
|
output: {
|
||||||
|
path: __dirname,
|
||||||
|
filename: 'bundle.js'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* eslint-disable */
|
||||||
|
const configureWebpack = {
|
||||||
|
entry: 'entry.js',
|
||||||
|
output: {
|
||||||
|
path: path.join(__dirname, 'dist'),
|
||||||
|
filename: 'new.bundle.js'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/* eslint-enable */
|
||||||
|
|
||||||
|
config = applyConfigureWebpack(configureWebpack, config, false);
|
||||||
|
expect(config).toEqual({
|
||||||
|
entry: 'entry.js',
|
||||||
|
output: {
|
||||||
|
path: path.join(__dirname, 'dist'),
|
||||||
|
filename: 'new.bundle.js'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const errors = validate(config);
|
||||||
|
expect(errors.length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('use webpack-chain API', async () => {
|
||||||
|
// fake generated webpack config in webpack-chain format
|
||||||
|
let config = new Config();
|
||||||
|
config.output.path(__dirname).filename('bundle.js');
|
||||||
|
|
||||||
|
// user chainWebpack
|
||||||
|
/* eslint-disable */
|
||||||
|
const chainWebpack = (oldConfig, isServer) => {
|
||||||
|
if (!isServer) {
|
||||||
|
oldConfig.entry('main').add('./entry.js');
|
||||||
|
oldConfig.output
|
||||||
|
.path(path.join(__dirname, 'dist'))
|
||||||
|
.filename('new.bundle.js');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/* eslint-enable */
|
||||||
|
|
||||||
|
applyChainWebpack(chainWebpack, config, false);
|
||||||
|
|
||||||
|
// transform to webpack configuration object format
|
||||||
|
config = config.toConfig();
|
||||||
|
expect(config).toEqual({
|
||||||
|
output: {
|
||||||
|
path: path.join(__dirname, 'dist'),
|
||||||
|
filename: 'new.bundle.js'
|
||||||
|
},
|
||||||
|
entry: {
|
||||||
|
main: ['./entry.js']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const errors = validate(config);
|
||||||
|
expect(errors.length).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
|
@ -6975,6 +6975,12 @@ webpack-log@^1.0.1, webpack-log@^1.1.1, webpack-log@^1.1.2, webpack-log@^1.2.0:
|
||||||
loglevelnext "^1.0.1"
|
loglevelnext "^1.0.1"
|
||||||
uuid "^3.1.0"
|
uuid "^3.1.0"
|
||||||
|
|
||||||
|
webpack-merge@^4.1.4:
|
||||||
|
version "4.1.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.1.4.tgz#0fde38eabf2d5fd85251c24a5a8c48f8a3f4eb7b"
|
||||||
|
dependencies:
|
||||||
|
lodash "^4.17.5"
|
||||||
|
|
||||||
webpack-nicelog@^2.2.1:
|
webpack-nicelog@^2.2.1:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/webpack-nicelog/-/webpack-nicelog-2.2.1.tgz#e3458003ce0d98966e930657176fb4eb6f536b85"
|
resolved "https://registry.yarnpkg.com/webpack-nicelog/-/webpack-nicelog-2.2.1.tgz#e3458003ce0d98966e930657176fb4eb6f536b85"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue