Files
payloadcms/webpack.config.mjs
Alessio Gravili 4e0d90d720 WIP
2024-03-09 18:20:32 -05:00

210 lines
6.2 KiB
JavaScript

/* eslint-disable @typescript-eslint/no-var-requires */
import OptimizeCSSAssetsPlugin from 'css-minimizer-webpack-plugin'
import MiniCSSExtractPlugin from 'mini-css-extract-plugin'
import path, { join, parse, resolve } from 'path'
import TerserJSPlugin from 'terser-webpack-plugin'
import { fileURLToPath } from 'url'
import webpack from 'webpack'
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
import { createRequire } from 'node:module'
const require = createRequire(import.meta.url)
import { existsSync } from 'fs'
const exportsFolderPath = path.resolve(dirname, './packages/ui/src/exports')
const exportsFolderPath2 = path.resolve(dirname, './packages/ui/src/assets')
const mockModulePath = path.resolve(dirname, './emptyModule.js')
/** @type {import('webpack').Configuration}*/
const componentWebpackConfig = {
entry: path.resolve(dirname, './packages/next/src/index.ts'),
externals: ['react', 'react-dom', /^payload.*/, /^next.*/, 'react-image-crop'],
//externalsType: 'commonjs',
mode: 'production',
module: {
rules: [
{
exclude: function(modulePath) {
// Check if the modulePath is within node_modules and does not end with .tsx or .ts
const isNodeModuleButNotTS = /node_modules/.test(modulePath)
// Check if the modulePath starts with ./packages/payload
const isPayloadPackage = /packages\/payload/.test(modulePath.replace(/\\/g, '/')); // Normalizing backslashes to forward slashes to handle Windows paths
// Exclude if either condition is true
return isNodeModuleButNotTS || isPayloadPackage
},
resolve: {
fullySpecified: false,
},
// exclude: /node_modules/,
test: /\.(t|j)sx?$/,
use: [
{
loader: '@swc-node/loader',
options: {
jsc: {
parser: {
syntax: 'typescript',
tsx: true,
},
target: 'esnext',
},
module: {
type: 'es6',
},
// absolute path for tsconfig.json
configFile: path.join(dirname, 'tsconfig.json'),
},
},
],
},
{
sideEffects: true,
test: /\.(scss|css)$/,
use: [
{
loader: MiniCSSExtractPlugin.loader,
options: {
esModule: true,
}
} ,
{
loader: require.resolve('css-loader'),
options: {
esModule: true,
//url: false
/* // TODO: Enable url resolving again
url: {
filter: (url, resourcePath) => !url.startsWith('/'),
},
*/
},
},
{
loader: require.resolve('postcss-loader'),
options: {
postcssOptions: {
plugins: [require.resolve('postcss-preset-env')],
},
},
},
{
loader: require.resolve('sass-loader'),
options: {
sassOptions: {
includePaths: [exportsFolderPath, exportsFolderPath2],
},
},
},
],
},
{
test: /\.(ttf|woff|woff2)$/,
type: 'asset/resource',
exclude: '/node_modules/',
generator: {
filename: 'fonts/[name].[ext]',
}
},
{
test: /\.(?:ico|gif|png|jpg|jpeg|eot|otf|svg)$/i,
type: 'asset/resource',
exclude: '/node_modules/',
},
{
exclude: function(modulePath) {
// Check if the modulePath starts with ./packages/payload
const isPayloadPackage = /packages\/payload/.test(modulePath.replace(/\\/g, '/')); // Normalizing backslashes to forward slashes to handle Windows paths
// Exclude if either condition is true
return !isPayloadPackage
},
test: /\.(t|j)sx?$/,
type: 'asset/resource',
},
],
},
optimization: {
minimizer: [
new TerserJSPlugin({
extractComments: false,
}),
new OptimizeCSSAssetsPlugin({}),
],
},
output: {
filename: 'index.js',
//libraryTarget: 'commonjs2',
path: path.resolve(dirname, './dist'),
publicPath: '/',
},
plugins: [
new MiniCSSExtractPlugin({
filename: 'styles.css',
ignoreOrder: true,
}),
// This fixes esm: https://github.com/vercel/next.js/issues/41961#issuecomment-1311091390
new webpack.NormalModuleReplacementPlugin(
/\.js$/,
(
/** @type {{ context: string, request: string }} */
resource,
) => {
// Skip a non relative import (e.g. a bare import specifier).
if (resource.request.startsWith('.')) {
const path = resolve(resource.context, resource.request)
if (
// Skip the relative import if it reaches into `node_modules`.
!path.includes('node_modules') &&
!existsSync(path)
) {
const { dir, name } = parse(path)
const extensionlessPath = join(dir, name)
for (const fallbackExtension of ['.tsx', '.ts', '.js']) {
if (existsSync(extensionlessPath + fallbackExtension)) {
resource.request = resource.request.replace(/\.js$/, fallbackExtension)
break
}
}
}
}
},
),
],
resolve: {
fullySpecified: false,
extensionAlias: {
'.cjs': ['.cjs', '.cts'],
'.js': ['.js', '.ts'], // TODO: instead of my webpack.NormalModuleReplacementPlugin I could also add .tsx and .jsx here
'.mjs': ['.mjs', '.mts'],
},
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
alias: {
payload$: mockModulePath,
},
fallback: {
crypto: false,
http: false,
https: false,
path: require.resolve('path-browserify'),
},
modules: ['node_modules', path.join(dirname, './node_modules')],
},
resolveLoader: {
modules: ['node_modules', path.join(dirname, './node_modules')],
},
stats: 'errors-only',
}
export default componentWebpackConfig