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