I am doing a tutorial on React and I have made a youtube clone based on react. Now I wanted to upload this to my domain (hosted at one.com) but it doesn't work because bundle.js can't be found. Rather obvious since the app requires to run "npm start".
I've been googling and found that I somehow need to deploy the app by writing a deploy configuration for webpack, but I can't get it to work.
I've never understood this and I'd like to ask: how do I deploy a javascript/nodejs/webpack website to a server? Am I on the right track?
My project is based on this starter: https://github.com/StephenGrider/ReduxSimpleStarter
EDIT: So I've managed to get a bundle.js file by typing the following in cmd:
webpack ./src/index.js bundle.js
Uploaded that to the server
Now the problem is that it's looking for bundle and style in the root of the website.
Try bundling your application before running any deployment script. A package.json might have a script like this:
{
"name": "youtube-clone",
"scripts": {
"package": "webpack --config webpack.config.production.js --progress --colors",
"deploy": "npm run package && [your deployment script]"
}
}
So then you would have a file structure like this:
.
├── src/
├── .gitignore <= make sure your build files are ignored on source
├── package.json
├── webpack.config.development.js
└── webpack.config.production.js
Where one of your configs would be created for production and one for development
Related
I recently created a barebones React.js website and deployed it to GitHub pages as a user page, meaning the page should have a url of propertycashflowapp.github.io. The GitHub repo is public and can be found here.
Here is the directory tree:
├── README.md
├── index.html (this index.html is a duplicate of the one in the public directory)
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
└── src
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
├── reportWebVitals.js
└── setupTests.js
I followed all the steps in the GitHub Pages documentation. When I run npm start, the webpages shows up correctly. However after deployment when I type the url https://propertycashflowapp.github.io, I only see an empty screen.
I tried to move my index.html file to the root directory as was advised online, but it did not work. I also tried to change the line
"homepage": "https://propertycashflowapp.github.io/" many times to include the path to the index.html file, but this did not work either. I also added <BrowserRouter basename={process.env.PUBLIC_URL}> to my index.js that wrapped around my <App /> JSX tag, but this did not fix it either. I've looked at several other answers for similar questions but wasn't able to fix my issue.
All help would be greatly appreciated, thank you!
You are trying to deploy the react project with the devlopment code or the source code. This code typically contains unminified and uncompressed JavaScript and CSS files. It is not optimized or suited for production use.
You need to run npm run build command.
To know what the command does read
What is "npm run build" in create-react-app?
There are two options to deploy you code.
Option 1: use the build folder instead of the complete react project
Use this option if you want easy deployment and do not intend on changing your code.
In your local development environment, build your React application using the command npm run build. This will create a "build" folder with the optimized production version of your application.
The build folder is the folder which will contain index.html file.
Commit and push the build folder to the GitHub repository.(should be the root folder)
cd build
git init
git add .
git commit -m "message"
git branch -M
git remote add origin https://github.com/propertycashflowapp/propertycashflowapp.github.io.git
git push origin main
Enable GitHub Pages for your repository by going to the repository settings and selecting the "main" branch option under "GitHub Pages" section.
Option 2: using gh-pages
Use this option if you intend to write new code regularly. (needs setup)
Please read this article first: https://www.c-sharpcorner.com/article/how-to-deploy-react-application-on-github-pages/
Install the gh-pages package in your React app by running npm install gh-pages --save-dev in the command line.
Add a homepage field in your package.json file. This field should contain the URL of your GitHub Pages repository, which will be in the format https://propertycashflowapp.github.io.
Create a new script in your package.json file for deploying to GitHub Pages. For example, you can add the following script:
"scripts": {
"predeploy": "npm run build",
"deploy": "gh-pages -d build",
...
}
Sample package.json file can be found here
Run the deploy script by executing npm run deploy in the command line. (If you change any code run npm run deploy for deploying the changes.)
Wait for the deployment to complete and then visit the URL of your GitHub Pages repository to see your app live.
If you encounter any issue in the process, you can check the logs for troubleshooting.
Hope this helps.
I'm separating my project frontend from server side so I have the following folder structure:
- client
- server
Each folder has its own package.json to separate packages. Now from the client folder I have the following command:
webpack serve --progress --config webpack.config.development.js
And in the server command I have the following command:
nodemon server.js
I want to run both command at the same time, is there is a way to do this while keeping the same folder structure and separation of packages?
Making the folder structure like this:
Project/
├─ client/
├─ server/
├─ run.sh
run.sh:
cd server && nodemon server.js &;
cd ../client && webpack serve --progress --config webpack.config.development.js &;
run the command : ./run.sh
But because we run the applications in the background you need to kill it with ps -eaf ( for example ps -eaf | grep server.js to search within )
I think the best way to do all of this is to use a a process manager like PM2
I have a MERN stack project where previously everything server related was at the root level, however issues with ESLINT, VSCODE and package.json files has meant that I'm moving everything related to the server into it own sub directory.
However this has meant that Heroku is now giving me errors that look related to Express not being able to serve the files. Please see screengrab of errors on Heroku log below.
Deploying the app on Heroku works fine with no build errors.
How Express is configured in my server.js file
// prod only, uses /public in dev env
app.use(express.static('index.html', { root: '../client/build' }) );
app.get('*', (req, res) => {
res.sendFile(`index.html`, { root: '../client/build' });
});
My directory structure
client/
src/
public/
build/
package.json
server/
routes/
models/
server.js
package.json
.gitignore
README.md
package.json // very small file only including scripts to satisfy Heroku
Root level package.json (entire contents of file)
{
"scripts": {
"start": "cd server && node server.js",
"build": "cd client && npm run build",
"install-server": "cd server && npm install",
"install-client": "cd client && npm install",
"heroku-postbuild": "npm run install-server && npm run install-client && npm run build"
}
}
Notes:
Express isn't having a problem serving the files when I start the project locally
Heroku requires a package.json file at the root directory if you're suing a Node.js type project. This is why I have a small package.json in my root that doesn't have much in it
As it turns out switching from this:
app.use(express.static('index.html', { root: '../client/build' }) );
To
app.use(express.static('/app/client/build'))
Solved the issue.
I did try app.use(express.static('index.html', { root: '/app/client/build' }) ); but that again broke the site.
I am using create-react-app (CRA) to create and build my frontend code. My (simplified) folder structure looks like this:
package.json
node_modules/
public/
└── electron.js
└── index.html
src/
My npm scripts:
"build": {
"appId": "com.somedomain.app",
},
"scripts": {
"react-start": "react-scripts start",
"react-build": "react-scripts build",
"react-test": "react-scripts test --env=jsdom",
"react-eject": "react-scripts eject",
"electron-build": "electron-builder",
"release": "yarn react-build && electron-builder --publish=always",
"build": "yarn react-build && yarn electron-build"
}
When I run "build", the project is built and there's a build folder with everything in it, which is then used by electron to create the app.asar file. When I extract the contents, I see following structure:
package.json
node_modules/
build/
└── electron.js
└── index.html
How did electron-builder know to take the build folder from my project folder? I tried figuring it out by playing with the "build" field of my package.json like so:
"build": {
"appId": "com.somedomain.app",
"files": "app"
},
and renamed my build folder to app but then I get the following error:
⨯ Application entry file "build\electron.js" in the "[redacted][\app.asar" does not exist. Seems like a wrong configuration.
It seems as though electron still tries to run electron.js from the build folder, which now doesn't exist in app.asar.
How can I modify the file structure in the app.asar file? Does it have to contain a build folder? Ideally, I'd like have the following structure:
package.json
node_modules
electron/
└── electron.js
frontend
└── index.html
I tried modifying the "files" field some more, I tried "extraFiles" and "buildResources" but even if I can get the folder structure inside of app.asar the way I want it, I continue to get the error:
⨯ Application entry file "build\electron.js" in the "[redacted][\app.asar" does not exist. Seems like a wrong configuration.
I found out what was the problem was. Apparently, when electron-builder sees that react-scripts are in the dependencies it automatically uses a built-in configuration called react-cra. The build-in configuration for react-cra looks like this:
directories: {
buildResources: "assets"
},
files: ["build/**/*"],
extraMetadata: {
main: "build/electron.js"
}
the extraMetadata field is what caused the
⨯ Application entry file "build\electron.js" in the "[redacted][\app.asar" does not exist. Seems like a wrong configuration.
error.
To prevent using the the react-cra built-in configuration, one can add "extends": null in their package.json's "build" field. With the following configuration I got the desired result:
"build": {
"appId": "io.gueney.app",
"extends": null,
"files": [
"electron/**/*",
"frontend/**/*"
]
},
I have a repository which contains a backend (Node/Express) and a Frontend client, as such:
├── build
├── config
├── coverage
│ └── lcov-report
├── dist
│ └── static
├── server (node/express server)
│ ├── coverage
│ ├── docs
| ├── src
│ ├── etc
│ └── package.json
|
├── src (Vue.js : client code)
│ ├── api
│ ├── assets
│ ├── components
│ ├── router
│ └── store
└── static
└── package.json
I have two package.json files, one for the client and one for the server.
I face issues deploying on services such as Heroku as they don't expect two different npm packages in one repository (I think). How is it possible to deploy to Heroku (or others) with this setup?
Would it be wiser to have 1 package.json file for both parts of the application?
Which would be the advantage and disadvantages of having both frontend and backend parts in the same package.json?
You can use heroku-postbuild and maintain separate package.json files for your client and server in a single git repo that you push to Heroku.
For example, in one of my projects, the directory structure looks like this:
|-- package.json (for node/express server)
|-- Procfile
|-- www
|--client
|-- package.json (for Ionic/Angular client app)
|-- ...
|--server
|--- ...
|-- server.js (top level node.js/express script for server)
In my top-level package.json, I have:
"scripts": {
"start": "node www/server.js",
"heroku-postbuild": "cd www/client && npm install && npm run build"
},
In my client package.json I have:
"scripts": {
"build": "ionic-app-scripts build",
...
},
And finally in my Procfile I have:
web: npm start
With this solution, Heroku runs my server and builds my client code on every Heroku build.
I think client and server package.jsons should be kept separate for several reasons. For one thing, you really don't want all your server-side code bundled into your client.
I had a similar problem deploying to heroku.
I use a package called concurrently to start client side and server side via just the start script in the server side package.json. I also use node's built in proxy feature to send any requests from the client to the server by adding a line to the client package.json.
By the way, I use create-react-app for the client side so thats why some stuff looks a little strange.
My folder structure is
Server folder
Server package.json
Client folder
Client package.json
Server package.json:
"scripts": {
"start": "concurrently \"npm run server\" \"npm run client\"",
"server": "cross-env NODE_ENV=production node server.js",
"server-dev": "nodemon --watch ./ --exec babel-node -- server.js",
"client": "node start-client.js",
"dev": "concurrently \"npm run server-dev\" \"npm run client\"",
"lint": "eslint ."
},
Client package.json:
"proxy": "http://localhost:3001",
I assume Heroku just looks for a start script and runs that.
I think having some degree of separation between your server and client is a good idea so I wouldn't recommend trying to fit it all in one package.json
If you want you could probably find a tutorial online by googling with keywords like: heroku concurrently server client
btw, you don't need CORS if you set up like this
Cheers
I have run into similar issues. I have found that the easiest solution is to have two separate Git repositories, one for the backend and one for the frontend. Then there is only one package.json in the root folder of each repository.
You could then create a third repository and use Git submodules to include the backend and frontend repositories. You would use the "combined" repository to do development work, but you would deploy the individual repositories. This offers the most compatibility with deployment tools while allowing you to still maintain a single repository for easy development.