Errors when building with meteor V3.4.1 using Rspack

I have just upgraded a project to meteor V3.4.1 and now I am using meteor build to create a deployment bundle.
Building succeeded fine right after upgrading.
Also when I added "meteor: {"modern": true} to package.json building with SWC went fine.
However, when I tried to use rspack, the build process failed with lots of WARNINGS like this:

  WARNING in ./node_modules/node-aead-crypto/lib.js 32:37-75                                                                                                           
    ⚠ Module not found: Can't resolve './node-aead-crypto.android-arm64.node' in '/Users/willem/meteor/ctrlh/node_modules/node-aead-crypto'
      ╭─[32:28]
   30 │         try {
   31 │           if (localFileExisted) {
   32 │             nativeBinding = require('./node-aead-crypto.android-arm64.node')
      ·                             ────────────────────────────────────────────────
   33 │           } else {
   34 │             nativeBinding = require('node-aead-crypto-android-arm64')
      ╰────

and finally some ERRORS:

 ERROR in ./node_modules/node-aead-crypto-darwin-arm64/node-aead-crypto.darwin-arm64.node
    × Module parse failed:
    ╰─▶   × JavaScript parse error: Unexpected character '�'
           ╭────
         0 │ ����
��._stubs__TEXT�.��x__TEXT@@__text__TEXTPx
           · ▲
           ╰────
        
    help: 
          You may need an appropriate loader to handle this file type.
  

  ERROR in ./node_modules/node-aead-crypto-darwin-universal/node-aead-crypto.darwin-universal.node
    × Module parse failed:
    ╰─▶   × JavaScript parse error: Unexpected character '�'
           ╭─[1:0]
         1 │ ����@�X
                    @�p����x__TEXT��__text__TEXT@8`e@8�__stubs__TEXT�����__stub_helper__TEXT��:���__const__TEXTТ�3Т__gcc_except_tab__TEXTl���l�__unwind_info__TEXT�g��g__eh_frame__TEXT�@�h__DATA�@�@
           · ▲
         2 │ __nl_symbol_ptr__DATA�Q__got__DAT�R__la_symbol_ptr__DATA���T__mod_init_func__DATA�� ��   __const__DATA���__data__DATAȡ ȡ__thread_vars__DATA���__thread_dat�/Users/runner/work/node-aead-crypto/node-aead-crypto/target/release/deps/libnode_aead_crypto.dylib"�0�00�8h��`�(X�U@�
                                                                                                                      PS����VL�F0���t�+���$
           ╰────
        
    help: 
          You may need an appropriate loader to handle this file type.
  

  [server-rspack] compiled with 2 errors and 26 warnings in 584 ms
Rspack Build failed in Server with exit code 1                                  
Rspack plugin error: Rspack Build failed in Server with exit code 1             
packages/core-runtime.js:189                  
            throw error;
            ^

Error: Rspack Build failed in Server with exit code 1
    at Object.onExit (packages/rspack/lib/processes.js:627:25)
    at ChildProcess.<anonymous> (packages/tools-core/lib/process.js:52:33)
    at ChildProcess.emit (node:events:519:28)
    at maybeClose (node:internal/child_process:1101:16)
    at Process.ChildProcess._handle.onexit (node:internal/child_process:304:5)
    at Process.callbackTrampoline (node:internal/async_hooks:130:17)

Node.js v22.22.1
1 Like

The issue is that node-aead-crypto is a native addon, Rspack is trying to follow its dynamic require() calls and parse the compiled .node binaries as JavaScript, which is where the parse errors come from. Native binaries shouldn’t go through the bundler at all; they need to stay external and let Node load them at runtime.

Meteor has a helper for exactly this: Meteor.compileWithMeteor, which marks deps as externals so Rspack skips them. Meteor.compileWithMeteor is a handy wrapper of the Rspack’s externals.

Add this to your rspack.config.js:

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

module.exports = defineConfig(Meteor => ({
  ...(Meteor.isServer
    ? Meteor.compileWithMeteor([/node-aead-crypto/])
    : {}),
}));

The regex catches both the main package and its per-platform binary siblings (node-aead-crypto-darwin-arm64, etc.), so it clears the warnings and the errors in one go. Same approach the docs recommend for sharp and thread-stream.

Let me know if that fixes it for you.

1 Like

The fix to rspack.config.js solved the error messages and most of the warnings, the build procedure now runs to completion. Thanks!
There are some warnings still:

WARNING in ./node_modules/ws/lib/buffer-util.js 117:32-43                                                                                                            
    ⚠ Module not found: Can't resolve 'bufferutil' in '/Users/willem/meteor/ctrlh/node_modules/ws/lib'

WARNING in ./node_modules/ws/lib/validation.js 144:33-48
    ⚠ Module not found: Can't resolve 'utf-8-validate' in '/Users/willem/meteor/ctrlh/node_modules/ws/lib'

WARNING in ⚠ asset size limit: The following asset(s) exceed the recommended size limit (244.141 KiB). This can impact web performance.                              
    │ Assets:
    │   ../_build/main-prod/client-rspack.js (2.823 MiB)
  
WARNING in ⚠ entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244.141 KiB). This can impact web performance.
    │ Entrypoints:
    │   main (2.823 MiB)
    │       ../_build/main-prod/client-rspack.js
  
  WARNING in ⚠ Rspack performance recommendations:
    │ You can limit the size of your bundles by using import() to lazy load some parts of your application.
1 Like

Glad to see that helped you.

Regarding your new warnings, two things:

  1. These are rspack’s default thresholds to warn you about large bundle sizes. It’s usually not a problem in itself, instead it’s a good signal to plan future optimizations and make the experience better for your users. If you want a clean output now, you can disable the hints (performance: { hints: false }) or bump the limits to something realistic for your app. More info in the performance Rspack docs.
    The proper fix, when you get to it, is lazy loading the heavy parts with dynamic import(). To figure out what’s worth splitting, you can analyze the bundle with rsdoctor which is automatically loaded when using the meteor bundle visualizer.

  2. The bufferutil and utf-8-validate ones come from ws. Those are optional native addons it tries to require for a bit of extra speed, but it falls back to pure JS when they’re not there, so nothing is broken. On a client bundle they don’t make sense anyway, so you can just tell rspack to ignore them:

resolve: {
  fallback: {
    bufferutil: false,
    'utf-8-validate': false,
  },
},

and both go away.

1 Like

Thanks for the fixes and clear explanations; everything builds fine without warnings now.

1 Like

For warning two, I didn’t explicitly include the Meteor.isClient wrapping in the fix above, but doing so is likely the proper solution. It scopes the fallback to the client build only, leaving the server free to use these libraries, where they can actually give a performance benefit.

module.exports = defineConfig(Meteor => ({
  ...(Meteor.isClient && {
    resolve: { fallback: { bufferutil: false, 'utf-8-validate': false } },
  }),
}));

or

module.exports = defineConfig(Meteor => ({
  resolve: {
    // ...existing alias / extensions...
    fallback: {
      ...(Meteor.isClient && { bufferutil: false, 'utf-8-validate': false }),
    },
  },
}));
1 Like