Like what we’re doing? Star us on GitHub!

Collection endpoints - errors with modules

9 months ago
1 2

Hello again,

Thanks to @GeorgeyB (#675 (comment)) I moved my custom express endpoint implementation to collection property endpoints and REST API works ok but there are a lot of errors in server console - see some of these:

ERROR in ./src/collections/Invoices.ts 3:11-24
Module not found: Error: Can't resolve 'fs' in '(...)/src/collections'
ERROR in ./node_modules/puppeteer/lib/esm/puppeteer/node/BrowserRunner.js 29:0-46
Module not found: Error: Can't resolve 'child_process' in '(...)/node_modules/puppeteer/lib/esm/puppeteer/node'

ERROR in ./node_modules/puppeteer/lib/esm/puppeteer/node/BrowserRunner.js 30:0-25
Module not found: Error: Can't resolve 'fs' in '(...)/node_modules/puppeteer/lib/esm/puppeteer/node'

ERROR in ./node_modules/puppeteer/lib/esm/puppeteer/node/BrowserRunner.js 32:0-37
Module not found: Error: Can't resolve 'readline' in '(...)/node_modules/puppeteer/lib/esm/puppeteer/node'

ERROR in ./node_modules/puppeteer/lib/esm/puppeteer/node/BrowserRunner.js 34:0-33
Module not found: Error: Can't resolve 'util' in '(...)/node_modules/puppeteer/lib/esm/puppeteer/node'
webpack compiled with 73 errors and 5 warnings

I use much more packages and each used in the handler throws such error "Module not found". Surprisingly endpoint works ok and I'm getting a response.

When I used custom express endpoint I hadn't such errors.

  • jmikrut
    Payload Team
    9 months ago

    Hey @wojciechkrol — this is because you need to use Webpack aliases to make sure that your custom endpoint code is not loaded into the admin JS bundle. Because the entire Payload config is imported directly in Webpack, and you now have your custom endpoint handlers imported in your Payload code, the admin panel is actually trying to load and execute those modules. And, fs is a server-side only package built into Node.

    Here's an example from one of our projects, where we alias a bunch of server-only modules:

        webpack: (config) => ({
          resolve: {
            alias: [
              path.resolve(__dirname, './hookHelperFunctions/stripeFunctions'),
              path.resolve(__dirname, './twilio'),
              path.resolve(__dirname, './email/sendTemplatedEmail'),
            ].reduce((alias, aliasPath) => ({
              [aliasPath]: mockModulePath,
            }), config.resolve.alias),

    We basically tell Webpack that whenever one of those files gets imported, replace that file with the mockModulePath file.

    const mockModulePath = path.resolve(__dirname, './mocks/emptyModule.js');

    And then mockModulePath is a file that just exports an empty object:

    module.exports = {};

    There are some docs written up for this too here:

    Give it a shot!

  • wojciechkrol
    9 months ago

    Well, it looks a bit complicated. I will look into this solution. Thank you for the explanation!

Open the post
Continue the discussion in GitHub
Can't find what you're looking for?
Get help straight from the Payload team with an Enterprise License.Learn More