Execute a react webpack bundle without a server - reactjs

I have a simple React application that was built up with various node_modules. The application runs fine when I bundle the application into index.html and app.js and serve it from a webpack-dev-server instance. I tried to also point straight to the index.html file in chrome, expecting it to run the application as normal, given it has access to the bundled app.js though nothing loads.
My question is, what does the webpack-dev-server provide that I dont have when hitting the index.html file directly? I would have thought that everything that is needed by the application is included in the app.js bundle?
I don't have any static assets to worry about at the minute, this is a pretty simple react application that should render some basic components, that will display some text / buttons.
Console is empty and the network tab looks like the following -

Correct me if I'm wrong but I think you just didn't generate your bundle.
Webpack-server builds your files with webpack and keeps app.js in the memory. When you stop webpack-dev-server, there is no app.js file which your index.html could pick up. You simply need to use your webpack configuration to to build your app.js file.
add script to your package.json like:
"scripts": {
"build": "webpack --config directory/webpack.config.js --progress"
},
and then run nam run build, it should then generate your app bundle which then paste to directory of your index.html so it can pick it up.

Related

Issues deploying react under custom root path "/app" with create-react-app and react-router

I'm deploying an app on a host that has the following setup:
https://example.com/app1
https://example.com/app2
etc.
I need to deploy under a custom root path /app for my React app that will sit under this umbrella. I'm using react-router v5 and create-react-app.
Problem
When I build the app (I'm using vercel's serve), I get a blank page. When I go to localhost:5000/app/, nothing shows up.
I did all the suggestions from here and here, but still can't get my app to load.
I'm also confused: what's the difference between using react-router's basename and CRA's homepage field? Should I be using both, or one or the other?
EDIT: Potentially found the problem. Setting homepage=/app also changes the paths for my JS bundle, which it wasn't recognizing (hence the blank page). I manually added a app folder inside my build dir, like so: build/app/static and it worked. Shouldn't CRA do this automatically?
My setup
app.tsx
<Router basename={process.env.PUBLIC_URL}>
...
</Router>
package.json
scripts: {
"build-prod": "GENERATE_SOURCEMAP=false REACT_APP_ENVIRONMENT=production react-app-rewired build",
},
...
"homepage": "/app",
Command to serve the prod build locally
> npm run build-prod && serve -s build -l tcp://0.0.0.0:5000
The project was built assuming it is hosted at /app/.
You can control this with the homepage field in your package.json.
The build folder is ready to be deployed.
Find out more about deployment here:
bit.ly/CRA-deploy
I navigate to http://0.0.0.0:5000/app/ and get a blank page (no network calls).
What I tried
set homepage: "/app" in package.json source
set the basename for react-router source
The CRA docs shows an example using the full path of the website. That didn't work either:
"homepage": "https://example.com/app",
I got it working, although it's a workaround.
As Mohit's comment mentions, the homepage field makes it so all the assets are pre-pended by that sub-path defined in homepage. I was getting a blank screen because it couldn't find the new path to my JS bundle, aka it went from serving /build/static/js/.. to /build/app/static/js/...
Solution (workaround)
Create a new folder called app (or whatever your new root path is called) under your build directory.
Move your /build/static folder to build/app/static.
This is what it looks like with Dockerfile:
RUN pwd
RUN echo $(ls -1 $pwd)
RUN echo $(ls -1 ./build)
RUN mkdir -p ./build/app
RUN mv ./build/static ./build/app # now it should be /build/app/static
RUN echo $(ls -1 ./build)
You can take out the pwd and echo lines, I added it so I could see it working.
I don't know why CRA doesn't do this by default. It might be because I'm using react-app-rewired, which messes around with CRA's webpack config?

Hot Module Replacement in a Meteor app with React and TypeScript

I'm developing a web app in an environment consisting of Meteor, React, TypeScript and Webpack. Every time I make a change to a file I have to run webpack to recompile the full project and this can take a long time (20-30 seconds). Does anyone know if there is any way to recompile only the modified file (as the Webpack Hot Module Replacement or the React Hot Loader module works) within a Meteor app?
Thanks in advance!
Solved! It was as easy as using Webpack Watch. I created a script dev in package.json that runs meteor & webpack and added watch: true in webpack.config.js (it would be the same adding --watch in the script) so runing npm run dev starts in parallel Meteor and Webpack watching for file changes. When a file is changed, it recompiles in about just 2 seconds and refreshes the browser.

Make React JSX build faster with no production

