contentful.js icon indicating copy to clipboard operation
contentful.js copied to clipboard

Contentful.js doesn't work with Nuxt3

Open thiagorossener opened this issue 2 years ago • 5 comments

Expected Behavior

Contentful.js SDK works with Nuxt3 when building for production.

Actual Behavior

When creating a plugin to use Contentful:

import * as contentful from "contentful";

It works fine locally when running npm run dev.

However, when building for production, this happens:

[nuxt] [request error] contentful.createClient is not a function

Steps to Reproduce

  1. Create an entry with a "title" field in Contentful.

  2. Create a project using Nuxt3: npx nuxi init nuxt-app cd nuxt-app

  3. Install Contentful.js npm install contentful -D

  4. Create the file plugins/contentful.js and add:

import * as contentful from "contentful";

export default defineNuxtPlugin((nuxtApp) => {
  const client = contentful.createClient({
    space: "YOUR_SPACE_ID",
    accessToken: "YOUR_ACCESS_TOKEN",
  });

  nuxtApp.provide("contentfulClient", client);
});
  1. Then, in app.vue:
<template>
  <div>
    {{ entry.fields.title }}
  </div>
</template>

<script setup>
  const { $contentfulClient } = useNuxtApp();
  const entry = await $contentfulClient.getEntry("YOUR_ENTRY_ID");
</script>
  1. Run npm run dev and see that the title appears as expected.
  2. Run npm run build, then npm run preview. An error 500 occurs, in the log you see: [nuxt] [request error] contentful.createClient is not a function

Context

I'm trying to deploy my application on Netlify.

Environment

  • Language Version: Node v16.14.0
  • Package Manager Version: NPM 8.3.1
  • Browser Version: Version 100.0.4896.127 (Official Build) (x86_64)
  • Operating System: macOS Monterey v12.2.1Darwin *** 21.3.0 Darwin Kernel Version 21.3.0: Wed Jan 5 21:37:58 PST 2022; root:xnu-8019.80.24~20/RELEASE_X86_64 x86_64
  • Package Version: "contentful": "^9.1.25" and "nuxt": "3.0.0-rc.1"
  • Which API are you using?: Trying to use Contentful JavaScript Content Delivery Library

thiagorossener avatar Apr 26 '22 20:04 thiagorossener

I've run into the same issue in an Astro project. Interestingly in my case I only have this issue when building the site, not whilst Vite is running in watch mode.

I've played around with the stable and beta version of this package, along with named vs default imports and found this combination to work for me in both dev and production mode:

Install the beta version with

yarn add contentful@beta-v10

Then switch your usage like this

- import { createClient } from 'contentful';
+ import contentful from 'contentful';

- export const client = createClient({...});
+ export const client = contentful.createClient({...});

davidwarrington avatar May 02 '22 21:05 davidwarrington

What is the difference between the two?

import { createClient as createClientOrig } from 'contentful'; 
import { createClient as createClientToo } from 'contentful-management';

denisedelbando avatar Jun 24 '22 17:06 denisedelbando

contentful@beta-v10

Your solution is not working.

In short, this is a problem when using contenful.js with Vite.

cody-ta avatar Aug 14 '22 16:08 cody-ta

I had this same issue. Worked in Dev, but not in Production. The below code solved my problem. Basically, in Production you must use contentful.createClient. In Dev you can use createClient.

Hope this helps someone else.

import { createClient } from "contentful";
import contentful from 'contentful'

export default defineNuxtPlugin((nuxtApp) => {
  const config = useRuntimeConfig();

  const createClientFunc = process.env.NODE_ENV === 'development' ? createClient : contentful.createClient

  const client = createClientFunc({
    space: config.CTF_SPACE_ID,
    accessToken: config.CTF_CDA_ACCESS_TOKEN,
  });

  return {
    provide: {
      contentfulClient: client,
    },
  };
});

fmarcheski avatar Aug 16 '22 05:08 fmarcheski

Thanks @fmarcheski! I had to do the same thing, ended up forgetting to post it here. That solution works for me too.

thiagorossener avatar Aug 16 '22 14:08 thiagorossener

Any updates on a fix for this? I've tried the suggestions above, but no success. Running on "contentful": "^10.0.0-beta-v10.8" and "nuxt": "npm:nuxt3@latest". Getting either this error Named export 'createClient' not found. or the error from the OP.

