상세 컨텐츠

본문 제목

[Node.js] Node.js를 WebStorm 을 이용하여 ES6의 import, export 모듈화하여 개발 또는 모듈화 프로그래밍 관련

WEB/JavaScript

by AlrepondTech 2018. 10. 1. 12:30

본문

반응형

 

 

=================================

=================================

=================================

 

 

 

출처: https://medium.com/@oieduardorabelo/usando-es-modules-em-node-js-hoje-278ef1fd86bf

 

 

주의: ES6 -> import

 

import * as HTTP from "http";

 

이렇게 문법이 되는 모듈이 있고 안되는 모듈이 있다. 만약에 위와같이 했는데 안된다면

아래와 같이 해주면 된다.

 

import EXPRESS from "express";

import WS from "ws";

 

코드 넘어가서 확인해서 수정해되 되지만 귀찮을 경우 저렇게 해주면 왠간하면 된다,

 

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

// main.mjs
import express from "express";
const app = express();
app.get("/", (req, res) => res.json({ ok: true }));
app.listen(8080, () => console.log("ESM em com @std/esm"));

 

 

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

// main.mjs
import express from "express";
const service = () =>
  new Promise((res, rej) => {
    const start = Date.now();
    setTimeout(() => {
      const end = Date.now();
      res({
        ok: true,
        diff: end - start
      });
  }, 2000);
});

const app = express();

app.get("/", async (req, res) => {
  const data = await service();
  res.json(data);
});

app.listen(8080, () => console.log("ESM em com @std/esm"));

 

 

 

 

=================================

=================================

=================================

 

 

 

출처: https://medium.com/factory-mind/websocket-node-js-express-step-by-step-using-typescript-725114ad5fe4

 

Update

Checkout my new Angular WebSocket client article 😙.

You could be interested in my article about realtime and schemaless database (Cloud Firestore) and Angular -> Step by step tutorial and “CUD operations, transactions and batch writes deep dive”.


This is a quick step by step tutorial about WebSocket, Node/Express and Typescript. The full source code provided in these examples is lovely hosted by Github.

WebSocket is a communications protocol that provides a full-duplex communication channels over a single TCP connection established between a web browser (client) and a web server (this take place through the “classic HTTP mechanism” of handshaking, implemented using request/response headers).

This allows the server to send content to the browser without being called by the client, pushing data through the opened connection, defining ws and wss as URI schemes used respectively for unencrypted and encrypted connections.

In this tutorial we are going to use ws, a simple client/server library for Node.js that helps us to manage all the stuff under the protocol.

I choose this library instead of the well known Socket.IO because today the WebSocket protocol is natively supported in most major browsers (see the screenshot below) allowing to exclude all the overhead introduced by the several features of Socket.IO (see here for a head to head comparison).

Another useful thing that comes with the usage of HTTP concerns the possibility of use the “good old” Authorization header for Basic/Bearer Token Auth.

Now that we know a little more about what is hidden under the hood, let’s write some code.


First step

Let’s assume that we want to create a simple WebSocket server using Node.js and Express. Open your favorite console ad type the following commands (notice that this tutorial supposes that you have node installed on your machine: if it is not the case get it here:)

mkdir websocket-node-express
cd websocket-node-express
npm init
// add the details of your project
npm i ws express --save
// install the necessary types (and typescript)...
npm i typescript @types/ws @types/express -D
// ...optionally install typescript globally (tnx _Maxxx_)
npm i -g typescript

Now we can add some code to understand how it works. The minimal script in order to get a basic result is the following (copy it in src/server.ts):

 

import * as express from 'express';

import * as http from 'http';

import * as WebSocket from 'ws';

 

const app = express();

 

//initialize a simple http server

const server = http.createServer(app);

 

//initialize the WebSocket server instance

const wss = new WebSocket.Server({ server });

 

wss.on('connection', (ws: WebSocket) => {

 

    //connection is up, let's add a simple simple event

    ws.on('message', (message: string) => {

 

        //log the received message and send it back to the client

        console.log('received: %s', message);

        ws.send(`Hello, you sent -> ${message}`);

    });

 

    //send immediatly a feedback to the incoming connection    

    ws.send('Hi there, I am a WebSocket server');

});

 

