├── .gitignore ├── Dockerfile ├── README.md ├── api ├── README.md ├── gulpfile.js ├── package-lock.json ├── package.json ├── server.bundle.js ├── server.js └── webpack.config.js ├── deployment.yml ├── manifest.yml ├── my-app ├── .gitignore ├── README.md ├── components │ ├── App.js │ ├── CreateUser.js │ ├── DisplayBoard.js │ ├── Header.js │ └── Users.js ├── package-lock.json ├── package.json ├── pages │ ├── _app.js │ ├── api │ │ └── hello.js │ └── index.js ├── public │ ├── favicon.ico │ └── vercel.svg ├── server.js ├── services │ └── UserService.js └── styles │ ├── Home.module.css │ └── globals.css ├── pod.yml └── service.yml /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:10 AS ui-build 2 | WORKDIR /usr/src/app 3 | COPY my-app/ ./my-app/ 4 | RUN cd my-app && npm install && npm run build 5 | 6 | FROM node:10 AS server-build 7 | WORKDIR /root/ 8 | COPY --from=ui-build /usr/src/app/my-app/out ./my-app/out 9 | COPY api/package*.json ./api/ 10 | RUN cd api && npm install 11 | COPY api/server.js ./api/ 12 | 13 | EXPOSE 3080 14 | 15 | CMD ["node", "./api/server.js"] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nextjs-nodejs-example 2 | Example Project on how to develop and build NEXT.js with NodeJS Backend 3 | -------------------------------------------------------------------------------- /api/README.md: -------------------------------------------------------------------------------- 1 | # react-nodejs-example 2 | Example Project demonstrating how to develop React application with Nodejs 3 | -------------------------------------------------------------------------------- /api/gulpfile.js: -------------------------------------------------------------------------------- 1 | const { src, dest, series, parallel } = require('gulp'); 2 | const del = require('del'); 3 | const fs = require('fs'); 4 | const zip = require('gulp-zip'); 5 | const log = require('fancy-log'); 6 | const webpack_stream = require('webpack-stream'); 7 | const webpack_config = require('./webpack.config.js'); 8 | var exec = require('child_process').exec; 9 | 10 | const paths = { 11 | prod_build: '../prod-build', 12 | server_file_name: 'server.bundle.js', 13 | react_src: '../my-app/build/**/*', 14 | react_dist: '../prod-build/my-app/build', 15 | zipped_file_name: 'react-nodejs.zip' 16 | }; 17 | 18 | function clean() { 19 | log('removing the old files in the directory') 20 | return del('../prod-build/**', {force:true}); 21 | } 22 | 23 | function createProdBuildFolder() { 24 | 25 | const dir = paths.prod_build; 26 | log(`Creating the folder if not exist ${dir}`) 27 | if(!fs.existsSync(dir)) { 28 | fs.mkdirSync(dir); 29 | log('📁 folder created:', dir); 30 | } 31 | 32 | return Promise.resolve('the value is ignored'); 33 | } 34 | 35 | function buildReactCodeTask(cb) { 36 | log('building React code into the directory') 37 | return exec('cd ../my-app && npm run build', function (err, stdout, stderr) { 38 | log(stdout); 39 | log(stderr); 40 | cb(err); 41 | }) 42 | } 43 | 44 | function copyReactCodeTask() { 45 | log('copying React code into the directory') 46 | return src(`${paths.react_src}`) 47 | .pipe(dest(`${paths.react_dist}`)); 48 | } 49 | 50 | function copyNodeJSCodeTask() { 51 | log('building and copying server code into the directory') 52 | return webpack_stream(webpack_config) 53 | .pipe(dest(`${paths.prod_build}`)) 54 | } 55 | 56 | function zippingTask() { 57 | log('zipping the code ') 58 | return src(`${paths.prod_build}/**`) 59 | .pipe(zip(`${paths.zipped_file_name}`)) 60 | .pipe(dest(`${paths.prod_build}`)) 61 | } 62 | 63 | exports.default = series( 64 | clean, 65 | createProdBuildFolder, 66 | buildReactCodeTask, 67 | parallel(copyReactCodeTask, copyNodeJSCodeTask), 68 | zippingTask 69 | ); -------------------------------------------------------------------------------- /api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-nodejs-example", 3 | "version": "1.0.0", 4 | "description": "example project react with nodejs", 5 | "main": "server.js", 6 | "scripts": { 7 | "start": "node server.bundle.js", 8 | "build": "webpack", 9 | "dev": "nodemon ./server.js localhost 3080" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/bbachi/react-nodejs-example.git" 14 | }, 15 | "author": "Bhargav Bachina", 16 | "license": "ISC", 17 | "bugs": { 18 | "url": "https://github.com/bbachi/react-nodejs-example/issues" 19 | }, 20 | "homepage": "https://github.com/bbachi/react-nodejs-example#readme", 21 | "dependencies": { 22 | "express": "^4.17.1" 23 | }, 24 | "devDependencies": { 25 | "del": "^5.1.0", 26 | "fancy-log": "^1.3.3", 27 | "gulp": "^4.0.2", 28 | "gulp-zip": "^5.0.1", 29 | "nodemon": "^2.0.4", 30 | "webpack": "^4.43.0", 31 | "webpack-cli": "^3.3.11", 32 | "webpack-stream": "^5.2.1" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /api/server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const path = require('path'); 3 | const app = express(), 4 | bodyParser = require("body-parser"); 5 | port = 3080; 6 | 7 | // place holder for the data 8 | const users = []; 9 | 10 | app.use(bodyParser.json()); 11 | app.use(express.static(path.join(__dirname, '../my-app/out'))); 12 | 13 | app.get('/api/users', (req, res) => { 14 | console.log('api/users called!') 15 | res.json(users); 16 | }); 17 | 18 | app.post('/api/user', (req, res) => { 19 | const user = req.body.user; 20 | console.log('Adding user:::::', user); 21 | users.push(user); 22 | res.json("user addedd"); 23 | }); 24 | 25 | app.get('/', (req,res) => { 26 | res.sendFile(path.join(__dirname, '../my-app/out/index.html')); 27 | }); 28 | 29 | app.listen(port, () => { 30 | console.log(`Server listening on the port::${port}`); 31 | }); -------------------------------------------------------------------------------- /api/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | entry: './server.js', 5 | mode: 'production', 6 | target: 'node', 7 | output: { 8 | path: path.resolve(__dirname, '.'), 9 | filename: 'server.bundle.js' 10 | } 11 | }; -------------------------------------------------------------------------------- /deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | creationTimestamp: null 5 | labels: 6 | app: next-webapp 7 | name: next-webapp 8 | spec: 9 | replicas: 5 10 | selector: 11 | matchLabels: 12 | app: next-webapp 13 | strategy: {} 14 | template: 15 | metadata: 16 | creationTimestamp: null 17 | labels: 18 | app: next-webapp 19 | spec: 20 | containers: 21 | - image: docker.io/bbachin1/next-node-webapp 22 | name: webapp 23 | imagePullPolicy: Always 24 | resources: {} 25 | ports: 26 | - containerPort: 3080 27 | status: {} -------------------------------------------------------------------------------- /manifest.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | creationTimestamp: null 5 | labels: 6 | app: next-webapp 7 | name: next-webapp 8 | spec: 9 | replicas: 5 10 | selector: 11 | matchLabels: 12 | app: next-webapp 13 | strategy: {} 14 | template: 15 | metadata: 16 | creationTimestamp: null 17 | labels: 18 | app: next-webapp 19 | spec: 20 | containers: 21 | - image: nextfrontend.azurecr.io/aksdemo/next-nodejs:v1 22 | name: webapp 23 | imagePullPolicy: Always 24 | resources: {} 25 | ports: 26 | - containerPort: 3080 27 | status: {} 28 | 29 | --- 30 | 31 | apiVersion: v1 32 | kind: Service 33 | metadata: 34 | name: next-webapp 35 | labels: 36 | run: next-webapp 37 | spec: 38 | ports: 39 | - port: 3080 40 | protocol: TCP 41 | selector: 42 | app: next-webapp 43 | type: LoadBalancer -------------------------------------------------------------------------------- /my-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | -------------------------------------------------------------------------------- /my-app/README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | ``` 12 | 13 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 14 | 15 | You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. 16 | 17 | ## Learn More 18 | 19 | To learn more about Next.js, take a look at the following resources: 20 | 21 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 22 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 23 | 24 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 25 | 26 | ## Deploy on Vercel 27 | 28 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/import?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 29 | 30 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 31 | -------------------------------------------------------------------------------- /my-app/components/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import 'bootstrap/dist/css/bootstrap.min.css'; 3 | import { Header } from './Header' 4 | import { Users } from './Users' 5 | import { DisplayBoard } from './DisplayBoard' 6 | import CreateUser from './CreateUser' 7 | import { getAllUsers, createUser } from '../services/UserService' 8 | 9 | class App extends Component { 10 | 11 | state = { 12 | user: {}, 13 | users: [], 14 | numberOfUsers: 0 15 | } 16 | 17 | createUser = (e) => { 18 | createUser(this.state.user) 19 | .then(response => { 20 | console.log(response); 21 | this.setState({numberOfUsers: this.state.numberOfUsers + 1}) 22 | }); 23 | } 24 | 25 | getAllUsers = () => { 26 | getAllUsers() 27 | .then(users => { 28 | console.log(users) 29 | this.setState({users: users, numberOfUsers: users.length}) 30 | }); 31 | } 32 | 33 | onChangeForm = (e) => { 34 | let user = this.state.user 35 | if (e.target.name === 'firstname') { 36 | user.firstName = e.target.value; 37 | } else if (e.target.name === 'lastname') { 38 | user.lastName = e.target.value; 39 | } else if (e.target.name === 'email') { 40 | user.email = e.target.value; 41 | } 42 | this.setState({user}) 43 | } 44 | 45 | render() { 46 | 47 | return ( 48 |
User Id | 29 |Firstname | 30 |Lastname | 31 |
---|