ricokahler / next-plugin-preval

Pre-evaluate async functions during builds and import them like JSON
MIT License
255 stars 12 forks source link

Incompatibility with next-compose-plugins #68

Open bryanguillen opened 2 years ago

bryanguillen commented 2 years ago

Problem

As mentioned in the title, it seems like the default export (i.e. export default preval(getData())) is returning the Promise fulfilled, rather than the actual value resolved.

Here's what I see in the console:

Promise { <state>: "fulfilled", <value>: { data: "hello world" } }

So, to get around that, I've been using a hack, which is demonstrated in the mock component snippet below.

// component.js

import data from '../utils/data.preval.js'

function Component() {
  const [content, setContent] = useState({})

  // HACK: 
  data.then(resolvedData => setContent(resolvedData))

  return (
    <div>{content.data}</div>
  )
}

Obviously, this is not the right way -- something is off.

I expected it to be:

// component.js

import content from '../utils/data.preval.js'

function Component() {
  return (
    <div>{content.data}</div>
  )
}

File Setup/Usage

I actually just started using this library (awesome concept BTW!). Anyway, so here is the proof of concept we are working with.

data.preval.js

import preval from 'next-plugin-preval';

async function getData() {
  await new Promise((resolve) => setTimeout(resolve, 100));
  return { back: 'Back', next: 'Next', help: '?' };
};

export default preval(getData());

next.config.js

const withPlugins = require('next-compose-plugins');

const createNextPluginPreval = require('next-plugin-preval/config');
const withNextPluginPreval = createNextPluginPreval();

module.exports = withPlugins([
  [withNextPluginPreval]
  // some other plugins
]);

_app.js

/**
 * Other imports
 */

import globalContent from '../utils/data.preval';

// note: omitting unrelated code to keep component small
function App({ Components, pageProps }) {
  const [resolvedGlobalContent, setResolvedGlobalContent] = useState({});

  // HACK!
  globalContent.then(rglobalContent => setResolvedGlobalContent(rglobalContent));

  return (
    <>
      <NavBar next={resolvedGlobalContent.next}/>
      <Component {...pageProps}/>
    </>
}

So in summary: I am basically trying to use the resolved data within _app.js.

Versioning

Closing Thoughts

This is my first time using this package, so I may be doing something wrong (e.g. wrong use case).

However, my team and I have tried a few things, and can't seem to wrap our heads around the situation.

So in closing, I hope this was clear, and I'm looking forward to getting to the bottom of this. That way, we could use this awesome package!

All the best.

ricokahler commented 2 years ago

Hi @bryg217, thank for this detailed report. It helped me find the issue quickly!

I believe it's with next-compose-plugins. I'll look deeper into why this is happening when I get some time to.

For now, can you add withNextPluginPreval last like so:

const withPlugins = require('next-compose-plugins');

const createNextPluginPreval = require('next-plugin-preval/config');
const withNextPluginPreval = createNextPluginPreval();

// make `withNextPluginPreval` wrap last
module.exports = withNextPluginPreval(
  withPlugins([
    // ...
  ])
);
bryanguillen commented 2 years ago

@ricokahler , I tried out your suggestion and it worked! Thanks for the quick turnaround, wow!

Also, glad to hear that the info I provided helped you debug quickly.

Lastly, as far as closing the issue, I'll leave it open, and you can decide what to do with it when you're ready.

Thanks again.

neckaros commented 2 years ago

@ricokahler for me with compose it worked fine but had the issue described above when trying to access it in _App.tsx I tried your solution but then i got:

SyntaxError: Cannot use import statement outside a module at Object.compileFunction (node:vm:353:18) at wrapSafe (node:internal/modules/cjs/loader:1039:15) at Module._compile (node:internal/modules/cjs/loader:1073:27) at Module._compile (C:\Devs\serverless\node_modules\pirates\lib\index.js:99:24) at Module._extensions..js (node:internal/modules/cjs/loader:1138:10) at Object.newLoader [as .tsx] (C:\Devs\serverless\node_modules\pirates\lib\index.js:104:7) at Module.load (node:internal/modules/cjs/loader:989:32) at Function.Module._load (node:internal/modules/cjs/loader:829:14) at Module.require (node:internal/modules/cjs/loader:1013:19) at require (node:internal/modules/cjs/helpers:93:18)

Emiliano-Bucci commented 2 years ago

@ricokahler I've tried with the starter project, and with just

// next.config.js
module.exports = createNextPluginPreval();

and i'm still getting Promise{fullfiled} (only if i pass an async function to the preval(), otherwise i get the correct response, so it seems that the issue is the async function(?))