//start our server

server.listen(process.env.PORT || 8999, () => {

    console.log(`Server started on port ${server.address().port} :)`);

 

It starts a new instance of a simple http server using express. Later we add the WebSocket server specifying a (fat arrow) function that will be triggered by the ‘connection’ event (line 13): it is responsible to handle all the incoming connections from clients.

In this case we immediately send back a welcome message (line 24), registering at the same time the ‘message’ event: this function will be called on every message sent by the client. Here we log the received message and then we send it back to the client (like an echo service — this time using the Typescript string interpolation ${}).

Ok let me see if it works…

Before that add a minimal tsconfig.json (we’re using Typescript, aren’t we?)

 

 

{

    "compilerOptions": {

        "target": "es6",

        "module": "commonjs",

        "outDir": "./dist/server",

        "strict": true,

        "sourceMap": true,

        "typeRoots": [

            "node_modules/@types"

        ]

    },

    "exclude": [

        "dist",

        "node_modules"

    ]

}

 

Open your terminal and type

// please compile my code
./node_modules/.bin/tsc    // or simply tsc (if installed globally)

// then run the server
node ./dist/server/server.js

 

 
반응형

 

728x90

 

You should get something like this in your console (here I’m on Windows10 using cmder and a simple bash extension).

 

 

 

Now it’s time to make some connection using a WebSocket test client: these screenshots come from Smart Websocket Client (an extension of Chrome from the Chrome Web Store).

 

 

Add the server address ws://localhost:8999, press connect and send a message.

 

 

 

The server logs the message sent by the client and return it back. Obviously now we can go on and create another client and see if the server can manage another incoming connection.

 

 

Going deeper — Broadcasting

Now that we are able to start our server let’s add some code to enable a new feature: message broadcasting.

Modify the code in server.ts substituting the 'message’ event with this new version:

 

//connection is up, let's add a simple simple event

    ws.on('message', (message: string) => {

 

        //log the received message and send it back to the client

        console.log('received: %s', message);

 

        const broadcastRegex = /^broadcast\:/;

 

        if (broadcastRegex.test(message)) {

            message = message.replace(broadcastRegex, '');

 

            //send back the message to the other clients

            wss.clients

                .forEach(client => {

                    if (client != ws) {

                        client.send(`Hello, broadcast message -> ${message}`);

                    }    

                });

            

        } else {

            ws.send(`Hello, you sent -> ${message}`);

        }

    });

 

The trick here is to fetch the request sent by a client in order to understand if it is a broadcast message (there are a lot of different ways to do this: sniffing headers, using a common message structure in json, etc… but let’s keep things simple, we’re not in production!).

Here I’m using a simple regex to figure out if this is a broadcast message and to remove the “label” from the message content.

If this is the case forward the message content to the other connected clients.

 

 

Bonus track — Handle broken connections

The link between the server and the client can be interrupted in a way that both are unaware of the broken state of the connection. To avoid this situation we can simply use ping messages to check if the client is still responsive.

 

 

wss.on('connection', (ws: ExtWebSocket) => {

 

    ws.isAlive = true;

 

    ws.on('pong', () => {

        ws.isAlive = true;

    });

 

    //connection is up, let's add a simple simple event

    ws.on('message', (message: string) => { 

        //[...]

    }

});

 

setInterval(() => {

    wss.clients.forEach((ws: ExtWebSocket) => {

        

        if (!ws.isAlive) return ws.terminate();

        

        ws.isAlive = false;

        ws.ping(null, false, true);

    });

}, 10000);

 

//start our server

server.listen(process.env.PORT || 8999, () => {

    console.log(`Server started on port ${server.address().port} :)`);

 

As you can see here we set ws.isAlive = true when the ‘connection’ starts, doing the same when the ‘pong’ event is called (more on this later).

Before the server startup we set an interval (10 seconds in this case) that checks if the client is alive:

  • if the value of isAlive is false we terminate the client connection;
  • if the value of isAlive is true, we set its value to false and then we execute a ping. Pings and Pongs are just regular frames, but they are specific control frames defined by the specs of WebSocket protocol in order to check if the remote endpoint is still connected. In this case we are setting the isAlive to false to understand if the client pong event sets it back to true, completing the connection check.

 

 

=================================

=================================

=================================

 

 

 

출처: https://qiita.com/masakielastic/items/8dd290780d2667c9e78a

 

2017年9月8日の Node.js 開発版から ES モジュールローダーを試すことができるようになりました。試験的な機能なので、スクリプトの実行時に --experimental-modules フラグを指定する必要があります。

公式マニュアル

Github の node/doc/api/esm.md をご参照ください。

NVS による開発版のインストール

開発版を手軽に試すには NVS (Node Version Swither) が手軽です。

nvs add nightly nvs use nightly 

正式な最新バージョンを導入するには次のコマンドを実行します。

nvs add latest nvs use latest 

モジュールをつくる

ES モジュールをつくってみましょう。拡張子を .mjs にする必要があります。

hello.mjs
const msg = "hello";  function hello() {   console.log(msg); }  export { msg, hello }; 

ES モジュールを読み込んで、実行するスクリプトの拡張子も .mjs にする必要があります。

main.mjs
import { msg, hello } from "./hello";  console.log(msg); hello(); 

実行

スクリプトを実行してみましょう。

node --experimental-modules main.mjs  (node:49617) ExperimentalWarning: The ESM module loader is experimental. hello hello 

実行するスクリプトの拡張子が .js の場合、次のようなエラーメッセージが表示されます。

node --experimental-modules main.js /Users/masakielastic/test/esm-project/main.js:1 (function (exports, require, module, __filename, __dirname) { import { msg, hello } from "./hello";                                                               ^^^^^^  SyntaxError: Unexpected token import     at createScript (vm.js:80:10)     at Object.runInThisContext (vm.js:139:10)     at Module._compile (module.js:564:28)     at Object.Module._extensions..js (module.js:611:10)     at Module.load (module.js:521:32)     at tryModuleLoad (module.js:484:12)     at Function.Module._load (module.js:476:3)     at Function.Module.runMain (module.js:641:10)     at startup (bootstrap_node.js:201:16)     at bootstrap_node.js:626:3 

読み込もうとするモジュールの拡張子が .js の場合、次のようなエラーメッセージが表示されます。

(node:49783) ExperimentalWarning: The ESM module loader is experimental. SyntaxError: The requested module does not provide an export named 'msg'     at checkComplete (internal/loader/ModuleJob.js:86:27)     at moduleJob.linked.then (internal/loader/ModuleJob.js:69:11)     at <anonymous> 

標準モジュールを読み込む

url モジュールの URLSearchParams を試してみましょう。

client.mjs
import url from "url";  const params = new url.URLSearchParams(); params.append("msg", "hello world");  console.log(params.toString()); // msg=hello+world 

記事の執筆時点では次の書き方はエラーになります。

import { URLSearchParams } from "url";  const params = new URLSearchParams(); console.log(params.toString()); // msg=hello+world 

エラーメッセージは次のとおりです。

SyntaxError: The requested module does not provide an export named 'URLSearchParams'     at checkComplete (internal/loader/ModuleJob.js:86:27)     at moduleJob.linked.then (internal/loader/ModuleJob.js:69:11)     at <anonymous> 

開発環境における代替策

開発環境でモジュールローダーを手軽に試したい場合の代替案が複数あります。

@std/esm

Node v4 から ESM を利用できるようにするツールです。スクリプトの実行時に r オプションで読み込みます。

node -r @std/esm main.mjs 

yarn で導入するには次のコマンドを実行できます。

yarn add --dev @std/esm 

babel-node と babel-preset-env

babel-preset-env のおかげでトランスパイルするコードの量を最小限に抑えることができます。

package.json
{   "babel": {     "presets": [       ["env", {"targets": { "node": "current" }}]     ]   } } 

Yarn による導入は次のとおりです。

yarn add --dev babel-cli babel-preset-env 

スクリプトの実行に npx を使うことができます。

npx babel-node client.mjs 

トランスパイルされたコードを見たいのであれば、babel コマンドを使います。

npx babel client.mjs

 

=================================

=================================

=================================

 

 

*기타관련링크

 

https://velopert.com/1492

 

 

 

 

 

=================================

=================================

=================================

 

 

 

 

 

 

반응형


관련글 더보기

댓글 영역