Project to do the first steps with Express and NodeJS. It has been developed following a midudev tutorial.
If you don't have any language interpreter installed in your computer, like me, you can use Docker to package, run and deploy your project. Create a simple Dockerfile from the official NodeJS image (please, use a Node.js LTS version).
FROM node:18
WORKDIR /usr/src/app
USER node
COPY --chown=node:node . .
EXPOSE 3000May be you will need some service in the future running in your project. Create a docker-compose.yml file to manage the services. You will need Docker compose installed too.
version: '3.8'
services:
app:
container_name: express-tinkering
build:
context: .
volumes:
- .:/usr/src/app
command: tail -f /dev/nullTake in consideration that the
volumesproperty is to mount the current directory in the container. This way you can edit the files in your computer and the changes will be reflected in the container. This is useful for development, but you should not use it in production. The command incommandsection is to keep the container running, so we can access it and prepare the project.
At this step we are now ready to set up the project. Run docker-compose up -d to build (if it's the first time) and start the container.
docker-compose up -dIf you want to check the container health, you can use the following command:
docker psUse docker logs express-tinkering to check the container logs if any problem.
Now we can access the container and init the project.
docker exec -it express-tinkering bashOnce we have the container running we can set up our express project.
Run npm init inside the container to create the package.json file. The -y flag is to skip the questions and use the default values.
After that, we can install the standard package to enforce a code style.
- The
-Dflag is to save the package as a development dependency. You will not need it in production. - And the
-Eflag is to save the package as an exact version.
npm init -y
npm install standard -DEEdit the package.json file to add the eslint config:
{
"dependencies": {
...
},
"eslintConfig": {
"extends": "standard"
}
}You will also need to configure standard in your IDE. If you are using Visual Studio Code, you can install the ESLint plugin.
Ensure your vscode setting json file is configured as follows:
{
...,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"[javascript]": {
"editor.formatOnSave": true
}
}Now we are going to install the express package and create the first server.
npm install express -EStop the container by running docker-compose down and edit the Dockerfile like this to install the dependencies. Since we have the package.json file we can install them every time we build the container.
FROM node:18
WORKDIR /usr/src/app
USER node
COPY --chown=node:node . .
RUN npm install
EXPOSE 3000Create a src/index.js file with the following content:
const express = require('express')
const app = express()
const PORT = process.env.PORT || 3000
app.get('/', (req, res) => {
res.send('Hello World')
})
app.use((req, res) => {
res.status(404).send('Not Found')
})
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`)
})Modify the package.json file to add the dev script to run the server in watch mode. This way the server will restart every time we change the code.
Change the main definition too.
{
"name": "express-tinkering",
"version": "1.0.0",
"main": "src/index.js",
"scripts": {
"dev": "node src/index.js --watch"
},
...
}Edit the docker-compose.yml file to map the port 3000 of the container to the port 3000 of the host machine. Modify the command property to run the server.
version: '3.8'
services:
app:
container_name: express-tinkering
build:
context: .
volumes:
- .:/usr/src/app
ports:
- 3000:3000
command: npm run devStart the container again with docker-compose up -d and access the server in your browser at http://localhost:3000.
Add the next line in src/index.js to prevent our api clients to know which technology and version is running the server.
app.disable('x-powered-by')If you want to use only JSONs to struct your input/output data ensure your api server knows it.
app.use(express.json())If you want to change the type of the project from commonjs (default) to a module, you can add the type property in the package.json file.
{
"type": "module",
...
}So now you can use the import and export statements in your code instead of require and module.exports.
Take in consideration that we did not need to specify the file extension in the require statement. Now we will need to do it.
Before:
const express = require('express')After:
import express from 'express'If you want to import a json file in your code, you can use the import statement. But you will need to specify the type of the file using with statement.
import data from './data.json' with { type: 'json' }Alternatively, if with it's not supported yet, you can use the fs module to read the file and parse it.
import fs from 'node:fs'
const data = JSON.parse(fs.readFileSync('./data.json', 'utf-8'))Also, you can use the createRequire function to import a module from a URL.
import { createRequire } from 'node:module'
const require = createRequire(import.meta.url)
const data = require('./data.json')