Rspack Config for use with Sequelize

Evidently rspack can have trouble with Sequelize. I’ve been working for hours with the JetBrains AI agent and it finally found an rspack config that was able to load Sequelize.

const { defineConfig } = require('@meteorjs/rspack');
const rspack = require('@rspack/core');
const path = require('path');

/**
 * Rspack configuration for Meteor projects.
 */
module.exports = defineConfig(Meteor => {
    const config = {
        module: {
            rules: [
                // Handle .node files as external resources (don't parse as JS)
                {
                    test: /\.node$/,
                    type: 'asset/resource',
                },
                // CRITICAL: Block sequelize and database packages on CLIENT only
                ...(Meteor.isClient ? [
                    {
                        test: /node_modules[\\/](sequelize|pg|pg-hstore|pg-native|mysql2|mariadb|sqlite3|tedious|oracledb|ibm_db)/,
                        use: 'null-loader',
                    },
                    {
                        test: /[\\/]server[\\/]/,
                        use: 'null-loader',
                    },
                ] : []),
            ],
        },
        resolve: {
            // Exclude optional native addons that should not be bundled
            alias: {
                kerberos: false,
                'kerberos/build/Release/kerberos.node': false,
                // CRITICAL: Prevent Sequelize and database packages from being resolved ON CLIENT ONLY
                ...(Meteor.isClient ? {
                    'sequelize': false,
                    'sequelize/lib/sequelize': false,
                    'sequelize/lib/dialects/postgres/hstore': false,
                    'pg': false,
                    'pg-hstore': false,
                    'pg-native': false,
                    'mysql2': false,
                    'mariadb': false,
                    'sqlite3': false,
                    'tedious': false,
                    'oracledb': false,
                    'ibm_db': false,
                } : {}),
            },
            // Provide polyfills for Node.js built-in modules when building for browser
            fallback: Meteor.isClient ? {
                buffer: require.resolve('buffer/'),
                stream: false,
                util: false,
                assert: false,
                process: false,
                fs: false,
                path: false,
                crypto: false,
                net: false,
                tls: false,
                dns: false,
            } : {},
        },
        // Externalize database packages
        externals: [
            ...(Meteor.isClient ? [
                // On CLIENT: block database packages completely
                function({ context, request, contextInfo }, callback) {
                    const dbPackages = [
                        'pg',
                        'pg-hstore',
                        'pg-native',
                        'sequelize',
                        'mysql2',
                        'mariadb',
                        'sqlite3',
                        'tedious',
                        'oracledb',
                        'ibm_db',
                    ];

                    for (const pkg of dbPackages) {
                        if (request === pkg || request.startsWith(pkg + '/')) {
                            return callback(null, 'var {}');
                        }
                    }

                    // On client builds, externalize server directory imports
                    if (context) {
                        const normalizedContext = context.replace(/\\/g, '/');
                        if (normalizedContext.includes('/imports/startup/server/') ||
                            normalizedContext.includes('/server/')) {
                            return callback(null, 'var {}');
                        }
                    }

                    callback();
                }
            ] : [
                // On SERVER: externalize database packages so they load from node_modules at runtime
                function({ context, request, contextInfo }, callback) {
                    const dbPackages = [
                        'pg',
                        'pg-hstore',
                        'pg-native',
                        'pg-pool',
                        'sequelize',
                        'mysql2',
                        'mariadb',
                        'sqlite3',
                        'tedious',
                        'oracledb',
                        'ibm_db',
                    ];

                    for (const pkg of dbPackages) {
                        if (request === pkg || request.startsWith(pkg + '/')) {
                            return callback(null, 'commonjs ' + request);
                        }
                    }

                    callback();
                }
            ]),
        ],
        externalsType: 'commonjs',
        plugins: [
            // Provide global Buffer variable for browser (client only)
            ...(Meteor.isClient ? [
                new rspack.ProvidePlugin({
                    Buffer: ['buffer', 'Buffer'],
                    process: 'process/browser',
                }),
            ] : []),
            // Ignore optional MongoDB dependencies
            new rspack.IgnorePlugin({
                resourceRegExp: /^(kerberos|@mongodb-js\/zstd|@aws-sdk\/credential-providers|snappy|socks|gcp-metadata|mongodb-client-encryption|bson-ext)$/,
            }),
            // CRITICAL: Ignore database packages at the module level ON CLIENT ONLY
            ...(Meteor.isClient ? [
                new rspack.IgnorePlugin({
                    resourceRegExp: /^(sequelize|pg|pg-hstore|pg-native|mysql2|mariadb|sqlite3|tedious|oracledb|ibm_db)$/,
                }),
                new rspack.IgnorePlugin({
                    resourceRegExp: /.*/,
                    contextRegExp: /[\\/]imports[\\/]startup[\\/]server[\\/]/,
                }),
                new rspack.IgnorePlugin({
                    resourceRegExp: /.*/,
                    contextRegExp: /[\\/]server[\\/]/,
                }),
                new rspack.NormalModuleReplacementPlugin(
                    /[\\/]imports[\\/]startup[\\/]server[\\/]/,
                    function(resource) {
                        resource.request = 'data:text/javascript,export default {}';
                    }
                ),
            ] : []),
        ],
        ignoreWarnings: [
            // Suppress warnings
            {
                module: /.*/,
                message: /Can't resolve 'pg-hstore'/,
            },
            {
                module: /.*/,
                message: /Can't resolve 'sequelize'/,
            },
            {
                module: /node_modules\/mongodb/,
                message: /Can't resolve/,
            },
            {
                module: /node_modules\/mongoose/,
                message: /Can't resolve/,
            },
            {
                module: /node_modules\/sequelize/,
                message: /.*/,
            },
            {
                module: /node_modules\/sax/,
                message: /Can't resolve 'stream'/,
            },
            {
                module: /imports\/startup\/server/,
                message: /.*/,
            },
            {
                module: /server\//,
                message: /.*/,
            },
        ],
    };

    return config;
});


