Anh Thang Bui Node.js Developer Something to remember...

Configure JavaScript, ESLint and Prettier in VSCode for development

This short guide will provide you a consistent and reuseable development workflow for your new or existing projects, especially in JavaScript. You can increase your code quality and reduce the time spent on debugging. I will show you how to configure VSCode to handle code formatting, linting and type checking now.

Testing is outside the scope, but it’s highly recommended. You should check every changed files before commit

You can skip ahead to the next step if you have any already

Getting Started

Open VSCode and install following extensions (what I shared in previous post, it’s here)

ESLint and Prettier Setup

Install following npm packages for your project as dev dependencies. I use yarn here, you can use npm i --save-dev instead

yarn add --dev eslint eslint-config-airbnb-base eslint-config-prettier eslint-plugin-import eslint-plugin-prettier husky lint-staged prettier
  • added eslint, prettier
  • added eslint-config-prettier so eslint and prettier won’t fight over code formatting rules
  • added eslint-config-airbnb-base to use Airbnb’s base JS .eslintrc as an extensible shared config. You can use other base like: StandardJS
  • Prettier will auto-format your code based on it’s rules. It’s amazingggg! 🤩 Let’s install and enjoy your life.

Open the .eslintrc.json file and configure it like so:

{
    "extends": ["airbnb-base", "prettier"],
    "plugins": ["import", "prettier"],
    "rules": {
        "eqeqeq": ["warn"],
        "radix": ["warn"],
        "newline-per-chained-call": ["warn"],
        "newline-before-return": "error",
        "no-restricted-syntax": ["warn"],
        "no-param-reassign": ["error", { "props": false }],
        "import/no-dynamic-require": ["warn"],
        "prettier/prettier": [
            "error",
            {
                "singleQuote": true,
                "semi": false,
                "tabWidth": 4
            }
        ]
    }
}

You can create a file name .prettierrc and write it own rules

{
    "singleQuote": true,
    "semi": false,
    "tabWidth": 4
}

This section is my preferences. You’re free to add your own rules.

Lint your Code

Add the following to package.json file

"husky": {
    "hooks": {
        "pre-commit": "lint-staged"
    }
}

Husky can prevent bad git commit, git push and more 🐶 woof!

"lint-staged": {
    "*.js": [
        "eslint --fix",
        "git add"
    ]
}

Run linters against staged git files and don’t let 💩 slip into your code base!

"scripts": {
    "start": "node src/app/app.js",
    "lint": "eslint src --ext .js,.tsx,.ts --fix"
}

With this lint script, you can run from the terminal (yarn lint or npm run lint) and enjoy fixing linter errors!

You can find more details about eslint options here

Prettier Formatter

Now I want VSCode to format my code following ESLint, Prettier config whenever I saving a file

Go to VSCode Preferences then add the following settings:

  • Set Prettier is default formatter and config for all JavaScript projects
{
    "prettier.semi": false,
    "prettier.singleQuote": true,
    "prettier.tabWidth": 4,
    "[javascript]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    }
}
  • Let VSCode always fix after saving a file
{
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
    }
}

Example

Before

before

After

after

🥳 Watch the magic of Prettier

Happy Coding~

VSCode extensions for developers

