Faire / mjml-react

React component library to generate the HTML emails on the fly
https://www.npmjs.com/package/@faire/mjml-react
MIT License
375 stars 16 forks source link

Uncaught ReferenceError: process is not defined (Vite + TS + SWC) #93

Closed viktorkasap closed 1 year ago

viktorkasap commented 1 year ago

I've this error in Vite project

Steps: 1 npm create vite -> React -> TypeScript+SWC (and without SWC) 2 yarn add mjml mjml-react 3 Added this example to App.tsx

import {
    Mjml,
    MjmlHead,
    MjmlTitle,
    MjmlPreview,
    MjmlBody,
    MjmlSection,
    MjmlColumn,
    MjmlButton,
    MjmlImage,
} from "@faire/mjml-react";
import { render } from "@faire/mjml-react/utils/render";

const { html, errors } = render(
  <Mjml>
    <MjmlHead>
      <MjmlTitle>Last Minute Offer</MjmlTitle>
      <MjmlPreview>Last Minute Offer...</MjmlPreview>
    </MjmlHead>
    <MjmlBody width={500}>
      <MjmlSection fullWidth backgroundColor="#efefef">
        <MjmlColumn>
          <MjmlImage src="https://static.wixstatic.com/media/5cb24728abef45dabebe7edc1d97ddd2.jpg" />
        </MjmlColumn>
      </MjmlSection>
      <MjmlSection>
        <MjmlColumn>
          <MjmlButton
            padding="20px"
            backgroundColor="#346DB7"
            href="https://www.wix.com/"
          >
            I like it!
          </MjmlButton>
        </MjmlColumn>
      </MjmlSection>
    </MjmlBody>
  </Mjml>,
  { validationLevel: "soft" }
);

...

function App() {
  return (
    <iframe srcDoc={html} width="100%" height="100%"/>
  )
}

Result

Uncaught ReferenceError: process is not defined
    at node_modules/clean-css/lib/reader/rewrite-url.js (rewrite-url.js:16:17)
    at __require2 (chunk-6FBSFQRG.js?v=7779ef7f:18:50)
    at node_modules/clean-css/lib/reader/rebase.js (rebase.js:3:18)
    at __require2 (chunk-6FBSFQRG.js?v=7779ef7f:18:50)
    at node_modules/clean-css/lib/reader/read-sources.js (read-sources.js:9:14)
    at __require2 (chunk-6FBSFQRG.js?v=7779ef7f:18:50)
    at node_modules/clean-css/lib/clean.js (clean.js:25:19)
    at __require2 (chunk-6FBSFQRG.js?v=7779ef7f:18:50)
    at node_modules/clean-css/index.js (index.js:1:18)
    at __require2 (chunk-6FBSFQRG.js?v=7779ef7f:18:50)
emmclaughlin commented 1 year ago

This looks to me like it is coming from clean-css, which is part of html-minifier. This is used by the render function here. There is ongoing discussion about wether or not to pull html-minifier out of mjml-react in v4 as it causes many issues like these. But for now we chose to keep it as it was used in v2.

For the quickest resolution I would suggest trying to write your own render function that modifies the one provided and doesn't use html-minifier. There is an example here of one that doesn't use html-minifier.

viktorkasap commented 1 year ago

Thank you for answer

I tried to create render.js file

import mjml2html from "mjml";
import React from "react";
import ReactDOMServer from "react-dom/server";

function renderToMjml(email) {
    return ReactDOMServer.renderToStaticMarkup(email);
}

export function render(
    email,
    options= {}
) {
    return mjml2html(renderToMjml(email), options);
}

But it doesn't help, maybe I'm doing something wrong...

PhpStorm2023-02-23 at 15 27 53@2x
viktorkasap commented 1 year ago

@emmclaughlin

I made sandbox project for testing, could you check it out please please?

sandbox

emmclaughlin commented 1 year ago

Interesting, thank you for sharing the sandbox. It looks like html-minifier is still installed by mjml, which reminded me that mjml is also meant to be used in a node.js environment, so it may be causing problems in your app. Instead of using mjml, try mjml-browser https://www.npmjs.com/package/mjml-browser

import mjml2html from "mjml-browser"; // This update should be the key to your fix
import React from "react";
import ReactDOMServer from "react-dom/server";

function renderToMjml(email) {
    return ReactDOMServer.renderToStaticMarkup(email);
}

export function render(
    email,
    options= {}
) {
    return mjml2html(renderToMjml(email), options);
}

You could also create an alias that maps mjml to mjml-browser, but that one line in the render should be the only place you need to replace it.

viktorkasap commented 1 year ago

Yes! It works! Thank you so much 🙏

emmclaughlin commented 1 year ago

Happy to hear! You're welcome 🎉

Note: I am closing this but will be discussing better documentation/a better plan for handling mjml vs mjml-browsers for this project moving forward, so hopefully we can make this less confusing soon.