strapi/packages/core/admin/webpack.config.js

175 lines
4.9 KiB
JavaScript
Raw Normal View History

'use strict';
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ForkTsCheckerPlugin = require('fork-ts-checker-webpack-plugin');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { ESBuildMinifyPlugin } = require('esbuild-loader');
2019-05-13 16:01:16 +02:00
const WebpackBar = require('webpackbar');
const browserslist = require('browserslist');
2023-01-06 11:54:09 +00:00
const browserslistToEsbuild = require('browserslist-to-esbuild');
const alias = require('./webpack.alias');
const getClientEnvironment = require('./env');
const { createPluginsExcludePath } = require('./utils/plugins');
2019-04-29 19:04:23 +02:00
module.exports = ({
dest,
entry,
2019-04-29 19:04:23 +02:00
env,
optimize,
plugins,
2019-04-29 19:04:23 +02:00
options = {
backend: 'http://localhost:1337',
adminPath: '/admin/',
features: [],
2019-04-29 19:04:23 +02:00
},
tsConfigFilePath,
enforceSourceMaps,
2019-04-29 19:04:23 +02:00
}) => {
2019-04-29 15:48:16 +02:00
const isProduction = env === 'production';
const envVariables = getClientEnvironment({ ...options, env });
2019-04-29 15:48:16 +02:00
const webpackPlugins = isProduction
2019-04-25 12:34:55 +02:00
? [
new MiniCssExtractPlugin({
2019-04-29 15:48:16 +02:00
filename: '[name].[chunkhash].css',
chunkFilename: '[name].[chunkhash].chunkhash.css',
2019-10-08 16:32:07 +02:00
ignoreOrder: true,
2019-04-25 12:34:55 +02:00
}),
new WebpackBar(),
2019-04-29 15:48:16 +02:00
]
: [];
const nodeModulePluginPaths = Object.values(plugins)
.filter((plugin) => plugin.info?.packageName || plugin.info?.required)
.map((plugin) => plugin.pathToPlugin);
const excludeRegex = createPluginsExcludePath(nodeModulePluginPaths);
// Ensure we use the config in this directory, even if run with a different
// working directory
const browserslistConfig = browserslist.loadConfig({ path: __dirname });
const buildTarget = browserslistToEsbuild(browserslistConfig);
2023-01-11 09:42:26 +00:00
2019-04-29 15:48:16 +02:00
return {
mode: isProduction ? 'production' : 'development',
2022-08-08 15:50:34 +02:00
bail: !!isProduction,
devtool: isProduction && !enforceSourceMaps ? false : 'source-map',
experiments: {
topLevelAwait: true,
},
2022-08-11 10:40:09 +02:00
entry: [entry],
2019-04-29 15:48:16 +02:00
output: {
path: dest,
publicPath: options.adminPath,
2019-04-29 15:48:16 +02:00
// Utilize long-term caching by adding content hashes (not compilation hashes)
// to compiled assets for production
filename: isProduction ? '[name].[contenthash:8].js' : '[name].bundle.js',
chunkFilename: isProduction ? '[name].[contenthash:8].chunk.js' : '[name].chunk.js',
},
2019-04-29 15:48:16 +02:00
optimization: {
minimize: optimize,
2019-04-29 15:48:16 +02:00
minimizer: [
new ESBuildMinifyPlugin({
2023-01-11 09:42:26 +00:00
target: buildTarget,
css: true, // Apply minification to CSS assets
2019-04-29 15:48:16 +02:00
}),
],
2022-07-19 11:09:30 +02:00
moduleIds: 'deterministic',
2019-04-29 15:48:16 +02:00
runtimeChunk: true,
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
loader: require.resolve('esbuild-loader'),
exclude: excludeRegex,
options: {
loader: 'tsx',
2023-01-11 09:42:26 +00:00
target: buildTarget,
jsx: 'automatic',
},
},
2019-04-29 15:48:16 +02:00
{
test: /\.(js|jsx|mjs)$/,
exclude: excludeRegex,
2019-04-29 15:48:16 +02:00
use: {
loader: require.resolve('esbuild-loader'),
options: {
loader: 'jsx',
2023-01-11 09:42:26 +00:00
target: buildTarget,
},
},
2019-04-29 15:48:16 +02:00
},
/**
* This is used to avoid webpack import errors where
* the origin is strict EcmaScript Module.
*
* e. g. a module with javascript mimetype, a '.mjs' file,
* or a '.js' file where the package.json contains '"type": "module"'
*/
2022-11-17 17:27:13 +00:00
{
test: /\.m?jsx?$/,
resolve: {
fullySpecified: false,
},
},
2019-04-29 15:48:16 +02:00
{
test: /\.css$/i,
2019-10-10 06:24:19 +02:00
use: ['style-loader', 'css-loader'],
2019-04-29 15:48:16 +02:00
},
{
test: /\.(svg|eot|otf|ttf|woff|woff2)$/,
type: 'asset/resource',
2019-04-29 15:48:16 +02:00
},
{
2019-12-11 11:46:08 +01:00
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/, /\.ico$/],
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 1000,
},
2019-12-11 11:46:08 +01:00
},
2019-04-29 15:48:16 +02:00
},
{
test: /\.html$/,
include: [path.join(__dirname, 'src')],
use: require.resolve('html-loader'),
},
{
test: /\.(mp4|webm)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10000,
},
},
},
2019-04-29 15:48:16 +02:00
],
},
resolve: {
alias,
extensions: ['.js', '.jsx', '.react.js', '.ts', '.tsx'],
2019-04-29 15:48:16 +02:00
},
plugins: [
new HtmlWebpackPlugin({
inject: true,
template: path.resolve(__dirname, 'index.html'),
}),
new webpack.DefinePlugin(envVariables),
new ForkTsCheckerPlugin({
typescript: {
configFile: tsConfigFilePath,
},
}),
!isProduction && process.env.REACT_REFRESH !== 'false' && new ReactRefreshWebpackPlugin(),
2019-04-29 15:48:16 +02:00
...webpackPlugins,
].filter(Boolean),
2019-04-29 15:48:16 +02:00
};
};