remarkablemark/html-react-parser

Running the parser in a vercel edge function

Closed this issue ยท 24 comments

Hello,

Is it possible to run the parser in an edge function? I am trying to convert static HTML string to a react object in a vercel edge function.

Thanks
Sylvester

@sylvesteraswin Yes, it should be possible since this library can be run on both the server and client-side. See Node.js demo.

@remarkablemark thanks for your quick reply, I am referring to Vercel Edge functions. Looks like it does not support most of the Node.JS APIs.

Here is my example

// /api/sample.tsx

export const config = {
  runtime: "experimental-edge",
};

const handler = async (req: NextRequest) => {
  const element = reactParser(`<html></html>`, {});

  return element;
}

export default handler;

This is the below error I get

[Error: This browser does not support `document.implementation.createHTMLDocument`]

Thanks for the response. It seems like Vercel Edge functions is using the browser field of html-dom-parser, which is causing this error. If it didn't try to load the client library, I believe it should work.

I am also facing this issue, but just using server-side components in Next.js 13 :(

import parse from 'html-react-parser';

const htmlFromCMS = '<p>testing</p>';

...

return (
      <div>
        {parse(htmlFromCMS)}
      </div>
    );

returns:

Error: This browser does not support `document.implementation.createHTMLDocument`
    at parseFromDocument (webpack-internal:///(sc_server)/./node_modules/html-dom-parser/lib/client/domparser.js:12:11)
    at domparser (webpack-internal:///(sc_server)/./node_modules/html-dom-parser/lib/client/domparser.js:124:23)
    at HTMLDOMParser (webpack-internal:///(sc_server)/./node_modules/html-dom-parser/lib/client/html-to-dom.js:24:22)
    at HTMLReactParser (webpack-internal:///(sc_server)/./node_modules/html-react-parser/index.js:27:23)
    at Textblock (webpack-internal:///(sc_server)/./src/components/modules/Textblock.tsx:109:79)
    at attemptResolveElement (webpack-internal:///(sc_server)/./node_modules/next/dist/compiled/react-server-dom-webpack/server.browser.js:1167:42)
    at attemptResolveElement (webpack-internal:///(sc_server)/./node_modules/next/dist/compiled/react-server-dom-webpack/server.browser.js:1211:48)
    at retryTask (webpack-internal:///(sc_server)/./node_modules/next/dist/compiled/react-server-dom-webpack/server.browser.js:1811:43)
    at performWork (webpack-internal:///(sc_server)/./node_modules/next/dist/compiled/react-server-dom-webpack/server.browser.js:1856:33)
    at eval (webpack-internal:///(sc_server)/./node_modules/next/dist/compiled/react-server-dom-webpack/server.browser.js:1257:40)
    at scheduleWork (webpack-internal:///(sc_server)/./node_modules/next/dist/compiled/react-server-dom-webpack/server.browser.js:52:25)
    at pingTask (webpack-internal:///(sc_server)/./node_modules/next/dist/compiled/react-server-dom-webpack/server.browser.js:1256:29)
    at ping (webpack-internal:///(sc_server)/./node_modules/next/dist/compiled/react-server-dom-webpack/server.browser.js:1269:40)

@Jahrhause do you have a custom webpack config?

Yes I do, this is what I have:

webpack: (config, { isServer }) => {
    config.resolve.aliasFields = ['browser', 'browser.esm'];
    if (!isServer) {
      config.resolve.fallback = {
        ...config.resolve.fallback,
        net: false,
        tls: false,
      };
    }
    config.module.rules.push({
      test: /\.svg$/i,
      issuer: /\.[jt]sx?$/,
      use: ['@svgr/webpack'],
    });

    return config;
  },

@Jahrhause I think the browser field in your custom webpack config may be causing your issue.

@remarkablemark ahh that fixed the issue, sorry about that :)

@remarkablemark Hey! I have the same problem in Vercel Edge Functions, though I have default webpack config (Next.js 13).

Error: This browser does not support document.implementation.createHTMLDocument

In the logs I see it calls the lib\cleint instead of lib\server. Any ideas how to solve it? Can I somehow call the server implementatiion directly?

Thanks!

Can someone help me create a reproducible example (e.g., public repository) so I can take a look?

Running into this as well. I'm using Vercel's og image library (which runs in vercel edge functions) to generate OG images for rich text posts. I'd like to use this library to turn HTML into JSX and use it in the og image.

Here is a github repo you can use to reproduce. It's pretty simple:

  • run pnpm install
  • run pnpm dev
  • navigate to localhost:3000/api/og

You should run into it every time.

I confirm this issues still exists and it's can be a hudge problem, because if the error popup
Error: This browser does not support document.implementation.createHTMLDocument
The page in nextjs is fully loaded by the browser, SSR will break because of that.
I did that in order to fix the problem but now I have a hydrating error

'use client';

import { isServer } from '@/helpers/utils/isServer';
import parse from 'html-react-parser';

const DisplayHtmlContent: React.FC<{ content }> = ({ content }) => {
	if (isServer()) {
		return <div>{content}</div>;
	}

	return <div>{parse(content)}</div>;
};

export default DisplayHtmlContent;

This may be an issue on Vercel since it seems to be using the browser module of html-dom-parser on the server-side, which is causing this error. Has anyone tried opening an issue on Vercel?

Also, I'd like everyone to check that they're not setting the browser field in webpack config.

@grantmagdanz can you share the link to your GitHub repo?

@grantmagdanz I was able to fix the server error by updating the Webpack config in next.config.js:

const path = require('path');

/** @type {import('next').NextConfig} */
module.exports = {
  reactStrictMode: true,
  webpack: (config) => {
    config.module.rules = [
      ...config.module.rules,
      {
        test: /html-react-parser\/index\.js$/,
        resolve: {
          alias: {
            'html-dom-parser': path.join(path.dirname(require.resolve('html-dom-parser')), 'server/html-to-dom.js'),
          },
        },
      },
    ];
    return config;
  },
}

See remarkablemark/vercel-og-nextjs#2

Given this server error seems to be coming from Vercel/Webpack/PNPM and not from this library, I'm going to close this issue as won't do.

j4tmr commented

@remarkablemark It seems that the solution that was effective before now no longer works. First, I updated to the latest version, 5.1.9. Also, I noticed that the path you used, path.join(path.dirname(require.resolve('html-dom-parser')), 'lib/server/html-to-dom.js'), results in **/node_modules/html-dom-parser/lib/lib/server/html-to-dom.js, so I removed one layer of /lib, but it still doesn't work. Do you have any new ideas?

@j4tmr try this:

path.join(path.dirname(require.resolve('html-dom-parser')), 'server/html-to-dom.js')

You can verify the file path on UNPKG

j4tmr commented

@remarkablemark I think it's not because of the URL issue; I corrected the URL, and yet, it still reports, Error: This browser does not support document.implementation.createHTMLDocument.

@j4tmr can you open node_modules/html-dom-parser in your IDE and verify the full path to server/html-to-dom.js? You can copy that path and update in your webpack config

j4tmr commented

@remarkablemark Thank you for your reply. I tested it again today, and my webpack code is like this.

webpack: (config) => {
    console.log(path.join(path.dirname(require.resolve('html-dom-parser')), 'server/html-to-dom.js'))
    config.module.rules = [
      ...config.module.rules,
      {
        test: /html-react-parser\/index\.js$/,
        resolve: {
          alias: {
            'html-dom-parser': path.join(path.dirname(require.resolve('html-dom-parser')), 'server/html-to-dom.js'),
          },
        },
      },
    ];
    return config;
  },

I console.logged the URL, and the result looks like this. /Users/UserName/VSCode/ProjectName/node_modules/html-dom-parser/lib/server/html-to-dom.js I am sure that I can directly access the file via this URL. On a Mac's VSCode, you can just use command + click. I tested using a relative URL or pasting the URL directly without using path, and the result was the same.

j4tmr commented

@remarkablemark
I changed test: /html-react-parser\/index\.js$/ to test: /html-react-parser\/lib\/index\.js$/ it worked.

Has anyone got this workaround working using turbopack?