express

2021.10.26

Node.js Express configuration for React app

#express
use client /components/post/reExport , date: , tags: [ ], desc: , body: ( <> <H>Install</H> <ul> <li>Installation <Lnk path= >guide</Lnk></li> <li>In terminal <Code bash>npm i express</Code></li> </ul> <H>HTTP server</H> <Hs>Basic server</Hs> <Code block js>{ ) const app = express() const path = require( ) const PORT = process.env.PORT || 5000 app.listen(PORT, () => console.log(\ }</Code> <Hs>Static files</Hs> <Code block>{ ) app.use(express.static(path.join(__dirname, ), { index: false, extensions:[ ] // no need to put html extension })) app.use(express.static( )) // looks up files in the order static directories are set // manually serve files app.get( , (req, res) => res.sendFile(path.join(__dirname, index.html }</Code> <p>To start a server run <Code bash>node index.js</Code></p> <H>Hot restart</H> <ul> <li>Every update we do to our project files requires manual server restart with <kbd>Ctrl</kbd>+<kbd>C</kbd> & <Code bash>node index.js</Code></li> <li>To avoid it we may install <Lnk path= >nodemon</Lnk> tool and launch our server via it</li> <li>In terminal <Code bash>npm i -D nodemon</Code> to install the package as a development dependency</li> <li>Add into <code>package.json</code> following scripts</li> <Code block json>{ : { node index nodemon index }</Code> <li>Launch server via <Code bash>npm run dev</Code></li> <li>Now the server will be restarted automatically on every file update</li> </ul> <H>API documentation</H> <Lnk>https://expressjs.com/en/4x/api.html</Lnk> <H>Middleware</H> <ul> <li>Express is a routing and middleware web framework</li> <li>Express app is a series of middleware function calls</li> <li>Middleware functions can execute any code</li> <li>Can change the request or response objects</li> <li>End the request-response cycle</li> <li>Call the next middleware function in the stack</li> </ul> <H>app.use()</H> <ul> <li>Mounts the specified middleware function(s) at the specified path</li> <li>Middleware function is executed when the base of the requested path matches path.</li> </ul> <Hs>Middleware function parameters</Hs> <p>MW function has access to request & response objects and has the <Code>next</Code> function, which calls the next middleware function</p> <Code block>{ , (req, res, next) => { console.log( , req.method) next() }) const timeLogs = (req, res, next) => { console.log(\ )}\${req.originalUrl} on \${new Date().toString()}\ }</Code> <p>Every time the app receives a request, it prints the log message to the terminal</p> <Hs>Middleware in a separate file</Hs> <p>Add custom property to the request object</p> <Code block>{ added time to request object\ }</Code> <Code block>{ ./middleware/hitTime /checkAddedHitTimeToRequest }</Code> <p>Middleware function will be triggered when a user hit the url <Lnk>http://localhost:5000/checkAddedHitTimeToRequest</Lnk></p> <p>We can show this newly added object on the screen adding HTTP GET request route.</p> <Code block>{ /checkAddedHitTimeToRequest }</Code> <LazyImg path= /> <Hs>Middleware with parameters</Hs> <ul> <li>We can not pass parameters into a middleware function directly, because in <Code js>app.use()</Code> we have to pass only a reference to a middleware function</li> <li>That const mwWithOpt = (flag = true) => { return function (req, res, next) { if (flag) console.log( ) next() } } app.use(mwWithOpt(false)) in console, because we passed <code>false</code> param to a middleware function</li> <li>None of further middleware functions are triggered if <code>false</code> is passed, because <Code js>next()</Code> is never called</li> </ul> <H>next() vs next( )</H> <Hs>next()</Hs> <Code block>{ , (req, res, next) => { console.log( ) next() }, (req, res, next) => { console.log( ) next() } ) app.use(function(req, res, next) { console.log( ) next() }) app.get( , function(req, res, next) { console.log( /something_else ) next() }) app.get( , function(req, res, next) { console.log( ) next() }) app.get( ) - 01 app.get( ) - 02 app.use() - 03 app.get( ) - 05 )</Hs> <p><Code js>next( )</Code>passes control to the next matching route (GET, POST, PUT, DELETE methods).</p> <Code block>{ , (req, res, next) => { console.log( ) next( ) }, (req, res, next) => { console.log( ) next() } ) app.use(function(req, res, next) { console.log( ) next() }) app.get( , function(req, res, next) { console.log( /something_else ) next() }) app.get( , function(req, res, next) { console.log( ) next() }) app.get( ) - 01 app.use() - 03 app.get( ) - 05 app.get( , (req, res) => res.send( }</Code> <p>Hit <Lnk>http://localhost:5000/get</Lnk> and get rendered text on a screen.</p> <Hs>app.post()</Hs> <Code block>{ , (req, res) => res.send(hi }</Code> <p>We can make a post request from node file.</p> <Code block>{ ); axios.post( ) .then(function (response) { console.log(response.data); }) .catch(function (error) { console.log(error); }); s console and get the same result</p> <Code block>{ , { method: }) .then(response => response.text()) .then(msg => console.log(msg)) https://content-security-policy.com/ app.use(function(req, res, next) { res.header( default-src ) next() }) app.all( , (req, res, next) => { res.send( ) console.log( ) next() // pass control to the next handler }) app.all( , (req, res, next) => console.log( )) app.all( , (req, res, next) => console.log( )) app.get( , function (req, res, next) { console.log( ) next() }, function (req, res) { console.log( ) res.send( ) } ) const a = (req, res, next) => { console.log( ); next(); } const b = (req, res, next) => { console.log( ); next(); } const c = (req, res) => { console.log( ); res.send( ); } app.get( , [a, b, c]) app.get( , a, [b, c]) // http://localhost:5000/asdfhljljalasd73 app.get( /.*73$/, (req, res) => res.send( matching regexp /.*73$/</h1> , vehicle1: , vehicle2: } next() } ) // http://localhost:5000/users/34/books/8989 app.get( , (req, res) => res.send(req.params) // { } ) // hyphen (-) and the dot (.) are interpreted literally // http://localhost:5000/flights/LAX-SFO app.get( , (req, res) => res.send(req.params) // { } ) // regexp can be used in parentheses () // http://localhost:5000/user/42 app.get( , (req, res) => res.send(req.params) // { } ) app.route( ) .get((req, res, next) => res.send( )) .post((req, res) => res.send( )) .put((req, res) => res.send( }</Code> <H>Router</H> <p>We can extract routes and middlewares to a separate files with router objects.</p> <Code block>{ ) var animalRouter = express.Router() // middleware that is specific to this router animalRouter.use(function timeLog (req, res, next) { console.log( , Date.now()) next() }) // define the cats page route animalRouter.get( , (req, res) => res.send( )) // define the dogs page route animalRouter.get( , (req, res) => res.send( )) module.exports = animalRouter // index.js // load the router module in the app const routerAnimals = require( ) // http://localhost:5000/animals // http://localhost:5000/animals/dogs app.use( , routerAnimals) app.get( , (req, res) => res.json({id: 1, name: })) app.get( , (req, res) => res.send({id: 1, name: })) app.get( , (req, res) => res.send(Buffer.from( ))) app.get( , (req, res) => res.send( >some html</p> }</Code> <p>Note, it just returns partially rendered page, without styling. To enable styles need to adjust <Lnk path= >content-security-policy</Lnk>.</p> <Code block>{ Content-Security-Policy default-src ; style-src unsafe-inline ) next() }) /imgs/express/resSendHtmlString.png app.get( , (req, res) => res.status(404).send( )) app.get( , (req, res) => res.sendStatus(404)) app.get( , (req, res) => res.redirect(301, }</Code> <Hs>res.sendFile()</Hs> <ul> <li>Put file <code>/911.pdf</code> in the root folder</li> <li>File will be opened in the browser</li> <li>Same way can serve html files into the browser</li> </ul> <Code block>{ ) app.get( , (req, res) => { console.log(req.params) res.sendFile(path.join(__dirname, req.params.file)) }) app.get( , (req, res) => res.download( )) https://pugjs.org/api/getting-started.html http://expressjs.com/en/guide/using-template-engines.html // views\index.pug html head title= title body h1(style={ })= message app.set( ) app.get( , (req, res) => { res.render( , { title: , message: }) }) app.get( , (req, res) => res.status(404).end( color:red; }</Code> <Hs>res.set()</Hs> <p>Creates or replaces header</p> <Code block>{ ) res.set( ) res.set( ) res.set( check the response header Content-Type text/plain Content-Type text/plain Content-Length , ETag: }) next() }) app.get( , (req, res) => { res.append( ) res.append( ) res.append( ) res.append( check the response header }</Code> <H>POST request from html form and fetch</H> <Lnk>https://antonarbus.com/posts/post_requests</Lnk> <H>Serve React static folder from Express</H> <Code block js>{ ) const path = require( ) const app = express() const PORT = 3010 // React static files from folder app.use(express.static(path.join(__dirname, ))) // not needed, just an exampe, how to serve spcific file for the url app.get( , function (req, res) { res.sendFile(path.join(__dirname, index.html , (req, res) => { res.sendFile(path.join(__dirname, index.html Server started on port \${PORT}\ }</Code> <H>Route from React to Express APIs</H> <Code block jsx>{ ) const app = express() app.get( , (req, res) => { res.json({ message: }) }) app.listen(3001, () => { console.log( ) }) // app.js import React from function App () { const [data, setData] = React.useState(null) React.useEffect(() => { fetch( ) .then((res) => res.json()) .then((data) => setData(data.message)) }, []) return ( <> <p>{!data ? : data}</p> </> ) } export default App { quotation.app , : true, : { , , , , , , , , , }, : { react-scripts start react-scripts build react-scripts test , react-scripts eject nodemon server.js concurrently \ npm run client\ }, : { : [ , ] }, : { : [ , , ], : [ , , ] }, : { , , , , , }, http://localhost:3001