Visual Studio Code is a lightweight but powerful source code editor which runs on your desktop and is available for Windows, macOS and Linux. It comes with built-in support for JavaScript, TypeScript and Node.js and has a rich ecosystem of extensions for other languages (such as C++, C#, Java, Python, PHP, Go) and runtimes (such as .NET and Unity)

Here are my top VSCode extensions that every software developer must have:

  1. Better Comments

Improve your code commenting by annotating with alert, informational, TODOs, and more!

Better Comments

  1. Bracket Pair Colorizer 2

A customizable extension for colorizing matching brackets

Bracket

  1. ESLint

Integrates ESLint JavaScript into VS Code.

  1. gitflow

Forked from vector-of-bool/vscode-gitflow

Gitflow integration and support in Visual Studio Code

This is the only one with workspace support

gitflow

  1. Prettier - Code formatter

Prettier is an opinionated code formatter. It enforces a consistent style by parsing your code and re-printing it with its own rules that take the maximum line length into account, wrapping code when necessary.

  1. Prettify JSON

Prettify ugly JSON inside VSCode

  1. Settings Sync

Synchronize Settings, Snippets, Themes, File Icons, Launch, Keybindings, Workspaces and Extensions Across Multiple Machines Using GitHub Gist.

VSCode also has Preferences Sync, it still in preview and only available on Insiders. We can use this once moved to Stable.

  1. XML to JSON

Convert XML from clipboard or current document/selection to JSON

  1. XML Tools

XML Formatting, XQuery, and XPath Tools for Visual Studio Code

Some other extensions can help you increase your productivity:

  • Duplicate action - Ability to duplicate files in VS Code
  • Gitmoji Commit - A utility to compose GitHub commit messages with emojis. Based on Gitmoji.
  • Unique Lines - Keep unique lines of text and remove duplicates from current selection. Also includes a command to shuffle currently selected lines.

Happy Coding~

Dreaming keyboard layout

Updated: I ordered Canoe Gen2 - Homelander version, you can find it here: Percent Studio

Preferred features for my keyboard layout:

  • Polycarbonate
  • QMK with type C
  • RGB under glow

GB:

Think65

Full album: https://imgur.com/a/ZsSecSo

E6.5

Chimera65

Happy Hacking~

ingress-nginx controller not work for fanout configuration

Firstly, I want to says: Reading CHANGE_LOG will help you reduce the pain.

ingress-nginx has breaking changes from NGINX 0.22.0

Annotation nginx.ingress.kubernetes.io/rewrite-target has changed and will not behave as expected if you don't update them.

Refer to https://kubernetes.github.io/ingress-nginx/examples/rewrite/#rewrite-target on how to change it.

Refer to [#3174 (comment)](https://github.com/kubernetes/ingress-nginx/pull/3174#issuecomment-455665710) on how to do seamless migration.

From the documentation page at https://kubernetes.io/docs/concepts/services-networking/ingress/, you can define a fanout configuration routes traffic from a single IP address to more than one service, based on the HTTP URI being requested. An Ingress allows you to keep the number of loadbalancers down to a minimum.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
    name: simple-fanout-example
    annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /
spec:
    rules:
        - host: foo.bar.com
          http:
              paths:
                  - path: /foo
                    backend:
                        serviceName: service1
                        servicePort: 4200
                  - path: /bar
                    backend:
                        serviceName: service2
                        servicePort: 8080

However, it’s not work as expected if you have updated to the version 0.22.0 or newer. You need to change these annotations:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
    name: simple-fanout-example
    annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
    rules:
        - host: foo.bar.com
          http:
              paths:
                  - path: /foo/?(.*)
                    backend:
                        serviceName: service1
                        servicePort: 4200
                  - path: /bar/?(.*)
                    backend:
                        serviceName: service2
                        servicePort: 8080

Enjoy your time!

Running a Docker container as non-root user

By default, Docker container will be run as root user, this can cause us pain. We could tell Docker to run as an ordinary user instead of root.

We could build a Dockerfile like this:

FROM node:latest

# Add user so we dont run app as root
RUN groupadd -r node && useradd -r -g node node \
    && mkdir -p /home/node/<your-app-name> \
    && chown -R node:node /home/node

WORKDIR /home/node/<your-app-name>

COPY . .
RUN npm install

USER node
EXPOSE 3000

CMD ["npm", "start"]

Happy building v

Disable firewall in EC2 instance from AWS Console

I have locked myself out of SSH with UFW in EC2 AWS. Then, I can’t reconnect.

I found this script and it works with below steps:

  • Stop your problem instance
  • Paste this script in Instance Settings > View/Change User Data
Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0
--//
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"
#cloud-config
cloud_final_modules:
- [scripts-user, always]
--//
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"
#!/bin/bash
ufw disable
iptables -L
iptables -F
--//
  • Start your instance and now you should be able to SSH

Host ASP.NET Core on Linux with Nginx

This is a helper document guide how to setup, config and deploy an .NET Core Web Engine Hosting on an Ubuntu Server.

Access to Linux server

Run below command and input password

You can copy your local ssh key to server and no need password to login next time

ssh-copy-id -i .ssh/id_rsa [email protected]/ip

Install Nginx

sudo apt-get update
sudo apt-get install nginx

Since Nginx was installed for the first time, explicitly start it by running:

sudo systemctl start nginx

Config Nginx

To config Nginx as a reserve proxy to forward request to ASP.NET Core app, modify /etc/nginx/sites-available/default and replace or create a new sites-available

cd /etc/nginx/sites-available
touch site_name
sudo nano site_name

with the following contents

upstream site_name_svc  {
    server 127.0.0.1:5432;
}

server {
    server_name your_site_link;
    listen 80;

    root /usr/share/nginx/html;
    index index.html index.htm;

    location / {
        proxy_pass http://site_name_svc;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

This Nginx config file forwards incoming public traffic from port 80 to port 5432

Link your site to sites-enabled, then you can easy switch off site by remove syslink here and re-use again without re-config

sudo ln -s /etc/nginx/sites-available/kkday-test /etc/nginx/sites-enabled

Verify your config files

sudo nginx -t

If successful, reload Nginx to pickup the changes

sudo service nginx reload

Monitoring application

Use systemd and create a service file to start and monitor the underlying web app. systemd is an init system that provides many powerful features for starting, stopping, and managing processes.

Create service file

sudo nano /etc/systemd/system/service_name.service

and write the content like below

[Unit]
Description=Example .NET Web API Application running on Ubuntu

[Service]
WorkingDirectory=/path-to-your-app
ExecStart=/usr/bin/dotnet /path-to-your-app/working-file.dll
Restart=always
RestartSec=10  # Restart service after 10 seconds if dotnet service crashes
SyslogIdentifier=dotnet-example
User=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

[Install]
WantedBy=multi-user.target

Note: If the user www-data isn’t used by the configuration, the user defined here must be created first and given proper ownership for files.

Save the file and enable the service.

systemctl enable service_name.service

Start the service and verify that it’s running.

systemctl start service_name.service
systemctl status service_name.service

Now you can access your app from a browser on local machine via http://localhost

Minimal Docker container

With Docker multi stage, you can use multiple base image (call as builder) to build necessary files, assets and copy stuff over to final image after.

Here is some tricks:

  • You can use node:alpine, bitnami-docker-node or other smaller images if it’s enough to build your app.
  • Copy necessary files only
  • Base node docker image included yarn, it’s better some time (ex: build node-sass)

Example:

# node builder
FROM node:8.9.3 as nodebuilder
RUN mkdir publish
COPY gulpfile.js webpack.config.js package.json publish/
COPY ./Vue publish/Vue
COPY ./wwwroot publish/wwwroot
WORKDIR /publish

RUN cd /publish && yarn install \
    && yarn gulp all \
    && yarn run build

# dotnet builder
FROM microsoft/dotnet:2.0.0-sdk as builder
RUN mkdir publish
COPY . publish
WORKDIR publish
RUN dotnet restore <app_name>.csproj
RUN dotnet publish <app_name>.csproj --configuration Release --output ./out

# final image
FROM microsoft/dotnet:2.0.0-runtime
WORKDIR /dotnetapp
COPY --from=builder publish/out .
COPY --from=nodebuilder publish/wwwroot ./wwwroot
ENTRYPOINT ["dotnet", "<app_name>.dll"]

XML to JSON - VSCode extension

Convert XML from clipboard or current document/selection to JSON

Version Installs Downloads Rating

Are you using Code and working with XML builder tools day by day?

XML to JSON can help you create the final object, just edit the variables that need dynamic data instead of typing each object key, attribute and no typos mistake. Converted data can be use for xmlbuilder, xml2js or your expected format using configuration options.

Here are just some of the features that XML to JSON provides:

  • Convert XML from document or selection to JSON
  • Convert XML from clipboard to JSON

Property lookup on booleans

Performs a lot of dynamic lookups on the Boolean.prototype, as the ToBoolean operation let’s true pass for obj (which might itself be concerning that this can be a boolean). Instead of the coercion, the code should properly check for valid objects via typeof and strict equality with null comparison.

Example:

Use below

if (typeof obj === 'object' && obj !== null) {
    return obj[key] || 0
}

return 0

Instead of

return (obj && obj[key]) || 0

pino-redis - first contribution

Few months ago, I created a small project called pino-redis, a “transport” for the pino logger, receives pino logs from stdin and transform them into Redis.

Yesterday, I decided add it into official transports documentation via PR #307. And now, it was there.

It’s my first contribution to the open source community. You can find via npm or GitHub

Hello World! app with Node.js and Koa

Install Node.js for your platform

Open terminal and type

mkdir hello-world; cd hello-world

Initialize your project and link to npm

Running this command initializes your project:

npm init

This creates a package.json file in your hello-world app folder and will prompt you to enter number of things. You can enter your way through all of them EXCEPT this one:

entry point: (index.js)

You will want to change this to

<your_file_name>.js

Install Koa in the hello-world directory

npm i koa koa-router

--save is default option in node v8

Start your text editor and create a file named as entry point

const Koa = require('koa')
const Router = require('koa-router')

const app = new Koa()
const router = new Router()

router.get('/', (ctx) => {
    ctx.status = 200
    ctx.body = 'Hello, World'
})

app.use(router.routes())

app.listen(3000, () => {
    console.log('app listening on port 3000')
})

Run the app

node <your_file_name>.js

Cheers!