1

Note: None of the answers actually work [DO NOT DELETE THIS NOTE]

simple question, I got a project, npx create-react-app react-project (consider this Project Y)

now, inside this project's App.js

import React, { Component } from 'react'

export default class App extends Component {
  render() {
    return (
      <div>
        HELLO
      </div>
    )
  }
}

now in CDN I have another Comp.js (Consider this Project X)

https://codepen.io/sirakc/pen/ZEWEMjQ.js

import React, { Component } from 'react'

export default class Comp extends Component {
  render() {
    return (
      <div>
        WORLD
      </div>
    )
  }
}

now I want to show the Comp.js into App.js as if you are taking it from local source folder

so

import React, { Component } from 'react'
//somehow somewhere import Comp.js and then <Comp/>

export default class Comp extends Component {
  render() {
    return (
      <div>
        HELLO <Comp/>
      </div>
    )
  }
}

and ofc the output should be

HELLO WORLD

when I run the project react-project and if in the CDN I change WORLD to EARTH it should change WORLD to EARTH in the output as well

so now react-project's output is HELLO EARTH

I am putting all my rep into a bounty for this, upvote if you like this question to help me attract attention.

NOTE: my need is to show React project X inside React project Y without touching much of project Y and ofc update the project X without updating anything inside project Y, so yea the <script src='chunk.js'/> isn't gonna work here, the chunk name changes, if you can find a way to not make it change, then its great, do share. If you know a working way to do this bundled into chunk.js DO SHARE!

ANY WAY OF DOING THIS IS WELCOMED, as long as Project X is independent of Project Y and I can make changes to Project X without changing Project Y

  • 1
    I am pretty sure this is not the way to do it, is there any strict reason why you need it to be unbundled pure JSX from the CDN? There are much higher chances of doing is if you build your component and then target that CDN JavaScript. – Antonio Erdeljac Aug 05 '20 at 22:01
  • 1
    @AntonioErdeljac tell me any way to do it, a bundled or non bundled doesn't matter, as long as I can have it show inside another React Project, the goal is to show Project X inside Project Y while keeping both of them independent, so that I can update Project X and there will be no need to update Project Y –  Aug 05 '20 at 22:08
  • 1
    @AKC why not making the project-y as a package, and using it inside project-x package.json (with direct linking the package to github like: https://stackoverflow.com/a/41863948/4718434 ) – yaya Aug 05 '20 at 22:22

1 Answers1

0

There are a few options you have at hand.

Option 1 - Create a NPM Package

Turn Project X into a module.

This will mean you will go to Project X development folder, and run npm login and npm publish. You can read more about that here

After that, once your package is on NPM You can go to Project Y and do the following:

import React, { Component } from 'react'
import Comp from 'my-package'

export default class Comp extends Component {
  render() {
    return (
      <div>
        HELLO <Comp/>
      </div>
    )
  }
}

Option 2 - Load a bundled JS

Instead of having your script load the following:

import React, { Component } from 'react'

export default class Comp extends Component {
  render() {
    return (
      <div>
        WORLD
      </div>
    )
  }
}

This is JSX Syntax. And it cannot be read in plain Vanilla JS - thus you cannot just import it like <script src="myscript.js" /> since this is not valid JS without a parser like Babel.

I would go to Project X and run npm run build. After that I would get the bundle.js - bundled and minified script written in Plain JS. It would look something like this:

(this.webpackJsonpchrome_extension=this.webpackJsonpchrome_extension||[]).push([[2],[function(e,t,n){"use strict";e.exports=n(99)},,function(e,t,n){"use strict";function r(){return(r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}n.d(t,"a",(function(){return r}))},function(e,t,n){"use strict";function r(e,t){if(null==e)return{};var n,r,i={},o=Object.keys(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)

Basically non-human readable code, which is parsable by <script src="myscript.js" /> tag. And then you would have to go to your index.html and inject it there, or use some of modules like react-script-tag

I would highly highly recommend going with Option #1. Since this is the preferred way to go. Look into creating NPM packages from your React project, and follow step by step.

Some more useful links about Option #1:

Create a simple React npm package in simple steps using CRA

How to publish your React component on npm

Hope this will guide you in the right direction, but the current way you are doing it is a no-go

EDIT - Tehnically there is an option #3, but I wouldn't recommend it.

Option 3 - Make your url provide just JSX, and load it in dangerouslySetInnerHtml.

Let's say your https://codepen.io/sirakc/pen/ZEWEMjQ.js would provide with this only:

<div>
  WORLD
</div>

Technically, you could then turn your link into something more readable, like .txt extension, fetch it, store it in a variable, and load it in dangerouslySetInnerHTML.

for example:

const otherProjectJSX = somehowLoad(https://codepen.io/sirakc/pen/ZEWEMjQ.js)

const MyApp = () => <div dangrouslySetInnerHtml={otherProjectJSX} />

Basically it would be this:

const otherProjectJSX = '<div>WORLD</div>'

const MyApp = () => <div dangrouslySetInnerHtml={otherProjectJSX} />

I would not recommend this, but if it is only what is inside render() you care about - it might work after all.

Antonio Erdeljac
  • 2,974
  • 1
  • 17
  • 24
  • 1
    very interesting answer, I am reading it and trying it right now –  Aug 05 '20 at 22:27
  • 1
    yet I just read your option 3, and it sounds good, I have a question, wouldn't the inner HTML will be just HTML? what if we add js inside that HTML like this
    WORLD {this.javascriptFunctions}
    will this work?
    –  Aug 05 '20 at 22:35
  • 1
    @AKC No, unfortunately that wouldn't work. It is purely to render HTML, sorry, thats why its the last solution. I am almost 100% certain option #1 is what you're looking for – Antonio Erdeljac Aug 05 '20 at 22:36
  • 1
    Hey, the option one looks good but won't the npm package will be downloaded into local npm_modules folder, therefore even if I update the npm package online and keep the version same, it still won't update the local npm_modules, won't that mean it will still show the old react component? or am I missing something, will it show the updated react component? –  Aug 05 '20 at 23:10
  • 1
    Also, once I have gotten the bundle.js ( I didn't see any bundle.js but I saw main.chunk.js that looked similar) how can I add the Comp JSX Component to the App Component? –  Aug 05 '20 at 23:20
  • @AKC Exactly if u modified anything on that package we need to reinstall that package on that application to see latest Changes .. on the fly it wont update so CDN may work but i am also looking for the same u got any solution?? – sagar bhanu Oct 13 '20 at 11:35
  • @sagarbhanu 1. use iframe ( limited controls, no XSS ofc) 2. change name of the second index.js to index_second.js ( or whatever ) then compile it without it dividing in chunks, refer that bundle inside first project's index.html as script, inside index_second.js, the react dom will target some id not of its own index.html but of the first index.html, so we are tricking the index_second.js into thinking that first project's index.html is its own, therefore render will go there. –  Oct 14 '20 at 20:54
  • @sagarbhanu this answer may be a bit complicated but just remember, all you have to do is trick the second index.js into rendering stuff into the first project's index.html, to do that change the second project entry file name, its id used by reactDOM and make the complied version have a static name ( neverchangingNamebundle.js ) and refer that bundle as a script url into the first project's index.html –  Oct 14 '20 at 20:57