Mattijs
Mattijs

Reputation: 372

How do I create an embeddable next.js (react) component for third-party websites?

I'm attempting to create widgets for our customers to paste (embed) within their own site.

Ideally to be used by a third-party like so:

example.html

<div id="example"></div>
<script src="https://example.com/widgets/example.bundle.js"></script>
<script>
Example.init({
    selector: "#example",
    name: "example"
});
</script>

I just can't figure out how to "bundle" specific entry points down to a single file with next.js.

I'm using Vercel which builds from GitHub, so ideally I want these bundles to be generated on build, without breaking the existing next.js site.

What I've tried:

next.config.js

module.exports = {
    entry: {
        example: './pages/example.js'
    },
    output: {
        path: "./public/widgets",
        filename: '[name].bundle.js'
    }
}

Result:

This achieves nothing, and I don't understand why! :(

Useful Sources:

Github (Next.js Discussions): Adding a Webpack entry to load separately from main.js

Next.js: Custom Webpack Config

Next.js: Setting a custom build directory

Next.js: exportPathMap

Stackoverflow: Writing embeddable Javascript plugin with React & Webpack

Webpack: Configuration Documentation

Upvotes: 17

Views: 19496

Answers (2)

Vei
Vei

Reputation: 1

Try to use htmx + head-support

This code will receive the HTML CSS JS from your next JS site and paste it into the div you need

You need just to change by js or by server side langs hx-get routes. Also don't forget about CORS

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://unpkg.com/[email protected]"></script>
    <script src="https://unpkg.com/[email protected]/dist/ext/head-support.js"></script>
</head>

<body>
    <div hx-get="http://localhost:3000/" hx-trigger="load"></div>
</body>

</html>

Upvotes: 0

Jesper We
Jesper We

Reputation: 6087

First of all, your desired embedded / initialization format (which is of course typical for embeddable widgets) requires that the loaded script creates the Example global object, on which you can then invoke .init(), which then renders your widget html into the tag specified in selector.

Next creates a full page, not an object that can be called as described above.

To change this you need to override the Next server to bypass the whole app.render() process for specific urls, and instead create the Example object, which does its own call to ReactDOM.render() on .init().

You also need to address the two possible scenarios that the web page where your widget is embedded can be a React-based page or not. So you either need to use already loaded ReactDOM or make the browser load React before you can render your widget.

While all this is doable, it is not easy to make robust, and doing it inside NextJS makes it more cumbersome. My advice would be to structure the code of your NextJS app in such a way that the parts you need in the widget are components that you can use both in the NextJS main app and in a separate embeddable widget using plain CRA.

Some further reading:

https://selleo.com/blog/how-to-create-embedded-react-widget (not the iFrame parts though)

https://meda.io/embed-react-into-an-html-web-page/

Upvotes: 13

Related Questions