what is the best way to deploy nextjs app very first time and after than when a re-deployment is required? - next.js

I have a developed a sample application in nextjs and deployed this sample application using npm run build command.
I am following this (https://nextjs.org/docs/advanced-features/custom-server) article for a custom server deployment.
I have created a server.js file for custom server at the root level of build directory.
and modified the following in package.json:
"scripts": {
"dev": "node server.js",
"build": "next build",
"start": "NODE_ENV=production node server.js"
}
and next.config.js
module.exports = {
reactStrictMode: true,
};
const path = require("path");
module.exports = {
distDir: "build",
sassOptions: {
includePaths: [path.join(__dirname, "styles")],
},
env: {
DOM: process.env.DOM,
SERDOM: process.env.SERDOM,
PAPI: process.env.PAPI,
UAPI: process.env.UAPI,
PAEXIST: process.env.PAEXIST,
USEREXIST: process.env.USEREXIST
},
};
Now after that , I am a bit confused. Should I give the path of server.js using pm2 ?
server.js is using port 3000 and nextjs frontend app is using 3001.
Initially my deployment was not working and throwing 404 error but now it is working but here is some issue in it.
When I run the npm run build command to generate a new build/release and try to deploy again then my nextjs deployed app is not displaying the new changes.
Why ?
Does it get from somewhere else or from cached objects ?
How can I enable/display the updated deployment to my end user ?
Moreover, what is the best way to deploy nextjs app first time and after then latest deployment ?
================================package.json================================
{
"name": "New demo",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"bootstrap": "^5.0.2",
"next": "11.0.1",
"node-sass": "^4.14.1",
"react": "17.0.2",
"react-bootstrap": "^1.6.1",
"react-dom": "17.0.2",
"react-icons": "^4.2.0"
},
"devDependencies": {
"eslint": "7.29.0",
"eslint-config-next": "11.0.1"
},
"proxy": "http://localhost:3008"
}

Try like this
"scripts": {
"web:local": "env-cmd -f environments/.env.local node server.js",
"dev": "next dev",
"build": "next build",
"start": "next start"
},
where environments/.env.local is your local settins and some private info (you need to create environments folder and .env.local file). Server.js is your file, code example below
const { createServer } = require('https');
const { parse } = require('url');
const next = require('next');
const fs = require('fs');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
// these are keys to run your localhost with https protocol, you can // if you dont need it
const httpsOptions = {
key: fs.readFileSync('./environments/key.pem'),
cert: fs.readFileSync('./environments/cert.pem')
};
app.prepare().then(() => {
createServer(httpsOptions, (req, res) => {
const parsedUrl = parse(req.url, true);
handle(req, res, parsedUrl);
}).listen(3000, err => {
if (err) throw err;
console.log('> Ready on https://localhost:3000');
});
});
Then you run your application with npm run web:local
Why ?
Because you did a build, it's not dynamically updated
Does it get from somewhere else or from cached objects ?
No, its a "built" of your project
Moreover, what is the best way to deploy nextjs app first time and after then latest deployment ?
You upload your code to git, you link git to Vercel. In vercel you need to also add environment variables. Don't forget also, you need to.gitignore /environments folder!

Related

Deployed NextJS app's API returns 404 with NextJS version 13

Is there anyone else who faced the issues just like me? I try to make a GET request to my API endpoint it keeps on returning 404 when the application is deployed on Vercel - it works perfectly fine on locally.
Even it is a simple api that are provided by the Next.JS by default.
default api location: pages/api/hello
export default async function handler(req, res) {
res.status(200).json({
name: 'John Doe',
})
}
My package.json
{
"name": "my-next-js-sample"
"version": "0.1.1",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"axios": "^1.1.3",
"cheerio": "^1.0.0-rc.12",
"dayjs": "^1.11.6",
"firebase": "^9.13.0",
"next": "13.0.0",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"devDependencies": {
"eslint": "8.26.0",
"eslint-config-next": "13.0.0"
}
}
This is how I'd structured my folders.
This is how'd called the api routes.
http://localhost:3000/api/hello
http://localhost:3000/api/v2/live
Perfectly can call any api routes just like this example in local development.
Vercel Project Settings
After I'd created a new vercel account and deployed this project into that new one, then the problem has solved without knowing the actual issues.
For anyone crossing with this problem, this issue might be your guy
In a nutshell: Standalone configuration is not yet supported.

