I'm trying to deploy areact-app using express server but I've got a problem while trying to link the front and the back. The jsx pages are working, but the style is not.
Here is my server.js document:
const express = require("express");
const cors = require("cors");
const path = require("path");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
require("dotenv").config({ path: "./config/.env" });
require("./config/db");
const { checkUser, requireAuth } = require("./middleware/auth.middleware");
const userRoutes = require("./routes/user.routes");
const messageRoutes = require("./routes/message.routes");
const app = express();
app.use(express.static(path.join(__dirname, "client/build")));
const corsOptions = {
origin: process.env.CLIENT_URL,
credentials: true,
allowedHeaders: ["sessionId", "Content-Type"],
exposedHeaders: ["sessionId"],
methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
preflightContinue: false,
};
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.json());
app.use(cookieParser());
app.use(cors(corsOptions));
// jwt
app.get("*", checkUser);
app.get("/jwtid", requireAuth, (req, res) => {
res.status(200).send(res.locals.user._id);
});
app.use("/api/user", userRoutes);
app.use("/api/message", messageRoutes);
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname + "/client/build/index.html"));
});
app.listen(process.env.PORT, () => {
console.log(`listening on port ${process.env.PORT}`);
});
and here 's my file organisation
Related
I'm using Symfony/Webpack-Encore,and I'm trying to import puppeteer.
webpack.config.js (notice the config.target = "node" at the end)
const Encore = require('#symfony/webpack-encore');
...
const config = Encore.getWebpackConfig();
config.target = "node";
module.exports = config;
extra.js (imported in app.js)
const puppeteer = require('puppeteer-extra')
const StealthPlugin = require('puppeteer-extra-plugin-stealth')
const AdblockerPlugin = require('puppeteer-extra-plugin-adblocker')
function getDom(url) {
puppeteer.use(StealthPlugin())
puppeteer.use(AdblockerPlugin({ blockTrackers: true }))
puppeteer.launch({ headless: true }).then(async browser => {
const page = await browser.newPage()
await page.setViewport({ width: 800, height: 600 })
await page.goto(url);
const dom = await page.evaluate(() => document.documentElement.outerHTML)
await browser.close()
return dom;
})
return null;
}
I tried to find a way to change the language by changing the site's sub-path in the next-i18next package, I searched the Internet (https://github.com/isaachinman/next-i18next/issues/32 , https://github.com/i18next/i18next-browser-languageDetector#detector-options) for an answer to this question, but it did not work. After changing the subpath in the url it is duplicated and redirects me to a page that does not exist.
my code:
// path-to-my-project/i18n.js
const NextI18Next = require('next-i18next').default;
const i18nextBrowserLanguageDetector = require('i18next-browser-languagedetector').default;
const { localeSubpaths } = require('next/config').default().publicRuntimeConfig;
const path = require('path');
module.exports = new NextI18Next({
otherLanguages: ['ru'],
defaultNS: 'common',
localeSubpaths,
localePath: path.resolve('./public/static/locales'),
use: [i18nextBrowserLanguageDetector],
});
// path-to-my-project/pages/_app.js
import '../styles/main.scss';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import Router from 'next/router';
import App from 'next/app';
import { appWithTranslation } from '../i18n';
Router.events.on('routeChangeStart', () => NProgress.start());
Router.events.on('routeChangeComplete', () => NProgress.done());
Router.events.on('routeChangeError', () => NProgress.done());
const MyApp = ({ Component, pageProps }) => (
<Component {...pageProps} />
);
MyApp.getInitialProps = async (appContext) => ({ ...await App.getInitialProps(appContext) });
export default appWithTranslation(MyApp);
maybe I just missed something, because it's my first project on next.js, so I'm asking for help in the community and would be grateful for any help or hint.
By default next-i18next will try to detect the language to show from users browser.
Try to disable it.
const NextI18Next = require('next-i18next').default
const { localeSubpaths } = require('next/config').default().publicRuntimeConfig
const path = require('path')
module.exports = new NextI18Next({
browserLanguageDetection: false, // <---
serverLanguageDetection: false, // <---
otherLanguages: ['de'],
localeSubpaths,
localePath: path.resolve('./public/static/locales')
})
in file next.config.js i have this settings:
// path/to/project/next.config.js
const { nextI18NextRewrites } = require('next-i18next/rewrites');
const localeSubpaths = {
ru: 'ru',
};
module.exports = {
rewrites: async () => nextI18NextRewrites(localeSubpaths),
publicRuntimeConfig: {
localeSubpaths,
},
devIndicators: {
autoPrerender: false,
},
};
but there was not enough configuration for English localization, so you just need to add it:
// path/to/project/next.config.js
const { nextI18NextRewrites } = require('next-i18next/rewrites');
const localeSubpaths = {
en: 'en', // <------
ru: 'ru',
};
module.exports = {
rewrites: async () => nextI18NextRewrites(localeSubpaths),
publicRuntimeConfig: {
localeSubpaths,
},
devIndicators: {
autoPrerender: false,
},
};
I am trying to customize my server using Next.js:
const express = require('express')
const next = require('next')
port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({dev, dir: '../'})
const handle = app.getRequestHandler()
app.prepare().then(() => {
const server = express()
server.get('/a', (req, res) => {
res.send("Palin text: Hello From Express server Riko :)")
})
server.get('/b', (req, res) => {
return app.render(req, res, '/b', req.query)
})
server.get('/posts/:id', (req, res) => {
return app.render(req, res, '/posts', { id: req.params.id })
})
server.get('*', (req, res) => {
res.removeHeader('Transfer-Encoding')
res.setHeader('Connection', 'close')
return handle(req, res)
})
server.listen(port, err => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
When a page is being loaded i see that the response header Connection is set to 'keep-alive'. And this results in very long response time.
I tried to change the header here:
server.get('*', (req, res) => {
res.removeHeader('Transfer-Encoding')
res.setHeader('Connection', 'close')
return handle(req, res)
})
Without success though.
This is the Next.js configuration file:
module.exports = {
distDir: 'build',
poweredByHeader: false
}
use this:
res.set('Connection', 'close');
I am struggling to unit test the store in the componentWillLoad() lifecycle.
I have tried following this guide: https://github.com/dmitry-zaets/redux-mock-store
component.tsx
#Prop({ context: "store" }) store: Store;
componentWillLoad() {
this.store.mapDispatchToProps(this, { updateStep });
}
spec.ts
const middlewares = [thunk];
const mockStore = configureStore(middlewares);
const mapDispatchToProps = () => ({ type: updateStep});
it('should test componentWillLoad', () => {
const initialState = {};
const store = mockStore(initialState);
store.dispatch(mapDispatchToProps());
const actions = store.updateStep();
const expectedPayload = { type: updateStep};
expect(actions).toEqual([expectedPayload]);
});
I get the following error atm: TypeError: mockStore is not a function
When I try to upload the generated PDF file to storage bucket, the firebase logs gives me that response after log "Init upload of file...":
Function execution took 3721 ms, finished with status: 'connection
error'
Maybe the problem can be the order of Promises. But I'm beginner with Cloud Functions and Node.js to reorder that.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const pdf = require('html-pdf');
const gcs = require('#google-cloud/storage')({keyFilename: './service_account.json'});
const handlebars = require('handlebars');
const path = require('path');
const os = require('os');
const fs = require('fs');
const bucket = gcs.bucket(bucketURL);
admin.initializeApp(functions.config().firebase);
var html = null;
exports.generatePdf = functions.https.onRequest((request, response) => {
// data to apply to template file
const user = {
"date": new Date().toISOString(),
"title": "Voucher",
"body": "Voucher body"
};
const options = {
"format": 'A4',
"orientation": "portrait"
};
const localPDFFile = path.join(os.tmpdir(), 'localPDFFile.pdf');
try {
const source = fs.readFileSync(__dirname + '/voucher.html', 'utf8');
html = handlebars.compile(source)(user);
} catch (error) {
console.error(error);
}
const phantomJsCloud = require("phantomjscloud");
const browser = new phantomJsCloud.BrowserApi(phantomApiKey);
var pageRequest = { content: html, renderType: "pdf" };
// // Send our HTML to PhantomJS to convert to PDF
return browser.requestSingle(pageRequest)
.then(function (userResponse) {
if (userResponse.statusCode !== 200) {
console.log("invalid status code" + userResponse.statusCode);
} else {
console.log('Successfully generated PDF');
// Save the PDF locally
fs.writeFile(localPDFFile, userResponse.content.data, {
encoding: userResponse.content.encoding,
}, function (err) {
console.log('Init upload of file...' + localPDFFile);
// Upload the file to our cloud bucket
return bucket.upload(localPDFFile, {
destination: '/pdfs/voucher.pdf',
metadata: {
contentType: 'application/pdf'
}
}).then(() => {
console.log('bucket upload complete: ' + localPDFFile);
response.status(200).send({
message: 'PDF Gerado com sucesso!',
address: localPDFFile
});
return true;
}).catch(error => {
response.status(400).send({
message: 'Error on bucket upload!',
error: error
});
return false;
});
});
return true;
}
return true;
});
})