avatarLukas Wimhofer

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

6735

Abstract

ass="hljs-keyword">as</span> dotenv <span class="hljs-keyword">from</span> <span class="hljs-string">'dotenv'</span>; <span class="hljs-keyword">import</span> express <span class="hljs-keyword">from</span> <span class="hljs-string">'express'</span>; <span class="hljs-keyword">import</span> cors <span class="hljs-keyword">from</span> <span class="hljs-string">'cors'</span>; <span class="hljs-keyword">import</span> helmet <span class="hljs-keyword">from</span> <span class="hljs-string">'helmet'</span>;</pre></div><p id="0f46">Under the <code>App Variables</code> section, we load any environmental variables from the local <code>.env</code> file using the <code>dotenv.config()</code> method and we assign the port variable from <code>process.env</code> to <code>port</code>:</p><div id="0071"><pre><span class="hljs-comment">// App Variables</span>

dotenv.<span class="hljs-title function_">config</span>();

<span class="hljs-keyword">const</span> port = process.<span class="hljs-property">env</span>.<span class="hljs-property">PORT</span>;</pre></div><p id="a533">Under the <code>App Configuration</code> section, we create an instance of an express application, mount the middleware functions and add a basic route:</p><div id="3c19"><pre><span class="hljs-comment">// App Configuration</span>

<span class="hljs-keyword">const</span> app = <span class="hljs-title function_">express</span>();

app.<span class="hljs-title function_">use</span>(<span class="hljs-title function_">helmet</span>()); app.<span class="hljs-title function_">use</span>(<span class="hljs-title function_">cors</span>()); app.<span class="hljs-title function_">use</span>(express.<span class="hljs-title function_">json</span>());

app.<span class="hljs-title function_">get</span>(<span class="hljs-string">'/'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =></span> { res.<span class="hljs-title function_">send</span>(<span class="hljs-string">'Hello World!'</span>) })</pre></div><blockquote id="9985"><p><a href="https://helmetjs.github.io/"><code>hel</code>met</a> is a collection of 14 small middleware functions that set HTTP response headers. Mounting <code>helmet()</code> doesn't include all of these middleware functions but provides you with <a href="https://www.npmjs.com/package/helmet#how-it-works">sensible defaults</a> such as <a href="https://helmetjs.github.io/docs/dns-prefetch-control/">DNS Prefetch Control</a>, <a href="https://helmetjs.github.io/docs/frameguard/">Frameguard</a>, <a href="https://helmetjs.github.io/docs/hide-powered-by/">Hide Powered-By</a>, <a href="https://helmetjs.github.io/docs/hsts/">HSTS</a>, <a href="https://helmetjs.github.io/docs/ienoopen/">IE No Open</a>, <a href="https://helmetjs.github.io/docs/dont-sniff-mimetype/">Don't Sniff Mimetype</a>, and <a href="https://helmetjs.github.io/docs/xss-filter/">XSS Filter</a>.</p></blockquote><blockquote id="69f5"><p>By mounting <code>cors()</code>, you enable all CORS requests.</p></blockquote><blockquote id="ad39"><p>With <code>express.json()</code>, you parse incoming requests with JSON payloads, which populates the <code>request</code> object with a new <code>body</code> object containing the parsed data.</p></blockquote><p id="8921">Finally, under the <code>Server Activation</code> section, we start the express server:</p><div id="39c9"><pre><span class="hljs-comment">// Server Activation</span>

