Create-react-app - how does index.html read React application code? - reactjs

I'm new to React and I used this explanation to build a basic React app:
https://facebook.github.io/react/docs/installation.html
I opened a new project by:
npm install -g create-react-app
create-react-app my-app
cd my-app
npm start
index.html file is located in hello-world/public and here is the content of it:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<title>React App</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root">
</div>
</body>
</html>
However, all the "React stuff" is placed in hello-world\src directory. It looks that 'hello-world\src\index.js' activates the components.
What I don't understand is how index.html "reads" the content of index.js. index.html has no html tag that leads to index.js.
I can start this application by doing "npm start". What this command does is raising a server running on localhost:3000. How can I see the application without using "npm start"?

If we look at the DOM rendered on the browser (for npm start), it has the below script node injected:
<script type="text/javascript" src="/static/js/bundle.js"></script>
Similarly, for the production builds (npm run build), there is an index.html file under build folder that has a similar script node injected.
Example in my case:
<script type="text/javascript" src="./static/js/main.440dcd65.js">
Therefore, I tend to think that the script node injection is done by the react-scripts library or from one of it's dependencies.
Also, to run the app without a web server, the below should work:
Have "homepage": "./" defined in the package.json
Run a production build (npm run build)
Launch the index.html directly from the build folder.
Edited:
The configurations under ./node_modules/react-scripts/config appears to takes care of the <script> node injection.
Example: ./node_modules/react-scripts/config/webpack.config.dev.js has,
// Generates an index.html file with the <script> injected.
new HtmlWebpackPlugin({
inject: true,
template: paths.appHtml,
}),

You just need to bundle all your codes in single js file,for doing that you can use tools like webpack.
Suppose You have project structure like this:-
Project
-src
-app.js
-index.html
-package.json
-node-modules
You need to add webpack.config.js :- in your root directory which will contain some certain configurations to bundle your codes.
webpack.config.js will look alike this:-
var path = require('path');
var webpack = require('webpack');
BUILD_DIR = path.resolve(__dirname,'dist');
DEV_DIR = path.resolve(__dirname,'src');
var config = {
entry:DEV_DIR + '/app.js',
output:{
path:BUILD_DIR,
filename:'bundle.min.js',
},
module:{
loaders:[
{
test:/\.jsx?/,
include:DEV_DIR,
loader:'babel-loader',
exclude:/node_modules/,
}
]
},
};
module.exports = config;
Add a .babelrc file in your root directory:-
{
"presets": ["react","es2015","stage-1"]
}
after that In your root directory run command:-webpack
that will create a dist folder which will contain your bundle.min.js.
Edits in your index.html :-
<script src = "dist/bundle.min.js"></script>
package.json
"dependencies": {
"babel": "^6.23.0",
"babel-core": "^6.25.0",
"babel-loader": "^7.1.1",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-1": "^6.24.1",
"react": "^15.6.1",
"react-dom": "^15.6.1",
"webpack": "^3.4.1",
},
I know this is quite a big but in my opinion you will have to go through this process while developing in react,so better to go through this in the beginning.

Related

Snowpack says Im missing index.js when I'm not

