I have a website hosted on CPanel which was previously in React, but I needed to migrate it to NextJS for SEO requirements. Now that I want to deploy it, I struggle to make it work. I followed this video : https://www.youtube.com/watch?v=lex3qZAf_Ok&t=1136s and the official NextJS documentation : https://nextjs.org/docs/advanced-features/custom-server, but in the end, when I add the Node JS app I get a 500 Internal Server Error.
When I execute node server.js on local or through cpanel terminal, it works and shows the website at localhost:3000.
I tried with all my files like in the video, and with a standalone build, but I have the same issue.
My code architecture :
package.json :
{
"name": "newglobal",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "node server.js",
"build": "next build",
"start": "NODE_ENV=production node server.js",
"export": "next build && next export",
"lint": "next lint",
"sitemap": "next-sitemap --config next-sitemap-config.js"
},
"dependencies": {
"#emailjs/browser": "^3.6.2",
"axios": "^0.26.1",
"bootstrap": "^5.1.3",
"moment": "^2.29.3",
"next": "12.1.5",
"react": "^17.0.2",
"react-big-calendar": "^0.40.1",
"react-dom": "^17.0.2",
"react-icons": "^4.3.1",
"react-multi-carousel": "^2.8.0",
"react-responsive-carousel": "^3.2.23",
"reactstrap": "^9.0.2",
"sass": "^1.50.0",
"sharp": "^0.30.6"
},
"devDependencies": {
"babel-plugin-styled-components": "^2.0.7",
"babel-preset-next": "^1.4.0",
"eslint": "8.13.0",
"eslint-config-next": "12.1.5",
"next-sitemap": "^2.5.28",
"styled-components": "^5.3.5"
}
}
next.config.js
/** #type {import('next').NextConfig} */
const path = require("path");
const nextConfig = {
experimental: {
outputStandalone: true,
},
images : {
domains : ["res.cloudinary.com", 'http://localhost:3000'],
loader : 'imgix',
path : ''
},
reactStrictMode: true,
sassOptions: {
includePaths: [path.join(__dirname, 'src/styles')],
prependData: `#import "variables.scss";`
},
};
module.exports = nextConfig;
jsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"#/*":["src/*"],
"#/components/*":["src/components/*"],
"#/styles/*":["src/styles/*"],
"#/context/*":["src/context/*"],
"#/image/*":["public/img/*"]
}
}
}
I use the same server.js as the official documentation, or the following after the standalone build :
process.env.NODE_ENV = "production";
process.chdir(__dirname);
const NextServer = require("next/dist/server/next-server").default;
const http = require("http");
const path = require("path");
// Make sure commands gracefully respect termination signals (e.g. from Docker)
process.on("SIGTERM", () => process.exit(0));
process.on("SIGINT", () => process.exit(0));
let handler;
const server = http.createServer(async (req, res) => {
try {
await handler(req, res);
} catch (err) {
console.error(err);
res.statusCode = 500;
res.end("internal server error");
}
});
const currentPort = parseInt(process.env.PORT, 10) || 3000;
server.listen(currentPort, (err) => {
if (err) {
console.error("Failed to start server", err);
process.exit(1);
}
const addr = server.address();
const nextServer = new NextServer({
hostname: "localhost",
port: currentPort,
dir: path.join(__dirname),
dev: false,
conf: {
env: {},
webpack: null,
webpackDevMiddleware: null,
eslint: { ignoreDuringBuilds: false },
typescript: { ignoreBuildErrors: false, tsconfigPath: "tsconfig.json" },
distDir: "./.next",
cleanDistDir: true,
assetPrefix: "",
configOrigin: "next.config.js",
useFileSystemPublicRoutes: true,
generateEtags: true,
pageExtensions: ["tsx", "ts", "jsx", "js"],
target: "server",
poweredByHeader: true,
compress: true,
analyticsId: "",
images: {
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
path: "",
loader: "imgix",
domains: ["res.cloudinary.com", "http://localhost:3000"],
disableStaticImages: false,
minimumCacheTTL: 60,
formats: ["image/webp"],
dangerouslyAllowSVG: false,
contentSecurityPolicy: "script-src 'none'; frame-src 'none'; sandbox;",
},
devIndicators: {
buildActivity: true,
buildActivityPosition: "bottom-right",
},
onDemandEntries: { maxInactiveAge: 15000, pagesBufferLength: 2 },
amp: { canonicalBase: "" },
basePath: "",
sassOptions: {
includePaths: [
"C:\\Users\\johnk\\OneDrive\\Documents\\Elikya Academy\\global.client\\src\\styles",
],
prependData: '#import "variables.scss";',
},
trailingSlash: false,
i18n: null,
productionBrowserSourceMaps: false,
optimizeFonts: true,
excludeDefaultMomentLocales: true,
serverRuntimeConfig: {},
publicRuntimeConfig: {},
reactStrictMode: true,
httpAgentOptions: { keepAlive: true },
outputFileTracing: true,
staticPageGenerationTimeout: 60,
swcMinify: false,
experimental: {
cpus: 11,
sharedPool: true,
plugins: false,
profiling: false,
isrFlushToDisk: true,
workerThreads: false,
pageEnv: false,
optimizeCss: false,
nextScriptWorkers: false,
scrollRestoration: false,
externalDir: false,
reactRoot: false,
disableOptimizedLoading: false,
gzipSize: true,
swcFileReading: true,
craCompat: false,
esmExternals: true,
isrMemoryCacheSize: 52428800,
serverComponents: false,
fullySpecified: false,
outputFileTracingRoot: "",
outputStandalone: true,
images: { layoutRaw: false },
trustHostHeader: false,
},
configFileName: "next.config.js",
},
});
handler = nextServer.getRequestHandler();
console.log("Listening on port", currentPort);
});
try to 'next build' first before you delopy on CPanel , if you got erorr in next build you must fix it , then try deploy agin
As a workaround because I needed to deploy the website, I removed SSR from my pages and used useEffect instead, and did a next export to deploy it easily.
My protractor.conf.js has the following content. I was unable to find out whats wrong here. I have manually created target/screenshots in my root folder of angular-cli. When i run protractor conf.js the protractor tests in browser window but the screenshots aren't being generated. Can anyone help me resolve this?
// Protractor configuration file
const { SpecReporter } = require('jasmine-spec-reporter');
var HtmlScreenshotReporter = require('protractor-jasmine2-screenshot-reporter');
var fs = require('fs');
var reporter = new HtmlScreenshotReporter({
dest: 'target/screenshots',
filename: 'my-report.html',
cleanDestination: false,
showSummary: true,
showConfiguration: false,
reportTitle: null,
ignoreSkippedSpecs: false,
captureOnlyFailedSpecs: false,
reportOnlyFailedSpecs: false
});
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./e2e/**/*.e2e-spec.ts'
],
capabilities: {
'browserName': 'chrome'
},
directConnect: false,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
chromeOnly: true,
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['spec.js'],
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
onPrepare() {
require('ts-node').register({
project: 'e2e/tsconfig.e2e.json'
});
jasmine.getEnv().addReporter(reporter);
},
afterLaunch: function(exitCode) {
return new Promise(function(resolve){
reporter.afterLaunch(resolve.bind(this, exitCode));
});
}
};
Thanks in Advance!
You can check by adding the 'protractor-screenshoter-plugin'
plugins: [{
package: 'protractor-screenshoter-plugin',
screenshotPath: <specify the path>,
screenshotOnExpect: 'failure',
screenshotOnSpec: 'failure+success',
withLogs: 'true',
writeReportFreq: 'asap',
imageToAscii: 'failure',
htmlReport:'true',
verbose:'info',
clearFoldersBeforeTest: true,
failTestOnErrorLog: {
failTestOnErrorLogLevel: 900
}
},
Can also check https://www.npmjs.com/package/protractor-screenshoter-plugin
protractor-jasmine2-screenshot-reporter compatible with jasmine2, so change to framework: 'jasmine2' in your conf.js
And you need to use higher version of Protractor which includes jasmine2
I did a quick test with your conf(did little changes) and it worked.
conf.js
var HtmlScreenshotReporter = require('protractor-jasmine2-screenshot-reporter');
// var fs = require('fs');
var reporter = new HtmlScreenshotReporter({
dest: 'target/screenshots',
filename: 'my-report.html',
cleanDestination: false,
showSummary: true,
showConfiguration: false,
reportTitle: null,
ignoreSkippedSpecs: false,
captureOnlyFailedSpecs: false,
reportOnlyFailedSpecs: false
});
exports.config = {
allScriptsTimeout: 11000,
// specs: [
// './e2e/**/*.e2e-spec.ts'
// ],
capabilities: {
'browserName': 'chrome'
},
directConnect: false,
// baseUrl: 'http://localhost:4200/',
framework: 'jasmine2',
// chromeOnly: true,
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['spec.js'],
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
onPrepare() {
jasmine.getEnv().addReporter(reporter);
},
afterLaunch: function(exitCode) {
return new Promise(function(resolve){
reporter.afterLaunch(resolve.bind(this, exitCode));
});
}
};
spec.js
describe('xxx', function(){
it('yyy', function(){
browser.get('https://angular.io/');
});
});
target/screenshots folder and HTML report,
(I run for twice, so there are two screenshots.)
click the yyy will open the screenshot
protractor-jasmine2-screenshot-reporter will create target/screenshots folder if not exist, no need to create in advance.
Version I used:
protractor 5.3.0
protractor-jasmine2-screenshot-reporter 0.5.0
I am trying to take the "Screen shot" of the web page when the "test case fails".
I installed "protractor-jasmine2-screenshot-reporter" using "npm".
I am using below data.
1.Node -- v6.11.4
2.NPM -- 3.10.10
3.Protractor -- 5.1.2
My "Protractor.conf.js" file code below.
var HtmlScreenshotReporter = require('protractor-jasmine2-screenshot-reporter');
var reporter = new HtmlScreenshotReporter({
dest: 'C:/Users/agudla/Desktop/VSCodeWorkSpace/my-app/screenshots',
filename: 'my-report.html'
});
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./e2e/**/*.e2e-spec.ts'
],
multiCapabilities: [{
'browserName': 'chrome',
'seleniumAddress':'http://localhost:4444/wd/hub'
},
{'browserName': 'firefox',
'marionette': 'false',
'seleniumAddress':'http://localhost:4444/wd/hub'
}
],
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
beforeLaunch: function() {
return new Promise(function(resolve){
reporter.beforeLaunch(resolve);
});
},
onPrepare() {
require('ts-node').register({
project: 'e2e/tsconfig.e2e.json'
});
jasmine.getEnv().addReporter(reporter);
},
// Close the report after all tests finish
afterLaunch: function(exitCode) {
return new Promise(function(resolve){
reporter.afterLaunch(resolve.bind(this, exitCode));
});
}
};
I am getting below error message while running the test script.
ECONNREFUSED connect ECONNREFUSED 127.0.0.1:4444
Can any one help me to solve this issue.
It is working now , i run "Selenium server" and i changed the var HtmlScreenshotReporter = require('protractor-jasmine2-screenshot-reporter'); as
var Jasmine2HtmlReporter = require('C:/Users/agudla/AppData/Roaming/npm/node_modules/protractor-jasmine2-html-reporter');
Should have to provide complete "path" for the "protractor jasmine2 html reporter".
To know the "protractor jasmine2 html reporter" path in your system , type below command in command prompt.
npm link protractor-jasmine2-html-reporter
It will print the complete path .
Below is the config file which contains both 'protractor-jasmine2-screenshot-reporter' and 'jasmine-reporter'
It works fine individually but if i combine both the protractor-jasmine2-screenshot-reporter' is not working ,is it because i have two 'onPrepare' functions
var HtmlScreenshotReporter = require('C:/Protractor_Scripts/node_modules/protractor-jasmine2-screenshot-reporter');
var reporter = new HtmlScreenshotReporter({
dest: 'C:/Protractor_Scripts/Screenshots',
filename: 'Report.html'
});
exports.config = {
directConnect: false,
multiCapabilities: [
{'browserName': 'chrome'},
{'browserName': 'firefox'}
],
allScriptsTimeout: 1200000,
framework: 'jasmine2',
specs: ['C:/Protractor_Scripts/Protractor/Driver/Driver.js'],
// Setup the report before any tests start
beforeLaunch: function() {
return new Promise(function(resolve){
reporter.beforeLaunch(resolve);
});
},
onPrepare: function() {
jasmine.getEnv().addReporter(reporter);
},
// Close the report after all tests finish
afterLaunch: function(exitCode) {
return new Promise(function(resolve){
reporter.afterLaunch(resolve.bind(this, exitCode));
});
},
Jasmine Reporter which is used to generate xml reports
onPrepare: function() {
var jasmineReporters = require('C:/Protractor_Scripts/node_modules/jasmine-reporters');
jasmine.getEnv().addReporter(new jasmineReporters.JUnitXmlReporter({
consolidateAll: true,
savePath: 'C:/Protractor_Scripts/Results',
filePrefix: 'xmloutput'
}));
},
// ----- Options to be passed to minijasminenode -----
jasmineNodeOpts: {
// onComplete will be called just before the driver quits.
onComplete: null,
// If true, display spec names.
isVerbose: false,
// If true, print colors to the terminal.
showColors: true,
// If true, include stack traces in failures.
includeStackTrace: true,
// Default time to wait in ms before a test fails.
defaultTimeoutInterval: 1200000
}
};
Don't define two onPrepare functions, put everything into a single one:
onPrepare: function() {
jasmine.getEnv().addReporter(reporter);
var jasmineReporters = require('C:/Protractor_Scripts/node_modules/jasmine-reporters');
jasmine.getEnv().addReporter(new jasmineReporters.JUnitXmlReporter({
consolidateAll: true,
savePath: 'C:/Protractor_Scripts/Results',
filePrefix: 'xmloutput'
}));
},
Please, show me how to use Protractor with RequireJS.
code works
var dentalConfig = require('./conf/dentalConfig.js');
var login = require('./pages/login.js');
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
baseUrl: dentalConfig.baseUrl,
specs: [
'pages/company.js'
],
onPrepare: function () {
login();
}
};
but if i put exports.config inside of requirejs()
protractor throw error:
c:\Users\UserName\AppData\Roaming\npm\node_modules\protractor\lib\configParser.js:184
fileConfig.configDir = path.dirname(filePath);
TypeError: Cannot set property 'configDir' of undefined.
this doesn't work
var requirejs = require('requirejs');
requirejs.config({
baseUrl: './',
nodeRequire: require
});
requirejs([
'conf/dentalConfig',
'pages/login'
],
function (dentalConfig, login) {
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
baseUrl: dentalConfig.baseUrl,
specs: [
'pages/company.js'
],
onPrepare: function () {
login();
}
};
}
);
Your config file should look something like this..
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
directConnect: true,
framework: 'jasmine',
specs: ['TestScript name that has to be executed.js'],
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
isVerbose:true,
includeStackTrace:true
},
capabilities: {
'browserName': 'chrome',
},
}