Given the following scenario, how can I use React/Preact components in my project:
The main/header content is generated using Django (or static html) templates
I want to use React to generate the sidebar and footer components, depending on the page it is sitting on.
I think the following would work, but I don't know how to split or load the bundles according along the following lines:
Load React/React-dom bundle on every page
Load page specific bundles on demand, where needed
How can I bundle single components up using webpack for use in static html pages and display them where needed? How do I configure webpack for that?
Essentially you transpile React from a bunch of JS/JSX files into one JS script (using Babel), which is then loaded in your html document. So it'd be something like this:
<html>
<head>
// Usual head section stuff
</head>
<body>
<div id="header">
This is the Django site header
</div>
<div id="sidebar_root" />
<div>
Blah blah all the site's body content from Django
</div>
<div id="footer_root" />
<script src="react_sidebar.js" />
<script src="react_footer.js" />
</body>
</html>
And you'd have you React components (which would have a bunch of sub-components), one of which is rendered into "react_sidebar.js" and the other into "react_footer.js". So those components would be in React and the others would be Django.
So in order to load React bundle scripts on demand, you just need to include the script and the div which acts as its root.
P.S.
If you were always loading the sidebar and footer together (i.e. never just one or the other bur always both) you could combine them React DOM rendering into one script, so you'd only have to include one script in your html
Related
i built a Homepage using the Django templating engine and on one page is a js application i wrote. Now i moved to a Frontend <-> Backend architecture with React and Django-rest-framework.
The Application i had in Django was served as a .html file with <script> tags for the js part.
Now i moved to React and i'm serving the html elements through a React component and through React-helmet i'm adding the <script> tags for this specific page. The actual .js files reside in the /public folder of react.
I thought i can replicate this way the old structure. But now i get Errors that the .js files can't import classes from the first external script.
What could be the difference in this setup ?
Django:
<script type="text/javascript" defer src="https://unpkg.com/quantum-circuit"></script>
<script defer src="{% static 'path/to/file.js' %}"></script>
...
React:
<script type="text/javascript" defer src="https://unpkg.com/quantum-circuit"></script>
<script defer src={process.env.PUBLIC_URL + 'path/to/file.js' }></script>
...
The Error Message at React is that my file.js can't find the import from the first <script>. But in Django there is no problem.
the import statement in file.js is:
import { QuantumCircuit } from "quantum-circuit";
Thank you in advance for every answer :)
It seems that the first external script is not ready when my custom scripts are trying to call it.
I fixed the issue using the useEffect hook. It calls the external script and if it's ready i'm calling my custom scripts.
Despite i was able to resolve this issue, i'm wondering why this hasn't happend in Django before.
I am using snipcart which looks at the static html document and looks for #snipcart element. You can put vue elements in there and the magic will be done on the snipcart.js side.
When using Gatsby, in order to edit the index.html file, you have to create a React file called html.js. In this file I can successfully add Snipcart and everything works. That is until I want to customize the cart and Snipcart uses vue for that. You have to add the vue items in between the #snipcart div.
snipcart-docs-customization
An example
<div hidden id="snipcart" data-api-key="<API_KEY>">
<component-to-override>
<div class="root">
{{ vue_variable.itemText }}
</div>
</component-to-override>
</div>
The problem is, webpack will throw an error if I add vue. This makes sense. So Gatsby has a couple of nice middleware type API's gatsby-ssr and gatsby-browser that might help this.
Looking at these API's I am still unsure how to do this. I need this code added to the index.html as Gatsby is rendering the static pages, at least I feel that is best.
Because Snipcart looks in the #snipcart divs innerHTML for vue formatted components, this is difficult because webpack wants to convert the vue, I do not want it converted.
How can I go about this?
Some useful links I have entertained:
Gatsby Lifecyle
Gatsby-ssr api
Gatsby-browser api
Snipcart customizing components
Can Gatsby or Jekyll or any other static site generators render a React-authored site into purely static HTML? I'm looking to host on S3/CloudFront or similar and also have little to no JS in the output.
Basically I'm looking to create a static website but would like to use React as development tool to take advantage of reusable UI components. Actual runtime interaction is minimal and can be done without React at runtime.
I looked at react-static which seems to be exactly what I'm looking for but the rendered html pages still reference and load the React library.
With my minimal needs I could probably roll my own thing to create each page as a separate React SPA and then use ReactDOMServerto render each to a static HTML file. I'm looking to see if there are simpler/better options.
You can use pupeteer to get the rendered html of any webpage, including SPA. Or use rendertron, which uses pupeteer underneath.
Another one is react-snap, which will crawl your web on build and create the html for each page.
With Gatsby, sure you can. Gatsby has a html.js that serves as a template for all generated pages. You can simply remove Gatsby's javascript from that html.
/* Generated html */
...
<body>
<div id="___gatsby">...</div>
<script src="/common.js"></script> <-- remove this
</body>
First copy the default html to your src:
cp .cache/default-html.js src/html.js
Then, edit this line:
/* src/html.js */
<body {...this.props.bodyAttributes}>
{this.props.preBodyComponents}
<div
key={`body`}
id="___gatsby"
dangerouslySetInnerHTML={{ __html: this.props.body }}
/>
- {this.props.postBodyComponents}
+ {process.env.NODE_ENV !== 'production' && this.props.postBodyComponents}
</body>
This ensures you can still make use of gatsby's hot reload in development, but generated htmls will not include React & webpack generated scripts.
A more meticulous approach would be to loop over postBodyComponents & only removes the script tag that link to common.js, but for most case I think it'll be fine.
This definitely defeats the purpose of Gatsby, which has its own convention & complex process just so it can generate a progressive web app. For your case, if you're not already familiar with Gatsby, maybe it'd be simpler to roll your own SSR. My answer is only to show whether it's possible with Gatsby or not.
Is there a way to achieve this? I use react.js in the front end only and want to keep it like this.
When you build your application via Yarn/npm, that's what basically you'd be doing. The system will bundle your assets and generates an HTML file. If you open the built index.html you should see your parsed React app in plain JS and HTML.
If you plan to put the build on a CDN, all you need to do is move the assets (JS and CSS) and the index.html wherever you want to host them. Ensure that <script> and <link> are pointing to the bundled assets within your index.html.
<script type="text/javascript" src="/static/js/your-bundle-main.js"></script>
<link href="/static/css/your-bundlemain.0a265734.css" rel="stylesheet">
You can use unpkg, is a fast, global content delivery network for everything on npm. Use it to quickly and easily load any file from any package using a URL like:
<script src="unpkg.com/react#15.3.1/dist/react.min.js"></script>
<script src="unpkg.com/react-dom#15.3.1/dist/react-dom.min.js"></script>
I am working on a little interface built around AngularJS. I have an index.html file and I built a route to a base.html file (using ng-view) which contains several elements including a Morris chart.
However, when I launch my index.html everything from the base.html is displayed... except the chart. And I have the following error in the console :
Error: Graph container element not found
So I tried, to move my scripts morris.js (and 2 others) to the base.html juste after my element (that will contain the chart) is created but it doesn't work neither.
index.html
<!DOCTYPE html>
<div ng-app="pistApp" ng-controller="MainController" id="wrapper">
<div ng-view id="page-wrapper">
</div>
</div>
base.html
<!-- other elements who works but I simplify -->
<div id="morris-area-chart"></div>
Problem solved thanks to Angularjs does not load scripts within ng-view
I just had to include jQuery before angular script.
Include in your project-'raphael/raphael.js','morris.js/morris.js', 'angular-morris-chart/src/angular-morris-chart.js','morris.js/morris.css'
These files will be in your bower_components after the bower install angular-morris-chart.
Try examples in https://angular-morris-chart.stpa.co/
it will work.