contentful / contentful.js

JavaScript library for Contentful's Delivery API (node & browser)
https://contentful.github.io/contentful.js
MIT License
1.19k stars 200 forks source link

Bundle Size for the browser version is too big #2318

Closed moonglum closed 3 weeks ago

moonglum commented 2 months ago

We are using Contentful on our site for a few pages like the blog. Unfortunately, the chunk size of contentful keeps increasing version by version (a few versions ago, it was 90kb). It is now at 227kb, and is now the biggest chunk in our entire bundle.

Expected Behavior

Actual Behavior

Possible Solution

Allow tree shaking instead of including the entire minified bundle. You always get the entire code, I assume that contains a lot of code for previewing etc. which we don't use:

image

Steps to Reproduce

import {                                                                                                                                                     
      CreateClientParams,                                                                                                                                      
      createClient,                                                                                                                  
} from 'contentful'; 

Context

A bundle size like that is a burden for our customers, who need to download it.

Environment

moonglum commented 2 months ago

I checked our code, as additional information, these are the APIs we are using:

  1. We create the client with createClient using the CreateClientParams type.
  2. On that client, we only call .withoutUnresolvableLinks.getEntries, .withoutUnresolvableLinks.getEntry, withAllLocales.getEntries and .withAllLocales.getEntry.
paulcrussell commented 2 months ago

Hi @moonglum we've noticed something similar on our project and I thought this PR would most likely resolve it. https://github.com/contentful/contentful.js/pull/2169

@axe312ger is that your view also?

axe312ger commented 1 month ago

Yes my PR should solve it! :)

axe312ger commented 1 month ago

Its published as v11! Can you rebundle and share your results @moonglum?

It should now properly tree shake :)

moonglum commented 1 month ago

Thanks, Benedikt! Are there any breaking changes? Or do I just keep everything the same?

axe312ger commented 1 month ago

@moonglum The API of the package is the same. We "just" changed the wrapping code. You might need to adjust your requires/imports, but besides of that, everything stayed the same.

Changelog coming soon, preview here: https://github.com/contentful/contentful.js/issues/2334#issuecomment-2376213081

moonglum commented 1 month ago

Thank you, the hint with ESM is important :+1: I'll try it out and get back to you, @axe312ger

moonglum commented 1 month ago

@axe312ger If I update the package, and change nothing else, our build fails:

ERROR in ../node_modules/.pnpm/contentful@11.0.3/node_modules/contentful/dist/contentful.cjs 12:19-32
Module not found: Error: Can't resolve 'os' in '/src/node_modules/.pnpm/contentful@11.0.3/node_modules/contentful/dist'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

The same is raised for zlib and tty. It feels like this uses the node package, and not the browser package. Do I need to adjust the import?

axe312ger commented 4 weeks ago

The bundle you mentioned is now exported as un-bundled code with all the dependencies. You will be able to deliver smaller files to the browser now, but likely, axios is causing the trouble in your case.

How to Fix the Polyfill Issue:

1. Use Modern Import Syntax

Try using:

import * as contentful from 'contentful';

This could help with modern module resolution and might tell axios to exclude.

2. Fix Your Setup

It looks like you might have an older or misconfigured Webpack 5 setup. Maybe your Next.js version is outdated? Also, older versions of axios can interfere with the bundler picking up the right files. (npm ls or yarn why to the rescue!)

3. Patch Webpack Fallback

If updating your setup doesn’t work, use Webpack’s resolve.fallback to replace these dependencies. Most times, setting it to false works since the dependency is only used in Node related code:

module.exports = {
  resolve: {
    fallback: {
      os: false,
      zlib: false,
      tty: false,
    },
  },
};

This is mostly what axios does in their own webpack (4) config.

If issues persist, here’s a list of shims/polyfills that might help.

moonglum commented 3 weeks ago

Thanks, we invested some time today in updating our Babel configuration, and now it works :+1: I can confirm that this significantly reduces the size of contentful in our bundle to the point that it turned from the biggest package in our bundle to now being barely visible. Thanks for the effort :bow:

axe312ger commented 2 weeks ago

@moonglum AMAZING! That was the plan. Makes me really happy when it worked out!

Huge bundles s*ck! :)