Firebase emulator infinite compiling and function call for a NextJS hello world example on macOS

I'm trying to use firebase emulators on my Mac to run a simple NextJS hello world program. It's literally a hello world example. I'm forwarding all host requests to a function that I wrote, as bellow:
const { join } = require('path')
const { https } = require('firebase-functions')
const { default: next } = require('next')
const isDev = process.env.NODE_ENV !== 'production'
const nextjsDistDir = require('./next.config.js').distDir
const nextjsServer = next({
dev: isDev,
conf: {
distDir: nextjsDistDir,
},
})
const nextjsHandle = nextjsServer.getRequestHandler()
exports.nextjs = https.onRequest((req, res) => {
return nextjsServer.prepare().then(() => {
nextjsHandle(req, res)
})
})
And here is how my package.json file looks like:
{
"name": "firebase-boilerplate",
"main": "server.js",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"serve": "next build && firebase emulators:start --only functions,hosting --project 123"
},
"dependencies": {
"dotenv": "^8.2.0",
"firebase": "^8.2.3",
"firebase-admin": "^9.4.2",
"firebase-functions": "^3.13.1",
"next": "^10.0.5",
"react": "17.0.1",
"react-dom": "17.0.1"
},
"devDependencies": {
"#types/node": "^14.14.21",
"#types/react": "^17.0.0",
"typescript": "^4.1.3"
}
}
and like I said, the page I'm trying to load is like this:
import Head from 'next/head';
// import {app} from '../services/firebase';
export default function Home() {
return (
<>Hello World </>
)
}
Now, when I run this on my mac with "nom run serve", emulators boot up ok, but the moment it try to access localhost:5000/index it keeps compiling and calling my "NextJS" function and eventually leads to timeout. Occasionally though, I do get the "Hello World" output, but only after so much computation, and only occasionally. What exactly is wrong? Is fb emulator not a reliable software or not working for Mac? OR I'm missing something?
Thanks

Cypress Scripts - Cross-Domain - iFrame Does Not Load

Hope all's well. Kindly request your help with this. We are executing a Cypress script that launches URL 1 - https://domain1.com. This website has an iFrame embedded that launches another site - https://domain2.com. Problem is, site 2 does not load within the iFrame and we keep getting the message - "domain2.com took a long time to respond". However, outside of Cypress if I launch https://domain1.com, the iFrame is opened and domain2 is launched and displayed successfully.
I have reviewed several posts and have performed the following,
cypress.json
"chromewebsecurity": false AND "modifyobstructivecode": false
index.js, followed by package.json
const path = require('path');
module.exports = (on, config) => {
on('before:browser:launch', (browser = {}, args) => {
console.log(config, browser, args);
if (browser.name === 'chrome') {
const ignoreXFrameHeadersExtension = path.join(__dirname, '../extensions/ignore-x-frame-headers');
args.push(args.push(`--load-extension=${ignoreXFrameHeadersExtension}`));
args.push("--disable-features=CrossSiteDocumentBlockingIfIsolating,CrossSiteDocumentBlockingAlways,IsolateOrigins,site-per-process");
}
return args;
});
};
{
"name": "coral",
"version": "1.0.0",
"description": "Coral testing",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"cy:run": "C:\\Testing\\Cypress\\Coral\\node_modules\\.bin\\cypress run",
"download-extension": "ced gleekbfjekiniecknbkamfmkohkpodhe extensions/ignore-x-frame-headers"
},
"author": "",
"license": "ISC",
"devDependencies": {
"cypress": "^4.1.0",
"mochawesome": "^5.0.0",
"mochawesome-merge": "^4.0.2"
},
"reporterEnabled": "mochawesome",
"dependencies": {
"file-system": "^2.2.2",
"nodemailer": "^6.4.6",
"chrome-ext-downloader": "^1.0.4"
}
}
I have downloaded the .crx file for this extension and renamed it to ignore-x-frame-headers under the extensions dir.
However, every time I run the test, the page for domain2.com does not load inside the iFrame.
Can someone please explain what are the steps I'm missing/executing wrong? Really appreciate your prompt and positive response.
Thanks in advance,
Karthik.