JackEdwardLyons avatar Nov 01 '22 09:11 JackEdwardLyons

Hi @JackEdwardLyons, Sorry to hear you're still running into this issue! Unfortunately, I have personally no experience with nuxt. I have tried to create a very basic example to understand what is going on- maybe you want to have a look?

As far as I can see the import is working fine - the only error I see is expected (no space id and credentials provided, therefore also no entries returned)

https://codesandbox.io/s/condescending-nightingale-bkvx51

marcolink avatar Nov 01 '22 09:11 marcolink

Hi @marcolink thanks for the quick response. I appreciate it. I had a look at your codesandbox link and it is using "nuxt": "^2.15.0".

I forked it and bumped the version to the latest RC release, and now it's not loading correctly. If you open the terminal and run yarn build you'll get this error 'default' is not exported by plugins/contentful.js, imported by virtual:nuxt:/sandbox/.nuxt/plugins/client.mjs

Please take a look:

https://codesandbox.io/s/small-breeze-5fnx3x

Note: I've tested from nuxt 3 rc.0 onward and this error occurs. It does not occur on nuxt 2.15.8. From what I've read in other GH issues, this could be vite related. I'm not exactly sure if there is some vite specific config required, but just wondering, do you have any knowledge of vite and it's interaction with contentful?

JackEdwardLyons avatar Nov 01 '22 10:11 JackEdwardLyons

@JackEdwardLyons Changed the export/import of the plugin to use defaults, but now I get a different error

https://codesandbox.io/s/great-dust-v0oqz8

 ERROR  Nitro is not initialized yet. You can call useNitro() only after ready hook.             

Not sure what it means?

marcolink avatar Nov 01 '22 11:11 marcolink

Hi @marcolink thanks again, I checked your fork, and set the nuxt verion to the latest RC. I've updated the plugin code and been able to run a build - it's not a full reproduction of the issue I am facing, but at least running yarn build and yarn start seems to work (add your own credentials to see the screen actually show content).

https://codesandbox.io/s/stoic-cherry-9jl09s?file=/plugins/contentful.js

And just for reference here is the full error from my actual app:

[worker reload] [worker init] Named export 'createClient' not found. The requested module 'app/node_modules/contentful/dist/contentful.node.js' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'app/node_modules/contentful/dist/contentful.node.js';
const { createClient } = pkg;


  import { createClient } from 'node_modules/contentful/dist/contentful.node.js';
  ^^^^^^^^^^^^
  SyntaxError: Named export 'createClient' not found. The requested module 'node_modules/contentful/dist/contentful.node.js' is a CommonJS module, which may not support all module.exports as named exports.
  CommonJS modules can always be imported via the default export, for example using:
  
  import pkg from 'node_modules/contentful/dist/contentful.node.js';
  const { createClient } = pkg;
  
  at ModuleJob._instantiate (node:internal/modules/esm/module_job:128:21)
  at async ModuleJob.run (node:internal/modules/esm/module_job:194:5)
  at async Promise.all (index 0)
  at async ESMLoader.import (node:internal/modules/esm/loader:385:24)
  at async loadESM (node:internal/process/esm_loader:88:5)
  at async handleMainPromise (node:internal/modules/run_main:61:12)

ℹ Vite client warmed up in 12777ms  

JackEdwardLyons avatar Nov 01 '22 19:11 JackEdwardLyons

Hey @marcolink just want to say thanks for the help and that it's likely a Nuxt/Vite issue or something else on my side. I don't think you need to look into this any more.

JackEdwardLyons avatar Nov 02 '22 00:11 JackEdwardLyons

Hey @marcolink just want to say thanks for the help and that it's likely a Nuxt/Vite issue or something else on my side. I don't think you need to look into this any more.

Hey Jack have you found a way to solve this, I am really not getting it to work, I am getting the same error messages.

ruriarte-zaelot avatar Jan 23 '23 20:01 ruriarte-zaelot

@ruriarte-zaelot what version of contentful.js are you using?

marcolink avatar Jan 23 '23 20:01 marcolink

@ruriarte-zaelot what version of contentful.js are you using?

Hey marco thanks for your quick response. I'm using version 9.2.17