app.<span class="hljs-title function_">listen</span>(port, <span class="hljs-function">() =></span> { <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">Listening on port <span class="hljs-subst">${port}</span></span>); });</pre></div><p id="29d5">The final <code>index.ts</code> file should look like this:</p><div id="3f34"><pre><span class="hljs-comment">// Required External Modules</span>

<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> dotenv <span class="hljs-keyword">from</span> <span class="hljs-string">'dotenv'</span>; <span class="hljs-keyword">import</span> express <span class="hljs-keyword">from</span> <span class="hljs-string">'express'</span>; <span class="hljs-keyword">import</span> cors <span class="hljs-keyword">from</span> <span class="hljs-string">'cors'</span>; <span class="hljs-keyword">import</span> helmet <span class="hljs-keyword">from</span> <span class="hljs-string">'helmet'</span>;

<span class="hljs-comment">// App Variables</span>

dotenv.<span class="hljs-title function_">config</span>();

<span class="hljs-keyword">const</span> port = process.<span class="hljs-property">env</span>.<span class="hljs-property">PORT</span>;

<span class="hljs-comment">// App Configuration</span>

<span class="hljs-keyword">const</span> app = <span class="hljs-title function_">express</span>();

app.<span class="hljs-title function_">use</span>(<span class="hljs-title function_">helmet</span>()); app.<span class="hljs-title function_">use</span>(<span class="hljs-title function_">cors</span>()); app.<span class="hljs-title function_">use</span>(express.<span class="hljs-title function_">json</span>());

app.<span class="hljs-title function_">get</span>(<span class="hljs-string">'/'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =></span> { res.<span class="hljs-title function_">send</span>(<span class="hljs-string">'Hello World!'</span>) })

<span class="hljs-comment">// Server Activation</span>

app.<span class="hljs-title function_">listen</span>(port, <span class="hljs-function">() =></span> { <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">Listening on port <span class="hljs-subst">${port}</span></span>); }); </pre></div><h1 id="2236">Dev Script</h1><p id="ed7e">Another development-related utility library we are using is nodemon. It helps develop Node.js based applications by automatically restarting the nodejs application when file changes in the directory are detected.</p><p id="7f8d">We also need ts-node, which is a TypeScript execution engine and REPL for Node.js. It JIT transforms TypeScript into JavaScript, enabling you to directly execute TypeScript on Node.js without precompiling.</p><p id="7c06">Add nodemon and ts-node as dev dependency:</p><div id="704a"><pre>npm i -D nodemon ts-node</pre></div><p id="1dcc">Now we can customise nodemon by creating a <code>nodemon.json</code> file in our project directory. At this time we do not need some of the configurations, but we can still use the following code for a basic setup:</p><div id="a79d"><pre><span class="hljs-punctuation">{</span> <spa

Options

n class="hljs-attr">"watch"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span> <span class="hljs-string">"src"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">".env"</span> <span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"ext"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"js,ts,json"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"ignore"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span> <span class="hljs-string">"src/logs/"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"src/**/.{spec,test}.ts"</span> <span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"exec"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"ts-node --transpile-only src/index.ts"</span> <span class="hljs-punctuation">}</span></pre></div><p id="e134">In order to use nodemon with the configuration we just created, create a <code>dev</code> npm script in <code>package.json</code> to run your server:</p><div id="5684"><pre> <span class="hljs-attr">"scripts"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">"dev"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"nodemon"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span></pre></div><p id="95e4">Now we can use the <code>dev</code> script to check if the installation is working so far:</p><div id="81fe"><pre>npm run dev</pre></div><p id="c3a5">If you see “Listening on Port…” in the console, everything is working so far.</p><h1 id="bc00">Build Script</h1><p id="071c">Next we have to add the build script to our <code>package.json</code> file. We can also add a start script:</p><div id="aa1e"><pre><span class="hljs-attr">"build"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"tsc"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"start"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"npm run build && node dist/index.js"</span></pre></div><p id="4177">Node.js assumes it’s always running in a development environment. You can signal Node.js that you are running in production by setting the <code>NODE_ENV=production</code> environment variable. In case you want to use conditional statements to execute code in different environments, we can also adapt our dev script. However it depends on your operating system.</p><p id="1770">For Linux and Mac:</p><div id="c797"><pre><span class="hljs-attr">"dev"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"NODE_ENV=development nodemon"</span> <span class="hljs-attr">"build"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"tsc"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"start"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"npm run build && NODE_ENV=production node dist/index.js"</span></pre></div><p id="6ce6">For Windows we also need to install the following:</p><p id="ab5a"><b>Option 1:</b></p><div id="d942"><pre>npm install -g win-node-env</pre></div><p id="6e8a"><b>Option 2:</b></p><div id="b4f7"><pre>npm i -D cross-env</pre></div><p id="747a">When choosing option 2 we need to edit our scripts:</p><div id="7ada"><pre><span class="hljs-attr">"dev"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"cross_env NODE_ENV=development nodemon"</span> <span class="hljs-attr">"build"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"tsc"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"start"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"npm run build && cross-env NODE_ENV=production node dist/index.js"</span></pre></div><p id="3528">The last step of this part of the series is to check if our setup is working. Try each of the following commands one after the other:</p><div id="2755"><pre>npm run dev

npm run build

npm run start</pre></div><h1 id="f989">Finish</h1><p id="aa56">We have successfully created a basic nodejs, express project with typescript. In the next part of this series, we continue by adding additional tools. We will cover some new modules as well as tools that help us improve our development workflow.</p><p id="d6f0"><b>Content of the next part:</b></p><ul><li>Advanced Configuration</li><li>Path Aliases</li><li>Environment Variable Validation</li><li>Optional: SWC</li><li>ESLint + Prettier</li><li>Optional: Husky</li></ul><p id="123a">Go ahead and check out the next part of this series, which is all about evolving our Basic Project Starter to an Advanced Project Starter:</p><div id="1d16" class="link-block"> <a href="https://readmedium.com/api-development-with-nodejs-express-and-typescript-from-scratch-advanced-project-starter-2632afd09e22"> <div> <div> <h2>API development with nodejs, express and typescript from scratch — Advanced Project Starter</h2> <div><h3>This is the second part of the series “API development with nodejs, express and typescript from scratch” and it is all…</h3></div> <div><p>medium.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/1*W4M5bkkF5myqgVI-9t_ZDg.png)"></div> </div> </div> </a> </div><p id="32a7">If you find this tutorial helpful, feel free to clap and follow me to stay up to date with all the articles from myself. More tutorials and insights are on the way.</p><p id="f381">If you want to get unlimited, ad-free access to all the stories on Medium, you can subscribe by using my referral link below :)</p><div id="1ac6" class="link-block"> <a href="https://medium.com/@wimluk/membership"> <div> <div> <h2>Join Medium with my referral link — Lukas Wimhofer</h2> <div><h3>Get unlimited, ad-free access to all the stories on Medium. Your membership fee directly supports Lukas Wimhofer and…</h3></div> <div><p>medium.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*GaqpcdcIB5uEcPBS)"></div> </div> </div> </a> </div></article></body>

API development with nodejs, express and typescript from scratch — Project Starter

This is the first part of the series “API development with nodejs, express and typescript from scratch” and it is all about starting the project.

We will cover the following steps:

  • Prerequisites
  • Getting Started
  • Basic Configuration
  • Server Setup
  • Dev and Build Script

Prerequisites

Before we can start our project, we have to install Node.js®, which is an open-source, cross-platform JavaScript runtime environment. By installing nodejs, make sure that you are also installing npm, which is a package manager. Other options are yarn or pnpm, however, we are going to use npm in this series.

We are also using VSCode as editor, but feel free to use any code editor you like.

Follow the link below and install Node.js® on your machine:

Getting Started

Start by creating a new project directory anywhere on your system and open the directory in your code editor.

Next, open the terminal and initialize a nodejs project within the project directory with the following command. This will initialize the project and create a package.json file:

npm init -y

After the initialization, we can install a couple of dependencies, that we need, to create a secure express server.

npm i express dotenv cors helmet

Express is the web framework that we are going to use.

Dotenv is a zero-dependency module that loads environment variables from a .env file into process.env.

CORS is a node.js package for providing a Connect/Express middleware that can be used to enable CORS with various options.

Helmet helps you secure your Express apps by setting various HTTP headers. “It’s not a silver bullet, but it can help!”

To use TypeScript, we also need to install a stable version of typescript as developer dependency. We can also go ahead and install type definitions for the packages that we installed previously:

npm i -D typescript @types/node @types/express @types/dotenv @types/cors @types/helmet

When a package doesn’t have built-in types, you can get its type definitions through the @types npm namespace, which hosts TypeScript type definitions from the DefinitelyTyped project. Once you install the packages, the TypeScript compiler automatically includes the types, and your IDE can use them to provide you with code assistance.

Configuration

Next we want to generate a basic tsconfig.json file in our project directory. Generate it by using the following command:

npx tsc --init

We will customize this file in the advanced section. For now, open it, uncomment and edit baseURL and outDir like this:

"baseUrl": "src",
"outDir": "dist",

Instead of using hard-coded configuration variables in our files, we are creating a .env file, where we can define all of our sensitive variables.

Enter the following variable in our .env file to define the port your server can use to listen for requests:

PORT=3000

If you are using git, we have to make sure that unnecessary files or files that contain sensitive information are not pushed to github. Let’s create a .gitignore file and start by adding the following lines to it:

/node_modules
.env

Server Setup

Create a src directory inside your project and a new file called index.ts that serves as the entry point to our application. At this point, your project structure should look like this:

src/
  index.ts
.env
.gitignore
package-lock.json
package.json
tsconfig.json

The index.ts file can be structured into the following parts:

  • Required External Modules
  • App Variables
  • App Configuration
  • Server Activation

Let’s start with the first part and import the project dependencies that we installed earlier:

// Required External Modules

import * as dotenv from 'dotenv';
import express from 'express';
import cors from 'cors';
import helmet from 'helmet';

Under the App Variables section, we load any environmental variables from the local .env file using the dotenv.config() method and we assign the port variable from process.env to port:

// App Variables

dotenv.config();

const port = process.env.PORT;

Under the App Configuration section, we create an instance of an express application, mount the middleware functions and add a basic route:

// App Configuration

const app = express();

app.use(helmet());
app.use(cors());
app.use(express.json());

app.get('/', (req, res) => {
  res.send('Hello World!')
})

helmet is a collection of 14 small middleware functions that set HTTP response headers. Mounting helmet() doesn't include all of these middleware functions but provides you with sensible defaults such as DNS Prefetch Control, Frameguard, Hide Powered-By, HSTS, IE No Open, Don't Sniff Mimetype, and XSS Filter.

By mounting cors(), you enable all CORS requests.

With express.json(), you parse incoming requests with JSON payloads, which populates the request object with a new body object containing the parsed data.

Finally, under the Server Activation section, we start the express server:

// Server Activation

app.listen(port, () => {
  console.log(`Listening on port ${port}`);
});

The final index.ts file should look like this:

// Required External Modules

import * as dotenv from 'dotenv';
import express from 'express';
import cors from 'cors';
import helmet from 'helmet';

// App Variables

dotenv.config();

const port = process.env.PORT;

// App Configuration

const app = express();

app.use(helmet());
app.use(cors());
app.use(express.json());

app.get('/', (req, res) => {
  res.send('Hello World!')
})

// Server Activation

app.listen(port, () => {
  console.log(`Listening on port ${port}`);
});

Dev Script

Another development-related utility library we are using is nodemon. It helps develop Node.js based applications by automatically restarting the nodejs application when file changes in the directory are detected.

We also need ts-node, which is a TypeScript execution engine and REPL for Node.js. It JIT transforms TypeScript into JavaScript, enabling you to directly execute TypeScript on Node.js without precompiling.

Add nodemon and ts-node as dev dependency:

npm i -D nodemon ts-node

Now we can customise nodemon by creating a nodemon.json file in our project directory. At this time we do not need some of the configurations, but we can still use the following code for a basic setup:

{
    "watch": [
        "src",
        ".env"
    ],
    "ext": "js,ts,json",
    "ignore": [
        "src/logs/*",
        "src/**/*.{spec,test}.ts"
    ],
    "exec": "ts-node --transpile-only src/index.ts"
}

In order to use nodemon with the configuration we just created, create a dev npm script in package.json to run your server:

  "scripts": {
    "dev": "nodemon"
  },

Now we can use the dev script to check if the installation is working so far:

npm run dev

If you see “Listening on Port…” in the console, everything is working so far.

Build Script

Next we have to add the build script to our package.json file. We can also add a start script:

"build": "tsc",
"start": "npm run build && node dist/index.js"

Node.js assumes it’s always running in a development environment. You can signal Node.js that you are running in production by setting the NODE_ENV=production environment variable. In case you want to use conditional statements to execute code in different environments, we can also adapt our dev script. However it depends on your operating system.

For Linux and Mac:

"dev": "NODE_ENV=development nodemon"
"build": "tsc",
"start": "npm run build && NODE_ENV=production node dist/index.js"

For Windows we also need to install the following:

Option 1:

npm install -g win-node-env

Option 2:

npm i -D cross-env

When choosing option 2 we need to edit our scripts:

"dev": "cross_env NODE_ENV=development nodemon"
"build": "tsc",
"start": "npm run build && cross-env NODE_ENV=production node dist/index.js"

The last step of this part of the series is to check if our setup is working. Try each of the following commands one after the other:

npm run dev

npm run build

npm run start

Finish

We have successfully created a basic nodejs, express project with typescript. In the next part of this series, we continue by adding additional tools. We will cover some new modules as well as tools that help us improve our development workflow.

Content of the next part:

  • Advanced Configuration
  • Path Aliases
  • Environment Variable Validation
  • Optional: SWC
  • ESLint + Prettier
  • Optional: Husky

Go ahead and check out the next part of this series, which is all about evolving our Basic Project Starter to an Advanced Project Starter:

If you find this tutorial helpful, feel free to clap and follow me to stay up to date with all the articles from myself. More tutorials and insights are on the way.

If you want to get unlimited, ad-free access to all the stories on Medium, you can subscribe by using my referral link below :)

Web Development
Programming
Expressjs
Typescript
API
Recommended from ReadMedium