Merge pull request #5803 from strapi/core/custom-webpack

Allow custom webpack config
This commit is contained in:
Alexandre BODIN 2020-04-15 16:33:06 +02:00 committed by GitHub
commit 1be24385a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 89 additions and 45 deletions

View File

@ -220,7 +220,11 @@ module.exports = {
{ {
collapsable: true, collapsable: true,
title: '⚙️️ Admin Panel', title: '⚙️️ Admin Panel',
children: ['/3.0.0-beta.x/admin-panel/customization', '/3.0.0-beta.x/admin-panel/deploy'], children: [
'/3.0.0-beta.x/admin-panel/customization',
'/3.0.0-beta.x/admin-panel/custom-webpack-config',
'/3.0.0-beta.x/admin-panel/deploy',
],
}, },
{ {
collapsable: true, collapsable: true,

View File

@ -0,0 +1,16 @@
# Custom Webpack Config
In order to extend the usage of webpack, you can define a function that extends its config inside `admin/admin.config.js`, like so:
```js
module.exports = {
webpack: (config, webpack) => {
// Note: we provide webpack above so you should not `require` it
// Perform customizations to webpack config
// Important: return the modified config
config.plugins.push(new webpack.IgnorePlugin(/\/__tests__\//));
return config;
},
};
```

View File

@ -1,5 +1,6 @@
/* eslint-disable no-useless-escape */ /* eslint-disable no-useless-escape */
const path = require('path'); const path = require('path');
const _ = require('lodash');
const fs = require('fs-extra'); const fs = require('fs-extra');
const webpack = require('webpack'); const webpack = require('webpack');
const getWebpackConfig = require('./webpack.config.js'); const getWebpackConfig = require('./webpack.config.js');
@ -9,6 +10,71 @@ const chokidar = require('chokidar');
const getPkgPath = name => path.dirname(require.resolve(`${name}/package.json`)); const getPkgPath = name => path.dirname(require.resolve(`${name}/package.json`));
function getCustomWebpackConfig(dir, config) {
const adminConfigPath = path.join(dir, 'admin', 'admin.config.js');
let webpackConfig = getWebpackConfig(config);
if (fs.existsSync(adminConfigPath)) {
const adminConfig = require(path.resolve(adminConfigPath));
if (_.isFunction(adminConfig.webpack)) {
webpackConfig = adminConfig.webpack(webpackConfig, webpack);
if (!webpackConfig) {
console.error(
`${chalk.red('Error:')} Nothing was returned from your custom webpack configuration`
);
process.exit(1);
}
}
}
return webpackConfig;
}
async function build({ dir, env, options, optimize }) {
// Create the cache dir containing the front-end files.
await createCacheDir(dir);
const cacheDir = path.resolve(dir, '.cache');
const entry = path.resolve(cacheDir, 'admin', 'src', 'app.js');
const dest = path.resolve(dir, 'build');
const config = getCustomWebpackConfig(dir, { entry, dest, env, options, optimize });
const compiler = webpack(config);
return new Promise((resolve, reject) => {
compiler.run((err, stats) => {
let messages;
if (err) {
if (!err.message) {
return reject(err);
}
messages = {
errors: [err.message],
warnings: [],
};
} else {
messages = stats.toJson({ all: false, warnings: true, errors: true });
}
if (messages.errors.length) {
// Only keep the first error. Others are often indicative
// of the same problem, but confuse the reader with noise.
if (messages.errors.length > 1) {
messages.errors.length = 1;
}
return reject(new Error(messages.errors.join('\n\n')));
}
return resolve({
stats,
warnings: messages.warnings,
});
});
});
}
async function createPluginsJs(plugins, localPlugins, dest) { async function createPluginsJs(plugins, localPlugins, dest) {
const content = ` const content = `
const injectReducer = require('./utils/injectReducer').default; const injectReducer = require('./utils/injectReducer').default;
@ -153,49 +219,6 @@ async function createCacheDir(dir) {
); );
} }
async function build({ dir, env, options, optimize }) {
// Create the cache dir containing the front-end files.
await createCacheDir(dir);
const cacheDir = path.resolve(dir, '.cache');
const entry = path.resolve(cacheDir, 'admin', 'src', 'app.js');
const dest = path.resolve(dir, 'build');
const config = getWebpackConfig({ entry, dest, env, options, optimize });
const compiler = webpack(config);
return new Promise((resolve, reject) => {
compiler.run((err, stats) => {
let messages;
if (err) {
if (!err.message) {
return reject(err);
}
messages = {
errors: [err.message],
warnings: [],
};
} else {
messages = stats.toJson({ all: false, warnings: true, errors: true });
}
if (messages.errors.length) {
// Only keep the first error. Others are often indicative
// of the same problem, but confuse the reader with noise.
if (messages.errors.length > 1) {
messages.errors.length = 1;
}
return reject(new Error(messages.errors.join('\n\n')));
}
return resolve({
stats,
warnings: messages.warnings,
});
});
});
}
async function watchAdmin({ dir, host, port, options }) { async function watchAdmin({ dir, host, port, options }) {
// Create the cache dir containing the front-end files. // Create the cache dir containing the front-end files.
await createCacheDir(dir); await createCacheDir(dir);
@ -223,7 +246,8 @@ async function watchAdmin({ dir, host, port, options }) {
}, },
}; };
const server = new WebpackDevServer(webpack(getWebpackConfig(args)), opts); const webpackConfig = getCustomWebpackConfig(dir, args);
const server = new WebpackDevServer(webpack(webpackConfig), opts);
server.listen(port, host, function(err) { server.listen(port, host, function(err) {
if (err) { if (err) {