By any chance, could you share the repository where you use that Sequelize configuration or a minimal public repository?

It feels a bit unusual that you need all those settings, but maybe such tweaks and ignored imports are necessary when sharing code between the client and server, and using that library. I’d like to see your minimal setup to confirm.

Hmmm… for Sequelize to launch on dev, it needs a local sql database to connect to. I don’t know how to get a local sql db into a repo. Probably with sqlLite. But that’s going to be some hours of dev time and I’m super-busy working on getting rspack integrated in other ways, into my app. (It’s cut my client bundle size in half!)

Would a screen share at a time of your convenience be helpful?

a screen share would indeed be the most efficient way to troubleshoot the necessary Sequelize/database exclusions without requiring a full, replicable repository setup.

You can share a minimal Meteor-Sequelize example, either using SQLite3 (add it as an npm dependency) or parameterize it so the user installs their own database and just updates driver credentials (I can do). There are official examples, like sequelize/express-example, which use SQLite for easy setup. Preparing this repo isn’t as quick as prompting an AI, but it’s doable.

Also, remember that a minimal repository should focus on the setup and issue you face, not the project’s specific domain. Since the issue is related to the Rspack setup, I only need the minimal project structure, database (or setup instructions) and library usage, not other project details.

When I ask for minimal reproductions, especially for new setups, it’s not only to fix your issue. I need an example I can automate or run locally to ensure that, despite future Meteor Rspack changes, the project still behaves as expected. This is the most efficient way to support your setup and others, and to keep it stable and extended over time. This has been critical and fully adopted in the modern test suite to ensure there are no regressions across different projects and their specific requirements. Working with a reproduction also makes it easier to solve not only the first issue you found. If new issues appear, they can be added to the same repository and easily checked by me for further fixes.

Screensharing doesn’t give me that. It also takes more time to analyze large parts of your project in real time, and I lose the chance to review it on my own as I can with a minimal replication. Given my time capacity across Meteor OSS, Rspack betas, and other setups and reproductions, I can’t prioritize this now if there is no a replication. I can revisit it later. :pray: I may try it myself following the sequelize/express-example when I have more time after other tasks.

2 Likes

Per your request, I have created a tiny test app.

In my app I was getting errors regarding the postgres dialectModule: pg not being found.

In the tiny test app, I’m not seeing errors yet, but I’m getting these serious warnings regarding the same thing.

[Rspack Server] [server-rspack]:
  WARNING in ./node_modules/pg-protocol/esm/index.js
    ⚠ ESModulesLinkingWarning: export 'SASL' (imported as 'protocol') was not found in '../dist/index.js' (possible exports: DatabaseError, __esModule, parse, serialize)
     ╭─[6:20]
   4 β”‚ // Re-export all the properties
   5 β”‚ export const DatabaseError = protocol.DatabaseError
   6 β”‚ export const SASL = protocol.SASL
     Β·                     ─────────────
   7 β”‚ export const serialize = protocol.serialize
   8 β”‚ export const parse = protocol.parse
     ╰────
  

  WARNING in ./node_modules/sequelize/lib/dialects/abstract/connection-manager.js 44:15-63
    ⚠ Critical dependency: the request of a dependency is an expression
      ╭─[44:23]
   42 β”‚     try {
   43 β”‚       if (this.sequelize.config.dialectModulePath) {
   44 β”‚         return require(this.sequelize.config.dialectModulePath);
      Β·                        ────────────────────────────────────────
   45 β”‚       }
   46 β”‚       if (this.sequelize.config.dialectModule) {
      ╰────
  

  WARNING in ./node_modules/sequelize/lib/dialects/abstract/connection-manager.js 49:13-32
    ⚠ Critical dependency: the request of a dependency is an expression
      ╭─[49:21]
   47 β”‚         return this.sequelize.config.dialectModule;
   48 β”‚       }
   49 β”‚       return require(moduleName);
      Β·                      ───────────
   50 β”‚     } catch (err) {
   51 β”‚       if (err.code === "MODULE_NOT_FOUND") {
      ╰────

If I explicitly reference pg here:

const db = new Sequelize(Meteor.settings.postgres[useLocalDevDB ? 'development' : 'production'].dbname,
    Meteor.settings.postgres[useLocalDevDB ? 'development' : 'production'].dbuser,
    Meteor.settings.postgres[useLocalDevDB ? 'development' : 'production'].dbpsd,
    {
        host: Meteor.settings.postgres[useLocalDevDB ? 'development' : 'production'].host,
        port: Meteor.settings.postgres[useLocalDevDB ? 'development' : 'production'].port,
        dialect: 'postgres',
        dialectModule: pg, // Explicitly provide the pg module

…I still get the same warnings.

1 Like