I switched to ReactJS from pure JS for my web frontend. I made my dev workflow slower. It used to be that I edit a file, refresh browser and it's there. But now, I have to run "npm run build" and wait for a few seconds before refreshing browser.
Is there a way I can do it without building? Or is there a way I can choose not to build a minified JS to save time?
1. Use webpack watch mode to build automatically.
Add --watch param to the script that starts your build
"start": "webpack --watch"
2. Hot module replacement
You can configure webpack to use hot module replacement, which basically puts your code in live edit mode and you don't have to refresh you browser to get the changes. Configuration might be tricky but will save you a lot of time.
For more info, refer official docs - Hot Module Replacement
3. Use create-react-app
If you are just starting your project, use create-react-app to generate the react boilerplate. It comes with built-in hot module replacement and optimal confguration for both development and production.
Navigate to a new dir and run
npx create-react-app your-project-name
This will create a new directory with the name you provided and everything else from there will be straight forward.
More info here - create-react-app

React registerServiceWorker- install event

I am working on React web app and to deployed it I used create-react-app. There is a file called registerServiceWorker.js which takes care of initializing the service worker. I want to cache some files on install event however the self.addEventListener('install', event gives me the error "Unexpected use of 'self' no-restricted-globals". I manage to get rid of that by changing self to window, however the install event is never being fired. How to use this "build in" service worker in React? Or can I create the other service worker?
After struggling with this myself, I finally figured out the following pieces of information:
the serviceWorker.js file in the default CRA project is not the same sort of service-worker.js file described by the PWA documentation from Chrome and Mozilla. That's not where the self.addEventListener statements go. They go into the file referenced by CRA's serviceWorker.js, specified by the string
const `swUrl = ${process.env.PUBLIC_URL}/service-worker.js`
By default, that service-worker.js is a file that you cannot access or modify! You will need to create your own service-worker.js file in the /public folder and point swUrl to it instead. It should point to the location as a string, statically, which means it will not get integrated as part of the build process and self will correctly refer to the module instead of the global context.
I found the simple solution. This utility is perfect for that: https://github.com/bbhlondon/cra-append-sw.
cra-append-sw
Utility tool to append custom code to ServiceWorker created by Create
React App.
It allows to keep the default CRA configuration (no ejecting). It
simply appends custom code to the ServiceWorker file created by CRA
build scripts. By default, it bundles the code using very basic
Webpack+Babel configuration (this can be omitted; see options).
Installation
$ npm install cra-append-sw --save
Usage
"start": "react-scripts start && cra-append-sw --mode dev
./custom-sw.js",
"build": "react-scripts build && cra-append-sw
./custom-sw.js",

Using "homepage" in package.json, without messing up paths for localhost

This question actually follows directly from my answer on a previous question.
I added a "homepage" to my package.json because it is a React app that I hosted on Github Pages. The output of npm run build say that the /build directory can now be deployed, and it assumes the project is being hosted at /project_name/.
But on localhost, the project is not being hosted at /project_name/, so the paths being requested for js and css are messed up (looking for /project_name/static/... instead of /static/...) and the app broken.
How can one have the homepage field in package.json so that they can deploy to Github Pages (for example) while still develop locally with a working app?
Docs for create-react-app explains how to serve same build from different relative paths.
If you put homepage as
"homepage": ".",
assets will be served relative to index.html. You will then be able to move your app from http://mywebsite.example to http://mywebsite.example/relativepath or even http://mywebsite.example/relative/path without having to rebuild it.
For development purposes, serving using yarn start or npm start is good enough. App will be available in localhost
You can use PUBLIC_URL environment variable to override the homepage for a specific build.
Even better have it set in your package.json, for instance:
{
// ...
"scripts": {
"build": "react-scripts build",
"build-localhost": "PUBLIC_URL=/ react-scripts build"
// ...
}
// ...
}
For an all-in-one answer which also covers react-router-dom:
Add package.json['homepage'] to be your production URL. To be noted, the CRA build step removes the domain part of the URL to leave only the path to index.
When building for localhost, do PUBLIC_URL=/ npm run build
Add <base href="%PUBLIC_URL%" /> in your public/index.html page as proposed in this article ; it will provide support for assets (img, CSS) and will expose the %PUBLIC_URL% to be reused later.
In the component which creates your BrowserRouter (typically App.js or main.js), add:
const basename = document.querySelector('base')?.getAttribute('href') ?? '/'
use as: <BrowserRouter basename={basename} />
You can override the homepage setting using you dev shell environment:
$ export PUBLIC_URL=http://localhost:3000/
$ yarn start
or if you prefer, remove your homepage setting and configure your env before building for production:
$ export PUBLIC_URL=http://example.com/subdir
$ yarn build
I had a similar situation where an image would not appear once I added 'homepage' to my package.json and deployed it to gh-pages. After trying many different solutions, I finally solved this by taking the image out of the public folder and into the src folder. Then I switched:
<img src="/img/image.JPG" alt="image" />
to
<img src={require('../../assets/image.JPG')} alt="image" />
This seemed to do the trick for me!

Resources