Module not found: Can't resolve 'fs' in '/vercel/2d531da8/node_modules/mysql/lib/protocol/sequences' when deploying to Vercel

I'm getting the following error when deploying to Vercel:
Module not found: Can't resolve 'fs' in '/vercel/2d531da8/node_modules/mysql/lib/protocol/sequences'
I don't use the dependency fs, my package.json file looks like:
{
"name": "single",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"mysql": "^2.18.1",
"next": "^9.4.4",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"serverless-mysql": "^1.5.4",
"sql-template-strings": "^2.2.2"
}
}
I'm pretty new to NextJS, so I'm not really sure what's going on. Any ideas?
Edit:
For context, I'm getting data from mySQL in the app, not sure if that has anything to do with the error
export async function getStaticProps() {
const db = require('./lib/db')
const escape = require('sql-template-strings')
const articles = await db.query(escape`
SELECT *
FROM articles
ORDER BY pid
`)
const var1 = JSON.parse(JSON.stringify({ articles }))
return {
props: {
var1,
},
}
}
Solved it by creating a next.config.js file and adding the following to it:
module.exports = {
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
// Note: we provide webpack above so you should not `require` it
// Perform customizations to webpack config
// Important: return the modified config
// Example using webpack option
//config.plugins.push(new webpack.IgnorePlugin(/\/__tests__\//))
config.node = {
fs: 'empty',
net: 'empty',
tls: 'empty'
}
return config
},
webpackDevMiddleware: config => {
// Perform customizations to webpack dev middleware config
// Important: return the modified config
return config
},
}
I had a similar problem whilst following the next.js tutorial. To resolve this I had to also create a next.config.js file as the above answer. However I have only added the following next configurations
module.exports = {
pageExtensions: ['page.tsx', 'page.ts', 'page.jsx', 'page.js']
}
Once I had added the above next.config.js file with the contents above I was able to successfully build the solution.
source: https://newspatrak.com/javascript/cant-build-react-next-project-found-page-without-a-react-component-as-default-export-context-api-file/
Next.js tutorial link: https://nextjs.org/learn/basics/deploying-nextjs-app/deploy

My Vuetify Nuxt SSR (Universal) application on Firebase is hanging