Thanks for reading my question.
I successfully made a React JS App from scratch on my other PC using snowpack. And I tried it on my other one. But when I set everything up in powershell(where Im running the npm start from), it keeps telling me snowpack cant find index.js.
[snowpack] [404] Not Found (/.src/index.js)
So now my browser is just blank at the localhost.
Here is the code:
package.json
{
"name": "02",
"version": "1.0.0",
"description": "Practice 3",
"main": "index.js",
"scripts": {
"start": "snowpack dev",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "V",
"license": "MIT",
"devDependencies": {
"snowpack": "^3.8.8"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>02</title>
</head>
<body>
<div id="root"></div>
<script type="module" src=".src/index.js"></script>
</body>
</html>
index.jsx
import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render(<div>Whats good React?</div>, document.getElementById('root'));
path structure
Apparently a jsx. compies down to a .js like it did on my other machine.
I tried to rename the index file to a normal .js. No difference. I encountered this issue before. But oddly, last time on my other machine I just closed powershell and ran 'npm start' again and it worked. Tried that thrice this time, no change. I also previously had a issue calling 'react' from both 'React' and 'ReactDOM' but fixed that setting 'react-dom' instead of 'react'.
Don't know why its saying this.
Im using webstorm IDE.
Thanks in advance.

I want to get the page the user reached in React with GA

I have created a process to send the page title (url) to the GA side using react-ga4, but when I actually check the GA side, all the page titles are in React App.
I would like to know how to actually get the page using GA4 and GTM in React.
The code is as follows.
Originally, when sending with send, the page is acquired with hitType and the current URL is sent with page, so I thought this would not be a problem.
However, the actual page title being sent is the information from the title part of index.html.
App.jsx
import ReactGA from "react-ga4";
import { useLocation } from "react-router-dom";
export const App = () => {
const location = useLocation();
useEffect(() => {
ReactGA.initialize(process.env.REACT_APP_GA_MEASUREMENT_ID);
ReactGA.send({ hitType: "pageview", page: location.pathname});
}, [location.pathname]);
return (
<div>
TEST
</div>
);
};
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
I will also include the plug-ins that I have installed.
"react": "^17.0.0",
"react-dom": "^17.0.0",
"react-ga4": "^1.4.1",
"react-helmet": "^6.1.0",
"react-redux": "^8.0.2",
"react-responsive": "^9.0.0-beta.10",
"react-router-dom": "^5.3.0",
"react-scripts": "^5.0.1",
"react-scroll": "^1.8.7",
"redux": "^4.2.0",

React build shows white page with Django

I am trying to load React build files in a Django template (serving the React build files via Django static files). I’ve had success using this approach in the past with other Django templates, but with this particular case, the React app is not attaching to my div in the Django template. The React app is created using create_react_app with minimal changes.
My src/index.js file: (only changed the root element)
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('chat-root')
);
reportWebVitals();
My public/index.html file: (only changed the root element)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="chat-root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
package.json
{
"name": "demo",
"version": "0.1.0",
"private": true,
"homepage": ".",
"dependencies": {
"#testing-library/jest-dom": "^5.11.4",
"#testing-library/react": "^11.1.0",
"#testing-library/user-event": "^12.1.10",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.1",
"web-vitals": "^0.2.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
I built my files via npm run build and placed the build files in my Django static folder. These are then included in my Django template as follows. Note that this Django app has several other React “apps” that use this same approach without issue.
<div id="chat-root"></div>
{% compress js %}
<script src="{% static 'react/build_files/chat.chunk.js' %}"></script>
<script src="{% static 'react/build_files/main.chat.chunk.js' %}"></script>
{% endcompress %}
The Django url setup works with a simple html template so I am sure that is correct.
I have also tried not setting homepage in package.json and setting "homepage": "/"
but that didn't help.
There are no error during build or on browser console. The network tab in dev tools shows that the scripts get loaded but no react components get created.
I am new to react so any help will be appreciated. Thanks!
For anyone facing a similar issue, I was able to resolve it by placing all JS files created in the build.
I noticed there was another file runtime~main.[number].js being created when a build was created. I had skipped this file earlier based on the how the other React "apps" were added to static folder in Django app.
Placing this build file along with the other JS files allowed the app to attach to Django and load properly.

How to override Chrome new tab content with a react component

I am trying to create a React application/Chrome extension which overrides the content of a new tab in Google Chrome. I have used create-react-app and am simply trying to override the content of a new tab with App.js content. The folder structure is straight from the initial create-react-app, which is below.
build
node_modules
Public
favicon.ico
index.html
logo192.png
logo512.png
manifest.json
src
App.css
App.js
app.test.js
index.css
index.js
logo.svg
..
..
My manifest.json file looks like this.
{
"name": "..",
"author": "..",
"version": "1.0.1",
"manifest_version": 2,
"description": "..",
"chrome_url_overrides": {
"newtab": "index.html"
}
}
This is what my index.html looks like.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
My index.js file looks like this.
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
serviceWorker.unregister();
I have tried inserting the following but receive an empty page.
<script src="../src/index.js"></script>
How would I override the content of a new tab with App.js?
In case some have missed this step, you also need to build the app and load the build file into chrome extensions.
After changing manifest.json in the public folder and adding a .env file in the root directory as described by Corbuk, run npm build. Next, drag the build file into chrome://extensions/ or import it with the Load unpacked button
Originally I modified my manifest.json file to the following.
{
"name": "..",
"author": "..",
"version": "1.0.1",
"manifest_version": 2,
"description": "..",
"chrome_url_overrides": {
"newtab": "index.html"
},
"content_security_policy": "script-src 'self' 'YOUR HASH'; object-src 'self'"
}
The YOUR HASH can be found from the console, as highlighted below
However, I went for an alternative approach. I created a .env file in the root directory and placed the following inside of it
INLINE_RUNTIME_CHUNK=false

How to use ionic with browserify?

I first tried to install ionic from npm and require it with
require('ionic')
It does not work, the npm ionic version in bundled in an browserify unknown path.
Then I installed it from bower, and added some browser-shim :
package.json
"browserify-shim": {
"ionic": "ionic"
},
"browserify": {
"transform": [
"browserify-shim"
]
},
"browser": {
"ionic": "./libs/ionic/release/js/ionic.js"
...
libs is my bower folder.
It looks like ionic is found by browserify. But I have the following ionic error:
Uncaught TypeError: Cannot read property 'navigator' of undefined
ionic.js is complaining that window object is null.
Do you know what I am missing for requiring correctly ionic ?
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- <link rel="stylesheet" href="styles/ionbio.css" media="screen" title="no title" charset="utf-8"> -->
<title>BIO by Ionic</title>
</head>
<body ng-controller="baseCtrl">
<ion-side-menus>
<h1 class="title">{{ionbio.title}}</h1>
</ion-side-menus>
<script src="js/main.js"></script>
</body>
</html>
js/main.js
'use strict';
require('ionic');
The error is due to window object which is null. And this is because of babel who is adding at some points a "use strict".
"this" is then equal to undefined.
So I disabled babel transformation as a workaround.

Resources