ruriarte-zaelot avatar Jan 23 '23 20:01 ruriarte-zaelot

Ok, that version introduces a fix for ESM builds. I'm completely unexperienced with VUE and NUXT, but does this work: https://codesandbox.io/p/sandbox/nuxt-with-contentful-m1bwfp

marcolink avatar Jan 23 '23 20:01 marcolink

@marcolink The problem I'm facing is that the way you imported in the sandbox is working for me but only in local. Same problem @thiagorossener was having. When I deploy to dev/production it throws this error.

Named export 'createClient' not found. The requested module 'contentful' is a CommonJS module, which may not support all module.exports as named exports.

CommonJS modules can always be imported via the default export, for example using:

import pkg from 'contentful';

const { createClient } = pkg;

What worked best for me so far was to use the procedure suggested by @fmarcheski . That is working but only for v10beta, not for v9.

ruriarte-zaelot avatar Jan 23 '23 21:01 ruriarte-zaelot

I am also having this issue in my current application using nuxt:3.0.0 and contentful:9.2.17. @ruriarte-zaelot To confirm, were you able to resolve the error you mentioned by switching to the v10beta release? What version of nuxt were you using?

adi-kumar avatar Feb 15 '23 06:02 adi-kumar

@adi-kumar using nuxt 3.0.0 with contentful v10beta applying the procedure given by @fmarcheski works.

ruriarte-zaelot avatar Feb 15 '23 15:02 ruriarte-zaelot

You don't need to switch to the beta version of contentful to fix this. The beta version seems to have some issues (it didn't respect the include setting on my calls when I tried it for example). In the built server, the createClient function ends up on the contentful.default object instead of the contentful object. I'm sure there's an explanation, probably something to do with interoperability between CommonJS and ES Modules.

Anyway, I solved it like this:

import * as contentful from 'contentful'

const client = contentful.createClient
    ? contentful.createClient({...})
    : contentful.default.createClient({...})

I'm using nuxt 3.2.3 and contentful 9.3.3.

eriklindgren avatar Mar 06 '23 15:03 eriklindgren

Cannot find contentful.default..

SatoshiRoppongi avatar Mar 18 '23 08:03 SatoshiRoppongi

Cannot find contentful.default..

The solution still works for me on nuxt 3.3.1 and contentful 9.3.5. I build the app with nuxi build and then run it with node .output/server/index.mjs. In the server/shell, the contentful.default object has the createClient function and in the client/browser the createClient function is on the contentful object itself.

If I run the app with nuxi dev, the createClient function is on the contentful object in both server and client 🤷

eriklindgren avatar Mar 19 '23 21:03 eriklindgren

Cannot find contentful.default..

I had to ignore this with /* eslint-disable import/namespace */. The solution from @eriklindgren is working for me.

  • Operating System: Darwin
  • Node Version: v18.14.1
  • Nuxt Version: 3.3.1
  • Nitro Version: 2.3.1
  • Builder: vite
  • User Config: target, ssr, experimental, runtimeConfig, build, tailwindcss, vite, css, image, modules, i18n

rutgerbakker95 avatar Mar 23 '23 17:03 rutgerbakker95

For me, @fmarcheski solution worked like a charm! Thank you.

lisaschumann avatar Apr 21 '23 12:04 lisaschumann

I am importing with import * as contentful from 'contentful'; and observed the structure of contentful object differs when running dev server vs build

dev server

{
  contentful: Object [Module] {
    createClient: [Getter],
    createGlobalOptions: [Getter]
  }
}

build

{
  contentful: [Module: null prototype] {
    contentful: undefined,
    default: Object [Module] {
      createClient: [Getter],
      createGlobalOptions: [Getter]
    }
  }
}

peeyushsingla avatar Aug 29 '23 10:08 peeyushsingla

This is a known issue when using Vite for server side rendering a CommonJS module, but it sounds like they're looking into fixing it for Vite 5. This issue thread has more information. One more potential fix would be to import contentful this way:

import contentful from 'contentful/dist/contentful.node.min.js';

But then you'll also want to polyfill global in your index.html file:

<script type="application/javascript">
  if (global === undefined) {
    var global = window;
  }
</script>

danemauland avatar Sep 25 '23 19:09 danemauland

closing this for now

marcolink avatar Oct 11 '23 11:10 marcolink