Update: My approach to use 2 folders: functions and src in not working. I started to use another approach when folder for firebase functions is located inside of the src folder. This approach is implemented by winzaa123 user: winzaa123/nuxt2-vuetify-ssr-on-firebase and I could launch it on my Google firebase.
My Steps: Preparation of the project from scratch
Create a Nuxt app inside of the src folder:
Create a Nuxt app in src folder with create-nuxt-app src
Choose the package manager Npm
Choose UI framework Vuetify.js
Choose rendering mode Universal (SSR)
Create a Firebase Project
Create a Firebase project with firebase init
Select Firebase Hosting, Firebase Functions, Firebase Firestore, Firebase Storage, Emulators
Use public directory? (public)
Configure as a single-page app (y/N) - Yes
Create a package.json file in the root folder
{
"name": "test-nuxt",
"version": "1.0.0",
"description": "My fine Nuxt.js project",
"author": "Alex Pilugin",
"private": true,
"scripts": {
"postinstall": "cd functions && npm install",
"dev": "cd src && npm run dev",
"start": "cd src && npm run dev",
"serve": "NODE_ENV=development firebase serve",
"build": "cd src && npm run build",
"build-deploy": "firebase deploy --only hosting,functions",
"build-deployf": "firebase deploy --only functions",
"build-deployh": "firebase deploy --only hosting"
},
"dependencies": {
"nuxt": "^2.0.0"
},
"devDependencies": {
"#nuxtjs/vuetify": "^1.0.0"
}
}
Edit firebase.json file
{
"functions": {
"source": "functions",
"predeploy": [
"rm -rf functions/nuxt && npm --prefix src run build && mkdir -p functions/nuxt/dist && cp -r src/.nuxt/dist/ functions/nuxt/dist && cp src/nuxt.config.js functions/"
]
},
"hosting": {
"public": "public",
"predeploy": [
"rm -rf public/* && mkdir -p public/_nuxt/ && cp -r functions/nuxt/dist/client/ public/_nuxt/ && cp -a src/static/. public/"
],
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"function": "nuxtssr"
}
]
},
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
},
"storage": {
"rules": "storage.rules"
}
}
You can see that I plan to copy content of the src/.nuxt/dist/client into the public/_nuxt folder.
I am doing it since I found "publicPath": "/_nuxt/" inside of the src/.nuxt/dist/server/client.manifest.json
Nest Step is editing of the functions/index.js file
const functions = require('firebase-functions');
const { Nuxt } = require("nuxt");
//const { Nuxt } = require("nuxt-start");
const config = {
ssrLog: true,
dev: true, // Don't start in dev mode.
debug: true, //<----------------------- Debug logs
buildDir: "nuxt",
build: {
//publicPath: ''
//publicPath: '/_nuxt/', //Default: '/_nuxt/' <-- content of .nuxt/dist/client
/*
** You can extend webpack config here
*/
extend ( config, { isDev, isClient, isServer } ) {
if ( isServer ) {
config.externals = {
'#firebase/app': 'commonjs #firebase/app',
'#firebase/firestore': 'commonjs #firebase/firestore',
//etc...
}
}
}
}
}
const nuxt = new Nuxt(config);
let isReady = false;
async function handleRequest(req, res) {
console.log("nuxtssr is running...");
if (!isReady) {
console.log("isReady: " + isReady);
try {
console.log("waiting for nuxt.ready().......");
isReady = await nuxt.ready();
console.log("nuxt is ready");
} catch (error) {
console.log("ERROR.....................");
console.log(error);
//throw new functions.https.HttpsError('error in Nuxt', error);
process.exit(1);
}
}
console.log("waiting for nuxt.render().......");
/*
* res.set('Cache-Control', 'public, max-age=1, s-maxage=1');
* await nuxt.render(req, res);
*/
res.set("Cache-Control", "public, max-age=300, s-maxage=600");
return new Promise((resolve, reject) => {
console.log("before nuxt.render......");
nuxt.render(req, res, promise => {
console.log("inside nuxt.render......");
promise.then(resolve).catch(reject);
});
});
}
exports.nuxtssr = functions.https.onRequest(handleRequest);
I use $ npm start to launch the application locally:
Nuxt.js v2.12.2
Running in development mode (universal)
Listening on: http://localhost:3000/
I deploy the application using $ firebase deploy command but I cannot see any Frontend. My application is hanging.
From my understanding, firebase hosting is only for static files. If you're trying to do SSR, that implies that there's a server running and some processing happening on the server side. You may need to deploy this to Google Cloud Functions as a "serverless" app. Take a look at this tutorial for an example.
That said, I'm not super familiar with Nuxt, but I can see two things you potentially need to do differently if you are, indeed, deploying to the correct place.
First, the hosting.public property in firebase.json should be the path to the folder that contains your built project. Since you've said your project is being built in public/_nuxt, you might need to change this property to match, i.e. in firebase.json have
{
...
"hosting": {
"public": "public/_nuxt",
...
},
...
}
For what it's worth, in regular (i.e. non-Nuxt) Vue projects, the project gets built in the dist/ folder, so in my firebase.json file I have "public": "dist". That said, I haven't ever hosted a Nuxt SSR project on firebase so this may not be how it is structured.
Second, you likely need to run nuxt build or nuxt generate before you run firebase deploy so that the project is built to the target directory. The firebase deploy command really is just a fancy way to upload files onto Google's platform.
Hope this helps!

Resources