ノードの基本、npm とパッケージ、Express ミドルウェアの入門

Node.js

1 Node.js の概要

Node.js は、Chrome V8 エンジンに基づく JavaScript ランタイム環境です。

ブラウザは JavaScript のフロントエンド ランタイム環境です。

Node.js は JavaScript のバックエンド ランタイム環境です。

DOM や BOM などのブラウザーの組み込み API は、Node.js では呼び出すことができません。

ブラウザでの JavaScript ラーニング パス:
JavaScript の基本構文 + ブラウザ組み込み API (DOM + BOM) + サードパーティ ライブラリ (jQuery、アート テンプレートなど)

Node.js 学習パス:
JavaScript の基本構文 + Node.js 組み込み API モジュール (fs、path、http など) + サードパーティ API モジュール (express、mysql など)

2 fs ファイルシステムモジュール

2.1 fs ファイルシステムモジュールとは

fs 模块これはファイルを操作するために Node.js によって公式に提供されているモジュールであり、一連のメソッドとプロパティを提供します。

例えば:

fs.readFile() メソッド。读取ファイルの内容を指定するために使用されます。

fs.writeFile() メソッドは、指定されたファイルの写入内容を書き込むために使用されます。

インポートファイル:

const fs = require('fs');

2.2读取ファイルの内容を指定する

1 fs.readFile() 構文形式。

fs.readFile( path[,options], callback);

パラメータの解釈: 角括弧 [] で囲まれたパラメータはオプションのパラメータです。

パラメータ 1: 必須パラメータ、文字列、表現文件的路径

パラメータ 2:编码格式ファイルの読み取り対象を示すオプションのパラメータ。

パラメータ 3: 必須パラメータ。ファイルが読み取られた後、コールバック関数を通じて取得されます读取的结果

2 fs.readFile() サンプルコード。

指定されたファイルの内容をutf8エンコード形式で読み取り、errとdataStrの値を出力します。

// 1 引入 fs 模块
const fs = require("fs");

// 2 调用 fs.readFile() 方法读取文件
fs.readFile("./files/1.txt", "utf8", (err, res) => {
    
    
  console.log("err", err); // 失败的结果
  console.log("res", res); // 成功的返回值
});

// 如果读取成功,则 err 的值为 null
// 如果读取失败,则 err 的值为 错误对象,res 的值为 undefined

2.3指定したファイルに写入コンテンツを追加する

1 fs.writeFile() 構文形式。

fs.writeFile(file, data[, options], callback)

パラメータの解釈:

パラメータ 1: 必須パラメータ。ファイルのストレージ パスを示すファイル パスの文字列を指定する必要があります。(パスに該当するファイルが存在しない場合は、新規ファイルを作成して内容を書き込みます。)

パラメータ 2: 必須パラメータ。 Yes を意味します写入的内容

パラメータ 3: ファイルの内容を書き込む形式を示すオプションのパラメータ。デフォルト値は utf8 です。

パラメータ 4: 必須パラメータ、ファイル書き込み後のコールバック関数

2 fs.writeFile() サンプルコード。

// 1 引入 fs 模块
const fs = require("fs");

// 2 调用 fs.writeFile() 方法读取文件
fs.writeFile("./files/2.txt", "222txt内容", (err) => {
    
    
  console.log("err", err);
});

// 如果写入成功,则 err 的值等于 null  
// 如果写入失败,则 err 的值等于一个 错误对象

2.4 事例

ファイルの読み取り、データの処理、ファイルの書き込み。

// 1 引入 fs 模块
const fs = require("fs");

// 2 调用 fs.readFile() 方法读取文件
fs.readFile("./files/成绩.txt", "utf8", (err, res) => {
    
    
  // 3 判断是否读取成功
  if (err) {
    
    
    return console.log("读取文件失败!", err);
  }

  // 4 读取文件成功后
  // 4.1 先把成绩的数据,按照空格进行分割
  const data = res.split(" ");

  // 4.2 将 = 替换 :
  const data2 = data.map((item) => item.replace("=", ":"));

  // 4.3 再将新数组中的每一项,进行合并,得到新的字符串 \r\n 表示换行的意思
  const str = data2.join("\r\n");

  //   5 调用 fs.writeFile() 方法,把处理完的数据写入到新的文件中
  fs.writeFile("./files/成绩2.txt", str, (err) => {
    
    
    if (err) {
    
    
      return console.log("写入文件失败!", err);
    }
    console.log("写入成功!");
  });
});

2.5 fs モジュール - パスの動的スプライシングの問題

fs モジュールを使用してファイルを操作する場合、指定された操作パスが ./ または .../ で始まる場合相对路径、パスの動的スプライシング エラーが発生しやすくなります。

理由: コードの実行中、ノード コマンドが実行されるディレクトリに基づいて、操作対象ファイルのフル パスが動的に結合されます。

解決策: fs モジュールを使用してファイルを操作する場合は、直接提供完整的路径動的パスのスプライシングの問題を防ぐために、./ または .../ で始まる相対パスを指定しないでください。

それは、ドライブレターから書き込みを開始することです。

const fs = require("fs");

fs.readFile("C:\\Users\\blank\\Desktop\\2022node\\代码笔记\\files\\1.txt", "utf8", (err, res) => {
    
    
  console.log("err", err);
  console.log("res", res);
});

欠点: 可搬性が悪く、メンテナンスが容易ではありません。

より良い解決策:__dirname現在のファイルが存在するディレクトリを指定します。

const fs = require("fs");

fs.readFile(__dirname + "/files/1.txt", "utf8", (err, res) => {
    
    
  console.log("err", err);
  console.log("res", res);
});

3パスパスモジュール

3.1 パスパスモジュールとは

パスモジュールは处理路径Node.jsが提供する公式モジュールを使用します。これは、ユーザーのパスの処理要件を満たす一連のメソッドと属性を提供します。

例えば:

path.join() メソッド、結合に使用されます多个路径片段拼接成一个完整的路径字符串

path.basename() メソッドは、パス文字列からファイル名を解析するために使用されます。

パスモジュールをインポートします。

const path = require('path');

3.2 パスの結合 path.join()

path.join()このメソッドは、複数のパス フラグメントを完全なパス文字列に連結できます。

文法形式:

path.join([...paths]);

パラメータの解釈:

...パス フラグメントのパス シーケンス。任意の数を指定できます。

戻り値:

コード例:

const path = require("path");
const fs = require("fs");

// 注意:../ 会抵消前面的路径
const pathStr = path.join("/a", "/b/c", "../", "./d", "e");
console.log(pathStr); // 一组 "../" 即抵消前面一个路径 \a\b\d\e

const pathStr2 = path.join("/a", "/b/c", "../../", "./d", "e");
console.log(pathStr2); // 两组 "../" 即抵消前面两个个路径 \a\d\e

// fs.readFile(__dirname + "./files/1.txt", "utf8", (err, res) => {
    
    

fs.readFile(path.join(__dirname, "/files/1.txt"), "utf8", (err, res) => {
    
    
  console.log("err", err);
  console.log("res", res);
});

3.3 パス内のファイル名を取得 path.basename()

path.basename()パスの最後の部分を取得することができ、パス内のファイル名はこの方法で取得されることが多いです。

構文形式は次のとおりです。

path.basename(path[, ext]);

パラメータの解釈:

path は必須パラメータであり、パスを表す文字列です。

ext ファイル拡張子を示すオプションのパラメータ。2 番目のパラメータが渡された場合、戻り値には拡張子は含まれません。

戻り値: パスの最後の部分を示します

コード例:

const path = require("path");

// 定义文件的存放路径
const fpath = '/a/b/c/index.html'

const fullName = path.basename(fpath);
console.log('包含扩展名',fullName); // 包含扩展名 index.html

const nameWithoutExt = path.basename(fpath,'.html');
console.log('不包含扩展名',nameWithoutExt); // 不包含扩展名 index

3.4 パス内の拡張子を取得 path.extname()

path.extname()メソッドを使用すると、パスを取得できます扩展名部分

構文形式は次のとおりです。

path.extname(path)

パラメータの解釈:

path は必須パラメータであり、パスを表す文字列です。

戻り値: 取得した拡張文字列を返します。

コード例:

const path = require("path");

// 定义文件的存放路径
const fpath = '/a/b/c/index.html'

const fext = path.extname(fpath);
console.log('文件扩展名',fext); // .html

3.5 包括的なケース


4 つの http モジュール

4.1 httpモジュールとは

ネットワーク ノードでは、リソースの消費を担当するコンピュータはクライアントと呼ばれ、
ネットワーク リソースを外部に提供する担当のコンピュータはサーバーと呼ばれます。

http 模块Node.js が公式に创建 web 服务器提供している。http モジュールによって提供されるhttp.createServer()メソッド、通常のコンピュータを Web サーバーに簡単に変えて、Web リソース サービスを外部の世界に提供できます。

http モジュールをインポートします。

const http = require('http');

4.2 http モジュールの役割を理解する

サーバーと通常のコンピューターの違いは、IIS、Apache などのWeb サーバー ソフトウェアがサーバーにインストールされていることです。これらのサーバーソフトウェアをインストールすることで、通常のコンピューターをWebサーバーに変えることができます。

Node.js では、IIS や Apache などのサードパーティ Web サーバー ソフトウェアを使用する必要はありません。Node.js が提供する http モジュールに基づいて、
数行の単純なコードを使用してサーバー ソフトウェアを手動で簡単に作成し、外部の世界に Web サービスを提供できるからです

4.3 サーバー関連の概念

1 IPアドレス

IP アドレスはインターネット上の各コンピューターの一意のアドレスであるため、IP アドレスは一意です。「IPアドレス」は、「パソコン」を「電話機」に例えると「電話番号」に相当し、相手のIPアドレスがわかっていて初めて、対応するパソコンとデータ通信を行うことができます。

IP アドレスの形式: 通常は「ドット付き 10 進数」の (abcd) の形式で、a、b、c、d はすべて 0 ~ 255 の 10 進整数です。例: IP アドレスをドット付き 10 進数で表現した場合 (192.168.1.1)

注:
インターネット上のすべての Web サーバーには独自の IP アドレスがあります。たとえば、Windows ターミナルで ping www.baidu.com コマンドを実行すると、Baidu サーバーの IP アドレスを表示できます。

② 開発期間中は、お使いのコンピュータがサーバーとしてもクライアントとしても機能しますが、テストの便宜上、ブラウザに IP アドレス 127.0.0.1 を入力して、お使いのコンピュータをサーバーとしてアクセスすることができます。

2 ドメイン名とドメインネームサーバー

IP アドレスはネットワーク上のコンピュータを一意にマークできますが、IP アドレスは一連の長い数字であり、直観的ではなく覚えにくいため、人々は別の文字ベースのアドレス スキーム、いわゆるドメイン名を発明しました。 (ドメイン名) . ) アドレス.

IP アドレスとドメイン名の間には 1 対 1 の対応関係があり、この対応関係はドメイン ネーム サーバー( DNS、ドメイン ネーム サーバー) と呼ばれるコンピュータに保存されます。ユーザーは覚えやすいドメイン名で対応するサーバーにアクセスするだけでよく、対応する変換作業はドメイン名サーバーによって実現されます。したがって、ドメイン ネーム サーバーは、IP アドレスとドメイン名の間の変換サービスを提供するサーバーです。

注:
① インターネット上のコンピュータも、IP アドレスを使用するだけで正常に動作します。しかし、ドメイン名の恩恵により、インターネットの世界はさらに便利になります。
② 開発およびテスト期間中、127.0.0.1に対応するドメイン名はlocalhostであり、すべて私たちのコンピュータを表しており、使用効果に違いはありません。( 127.0.0.1 === ローカルホスト )

3ポート番号

コンピュータのポート番号は、現実の家の番号のようなものです。家番号を介して、テイクアウト ブラザーは建物全体の多くの部屋にテイクアウトを正確に届けることができます。

同様に、数百または数千の Web サービスを 1 台のコンピュータ上で実行できます。各 Web サービスは一意のポート番号に対応します。クライアントから送信されたネットワーク リクエストは、ポート番号を介して対応する Web サービスに正確に渡されて処理されます。

注:
① 各ポート番号を複数の Web サービスで同時に占有することはできません。
② 実際のアプリケーションでは、URL のポート 80 は省略できます

4.4 Webサーバーの作成

1 基本的な手順:

① http モジュールをインポートします。
② Web サーバー インスタンスを作成します。
③ リクエスト イベントをサーバー インスタンスにバインドし、クライアントのリクエストをリッスンします
。 ④ サーバーを起動します。

// 1 导入 http 模块
const http = require("http");

// 2 创建 web 服务器实例
const server = http.createServer();

// 3 为服务器实例绑定 request 事件,监听客户端的请求
server.on("request", function (req, res) {
    
    
  console.log("Someone visit our web server.");
});

// 4 启动服务器
server.listen(8080, function () {
    
    
  console.log("server runing at http://127.0.0.1:8080");
});

2reqリクエストオブジェクト

サーバーは、クライアントのリクエストを受信する限り、server.on()を通じてサーバーにバインドされたリクエスト イベント処理関数を呼び出します。

イベント ハンドラーでクライアントに関連するデータまたはプロパティにアクセスする場合は、次のメソッドを使用できます。

// req 是请求对象,包含了与客户端相关的数据和属性
server.on("request", (req) => {
    
    
  const {
    
     url, method } = req;
  console.log('客户端请求的 URL 地址',url);
  console.log('客户端的 method 请求类型',method);
});

3res応答オブジェクト

サーバーのリクエスト イベント ハンドラーで、サーバー関連のデータまたは属性にアクセスする場合は、次のメソッドを使用できます。

res.end()

server.on("request", (req, res) => {
    
    
  const {
    
     url, method } = req;
  const str = `客户端请求的URL地址为:${
      
      url},客户端的请求类型为:${
      
      method}`;
  
  res.end(str); // res.end() 方法的作用:向客户端发送指定的内容,并结束这次请求的处理过程。
});

4 中国語の文字化け問題を解決する

res.end() メソッドを呼び出して中国語のコンテンツをクライアントに送信すると、文字化けが発生します。このとき、コンテンツのエンコード形式を手動で設定する必要があります。

res.setHeader(“Content-Type”, “text/html; charset=utf-8”);

server.on("request", (req, res) => {
    
    
  const {
    
     url, method } = req;
  const str = `客户端请求的URL地址为:${
      
      url},客户端的请求类型为:${
      
      method}`;

  // 为了防止中文显示乱码的问题,需要设置响应头 Content-Type 的值为 text/html;charset=utf-8
  res.setHeader("Content-Type", "text/html; charset=utf-8"); // 固定写法
  res.end(str); 
});

5 異なる URL に従って異なる HTML コンテンツに応答する

主要な実装手順:
要求された URL アドレス
を取得します。 ② デフォルトの応答コンテンツを404 Not found
に設定します。 ③ ユーザーが要求したのが/ または /index.htmlホームページである
かどうかを判断します。 ④ ユーザーが要求したのが/about.html about ページであるかどうかを判断します
。 ⑤中国語の文字化けを防ぐため、Content -Typeレスポンスヘッダを設定する
res.end()を使用してコンテンツをクライアントに応答する

const http = require("http");
const server = http.createServer();

server.on("request", function (req, res) {
    
    
  // 1 获取请求的 url 地址
  const {
    
     url } = req;
  // 2 设置默认的内容为 404 Not Found
  let content = "<h1>404 Not Found!</h1>";

  // 3 根据 url 确定要显示的内容
  if (url === "/" || url === "/index.html") {
    
    
    content = "<h1>index页面</h1>";
  } else if (url === "/about.html") {
    
    
    content = "<h1>about页面</h1>";
  }

  res.setHeader("Content-Type", "text/html; charset=utf-8");
  res.end(content);
});

server.listen(80, function () {
    
    
  console.log("server runing at http://127.0.0.1");
});


5 モジュラー

5.1 モジュール性の概念

1 モジュール性とは

プログラミング分野におけるモジュール化とは、固定ルールに従い、大きなファイルを独立かつ相互依存する複数の小さなモジュールに分割することです。つまり、複雑な問題は小さなモジュールに分割されて処理されます。

モジュール分割コードの利点:

コードの再利用性の向上

コードの保守性の向上

オンデマンドローディングを実現可能

2 モジュール仕様

モジュール仕様とは、コードをモジュール化して組み合わせるときに従う必要があるルールです。

例: モジュールを参照するためにどのような文法形式が使用されているか、およびモジュール内のメンバーを公開するためにどのような文法形式が使用されているか

モジュラー仕様の利点:

誰もが同じモジュール仕様に準拠してコードを作成するため、通信コストが削減され、モジュール間の相互呼び出しが大幅に促進され、他の人にも自分自身にも利益がもたらされます。

5.2 node.js のモジュール性

1 node.js におけるモジュール性の分類

node.js では、モジュールはモジュールのさまざまなソースに応じて 3 つのカテゴリに分類されます。

組み込みモジュール: fs、path、http など、node.js 公式 Web サイトによって提供されます。

カスタム モジュール: ユーザーが作成したすべての .js ファイルはカスタム モジュールです。

サードパーティ モジュール: サードパーティによって開発されたモジュールは、公式の組み込みモジュールでもユーザーが作成したカスタム モジュールでもないため、使用前にダウンロードする必要があります。

2 ロードモジュール

強力なrequire()メソッド、使用するために必要なモジュールをロードできます。例えば:

// 1 加载内置的 fs 模块
const fs = require('fs');

// 2 加载用户定义的自定义模块(需要通过路径) 
const custom = require('./custom.js');
const custom = require('./custom');//可以省略.js后缀名

// 3 加载第三方模块 
const moment = require('moment');

注: require() メソッドを使用して他のモジュールをロードすると、ロードされたモジュール内のコードが実行されます。

3 Node.jsのモジュールスコープ

関数スコープと同様に、カスタム モジュールで定義された変数、メソッド、およびその他のメンバーには、現在のモジュール内でのみアクセスできます。この種のモジュール レベルのアクセス制限は、モジュール スコープと呼ばれます

モジュール スコープの利点: グローバル変数汚染の問題を防止します。

4 共有モジュールのスコープ外のメンバー

(1) モジュールオブジェクト

各 .js カスタム モジュールにはモジュール オブジェクトがあり、現在のモジュールに関連する情報が保存されます。

Module {
    
    
  id: '.',
  path: 'C:\\Users\\blank\\Desktop\\2022node\\代码笔记',
  exports: {
    
    },
  filename: 'C:\\Users\\blank\\Desktop\\2022node\\代码笔记\\10 module.js',
  loaded: false,
  children: [],
  paths: [
    'C:\\Users\\blank\\Desktop\\2022node\\代码笔记\\node_modules',
    'C:\\Users\\blank\\Desktop\\2022node\\node_modules',
    'C:\\Users\\blank\\Desktop\\node_modules',
    'C:\\Users\\blank\\node_modules',
    'C:\\Users\\node_modules',
    'C:\\node_modules'
  ]
}
(2) module.exports オブジェクト

カスタム モジュールでは、外部使用のためにmodule.exportsOutward。デフォルトでは、 module.exports は空のオブジェクトと等しくなります。

外部がrequire()このメソッドカスタム モジュールをインポートすると、取得されるのは module.exports が指すオブジェクトです。

カスタムコンポーネント:

// 在一个自定义模块中,默认情况下,module.exports === {}

// 向 module.exports 对象上挂载 username 属性
module.exports.username = "小徐";

// 向 module.exports 对象上挂载 sayHello 方法
module.exports.sayHello = function () {
    
    
  console.log("Hello!");
};

const age = 24;
module.exports.age = age;

外部受信コンポーネント:

// 在外界使用 require 导入一个自定义的模块的时候,得到的成员就是,那个模块中
// 通过 module.exports 指向的那个对象

const zhidingyi = require("./11 自定义模块");

console.log(zhidingyi);// { username: '小徐', sayHello: [Function (anonymous)], age: 24 }

(3) メンバーを共有する際の注意点

require() メソッドを使用してモジュールをインポートする場合、インポートの結果は常に module.exports が指すオブジェクトに基づきます。

// 在一个自定义模块中,默认情况下,module.exports === {}

// 向 module.exports 对象上挂载 username 属性
module.exports.username = "小徐";

// 向 module.exports 对象上挂载 sayHello 方法
module.exports.sayHello = function () {
    
    
  console.log("Hello!");
};

const age = 24;
module.exports.age = age;

// 让 module.exports 指向一个全新的对象。
// 也就是在该文件中,最后输出的对象是下面最后指向的对象
module.exports = {
    
    
    nikename:'香香',
    sayHi(){
    
    
        console.log('Hi! xx');
    }
}

(4) エクスポートオブジェクト

module.export という単語は記述が複雑であるため、共有コードを簡素化するために、node はexportsobject を。

デフォルトでは、exports と module.exports は同じオブジェクトを指します

最終的な共有結果は、依然として module.exports が指すオブジェクトに基づいています。

module.exports.username = "小徐";

exports.username = "小徐";

// 二者作用相同
(5) エクスポートおよび module.exports の悪用

モジュールを require() すると、常に module.exports が指すオブジェクトを取得することに注意してください。

export.username = 'xiaoxu';
module.exports = {
    
    
    gender: 'nan',
    age: 22
}

// 最终输出的对象是 
{
    
     
    gender: 'nan',
	age: 22
}
module.exports.username = 'xiaoxu';
export = {
    
    
    gender: 'nan',
    age: 22
}

// 最终输出的对象是 
{
    
     
    username: 'xiaoxu',
}
exports.username = 'xiaoxu';
module.exports.gender = 'nan';

// 最终输出的对象是 
{
    
     
    username: 'xiaoxu',
	gender: 'nan'
}
export = {
    
    
    username: 'xiaoxu',
    gender: 'nan',
}
module.exports = exports;
module.exports.age = 22

// 最终输出的对象是 
{
    
     
    username: 'xiaoxu',
	gender: 'nan',
    age: 22
}

注:混乱を避けるため、同じモジュール内でexportsとmodule.exportsの両方を使用しないようにしてください。

5 Node.js のモジュール仕様

node.js はCommonJS モジュール、 CommonJS はモジュールの特性とモジュール間の相互依存性を指定します

CommonJS では次のように述べられています。

(1) 各モジュール内で、モジュール変数は現在のモジュールを表します。

(2) モジュール変数はオブジェクトであり、そのエクスポート属性 (つまり、module.exports) は外部インターフェイスです。

(3) モジュールのロードは、実際にはターゲット モジュールの module.exports プロパティをロードします。require() メソッドはモジュールをロードするために使用されます。


6 npm とパッケージ

6.1パッケージ

1 パッケージとは

node.js のサードパーティ モジュールは と呼ばれます

2つのソースパック

Node.js の組み込みモジュールやカスタム モジュールとは異なり、パッケージはサードパーティの個人またはチームによって開発され、誰でも無料で使用できます。

: Node.js のパッケージはすべて無料のオープンソースであり、料金を支払わなくても無料でダウンロードして使用できます。

3 なぜパッケージが必要なのか

Node.js の組み込みモジュールは一部の低レベル API しか提供していないため、組み込みモジュールに基づくプロジェクト開発の効率は非常に低くなります。

パッケージは組み込みモジュールに基づいてカプセル化され、より高度で便利な API を提供し、開発効率を大幅に向上させます。

パッケージと組み込みモジュールの関係は、jQuery とブラウザー組み込み API の関係に似ています。

4パッケージをダウンロードする場所

海外にnpm, Inc.というIT企業があります。この会社には非常に有名なウェブサイトがあります: https://www.npmjs.com/ は世界最大の荷物共有プラットフォームであり、このウェブサイトから必要なバッグを検索できます。十分な忍耐力がある限り!

これまでに、世界中の 1,100 万人以上の開発者が、このパッケージ共有プラットフォームを通じて、私たちが使用するために 120 万個以上のパッケージを開発し、共有してきました。

npm, Inc. は 、すべてのパッケージを外部と共有するために https://registry.npmjs.org/ というアドレスのサーバーを提供しており、このサーバーから必要なパッケージをダウンロードできます。

知らせ:

  • https://www.npmjs.com/ Web サイトから必要なパッケージを検索します。

  • https://registry.npmjs.org/ サーバーから必要なパッケージをダウンロードします。

5パッケージのダウンロード方法

npm, Inc. は パッケージ管理ツールを提供しており、このパッケージ管理ツールを使用して、ローカルで使用するために必要なパッケージを https://registry.npmjs.org/ サーバーからダウンロードできます。

このパッケージ管理ツールの名前は Node Package Manager (略して npm パッケージ管理ツール) であり、このパッケージ管理ツールは Node.js インストール パッケージとともにユーザーのコンピューターにインストールされます。

ターミナルでnpm -vコマンドを実行すると、コンピューターにインストールされている npm パッケージ管理ツールのバージョン番号を確認できます。

6.2npm

指定したパッケージをインストールする 1 つのコマンド

npm install 包的完整名称

// 简写
npm i 包的完整名称

2 初期パッケージ化後に追加されるファイル

初期パッケージ化が完了すると、プロジェクト フォルダーの下に、node_modules というフォルダーと構成ファイル package-lock.json が作成されます。

の:

node_modules文件夹プロジェクトにインストールされたすべてのパッケージを保存するために使用されますrequire() がサードパーティのパッケージをインポートする場合、このディレクトリからパッケージを検索してロードします。

package-lock.json配置文件これは、パッケージ名、バージョン番号、ダウンロード アドレスなどの各パッケージのダウンロード情報を node_modules ディレクトリに記録するために使用されます。

注: プログラマーは、node_modules または package-lock.json ファイル内のコードを手動で変更しないでください。これらは、npm パッケージ管理ツールによって自動的に保守されます。

3 指定したバージョンのパッケージをインストールします

デフォルトでは、npm install コマンドを使用してパッケージをインストールすると、パッケージの最新バージョンが自動的にインストールされますパッケージの特定のバージョンをインストールする必要がある場合は、パッケージ名の後ろに@ 記号を使用して特定のバージョンを指定できます。次に例を示します。

npm i moment@2.22.2

4 パッケージのセマンティック バージョニング仕様

パッケージのバージョン番号は、 2.24.0のように、合計 3 桁の「ドット 10 進数」の形式で定義されます。

各桁の意味は次のとおりです。

1桁目:大きいバージョン

2桁目:機能バージョン

3桁目:バグ修正バージョン

バージョン番号昇格のルール: 以前のバージョン番号が増加する限り、次のバージョン番号は 0 にリセットされます。

6.3 パッケージ管理設定ファイル

Npm では、プロジェクトのルート ディレクトリに、というパッケージ管理構成ファイルを提供する必要があると規定しています。package.json

プロジェクトに関連するいくつかの構成情報を記録するために使用されます。例えば:

  • プロジェクトの名前、バージョン番号、説明など。

  • プロジェクトで使用されるパッケージ

  • 開発中にのみ使用されるパッケージはどれですか

  • これらのパッケージは開発と展開の両方に必要です

1 多人数コラボレーションの問題

複数人でのコラボレーションで発生する問題:サードパーティのパッケージが大きすぎて、チーム メンバー間でプロジェクトのソース コードを共有するのが不便です。

解決策: 共有時にnode_modulesを削除します。

2 プロジェクトにインストールされているパッケージを記録する方法

プロジェクトのルート ディレクトリに、 というファイルを作成しますpackage.json 的配置文件このファイルは、プロジェクトにインストールされているパッケージを記録するために使用できます

これにより、node_modules ディレクトリを削除した後、チーム メンバー間でプロジェクトのソース コードを簡単に共有できるようになります。

: 今後のプロジェクト開発では、node_modules フォルダーを .gitignore 無視ファイルに必ず追加してください。

3 package.jsonを素早く作成する

npm パッケージ管理ツールには、コマンドが実行されるディレクトリに
パッケージ管理構成ファイルpackage.json をすばやく作成するためのショートカット コマンドが用意されています。

// 作用:在执行命令所在目录中,快速新建 package.json 文件
npm init -y

// 执行该命令的时机,是在新建好项目文件夹的时候,不要开始写任何代码,第一步要做的任务就是执行该命令,而且这个命令在项目中只需要执行一次就够了,目的就是创建package.json文件。

知らせ:

  • 上記のコマンドは、英語のディレクトリでのみ正常に実行できますしたがって、プロジェクト フォルダーの名前は中国語ではなく英語で付ける必要があり、スペースを含めることはできません。

  • npm install コマンドを実行してパッケージをインストールすると、npm パッケージ管理ツールはパッケージ名とバージョン番号をpackage.json に自動的に記録します。

4 つの依存関係ノード

package.json ファイルには、npminstall コマンドを使用してインストールしたパッケージを記録するために特別に使用される依存関係ノードがあります。

5 すべてのパッケージを一度にインストールする

node_modules を除外するプロジェクトを取得した場合、プロジェクトを実行する前に、すべてのパッケージをプロジェクトにダウンロードする必要があります。

それ以外の場合は、次のようなエラーが報告されます。

// 由于项目运行依赖于moment这个包,如果没有提前安装好这个包,就会报一下错误
Error: Cannot find module 'moment'

npm installコマンド(または npmi) を実行して、すべての依存関係を一度にインストールできます。

// 执行 npm install 命令时,npm 包管理工具会先读取 package.json 中的 dependencies 节点。
// 读取到记录的所有依赖包名称和版本号之后,npm 包管理工具会把这些包一次性下载到项目中。
npm install

6 パッケージをアンインストールする

npm uninstallコマンドを実行して、指定したパッケージをアンインストールできます。

// 使用 npm uninstall 具体的报名,来卸载包
npm uninstall moment

注: npm uninstall コマンドが正常に実行されると、アンインストールされたパッケージは package.json の依存関係から自動的に削除されます。

7 devDependcise ノード

一部のパッケージがプロジェクト開発段階でのみ使用され、プロジェクトがオンラインになった後は使用されない場合は、これらのパッケージを devDependency ノードに記録することをお勧めします。

同様に、開発およびプロジェクトの開始後に一部のパッケージを使用する必要がある場合は、これらのパッケージを依存関係ノードに記録することをお勧めします。

次のコマンドを使用して、パッケージを devDependency ノードに記録できます。

// 安装指定的包,并记录到 devDependcise 节点中
npm i 报名 -D

// 注意:上述命令是简写形式,等价于下面完整的写法
npm  install 报名 --save-dev

6.4 ダウンロード速度が遅い問題を解決する

1 ダウンロード速度が遅いのはなぜですか

npmを利用してパッケージをダウンロードする場合、デフォルトでは海外のhttps://registry.npmjs.org/サーバーからダウンロードされますが、この際ネットワークデータの伝送には長い海底光ケーブルを経由する必要があるため、ダウンロードは速度は非常に遅くなります。

拡張読書 - 海底ケーブル:

2 タオバオ NPM ミラー サーバー

タオバオは中国にサーバーを設置し、海外公式サーバー上のパッケージを国内サーバーに同期し、中国国内でパッケージをダウンロードするサービスを提供しています。これにより、ダウンロード速度が大幅に向上します。

拡大:

ミラーリングはファイル ストレージの一種で、あるディスク上のデータは別のディスクに同一のコピーを保持します。

3 npmのダウンロードミラーソースを切り替える

ダウンロードしたパッケージのイメージソースは を参照します下包的服务器地址

// 查看当前的下包镜像源
npm config get registry

// 将下包的镜像源切换为淘宝镜像源
npm config set registry=https://registry.npm.taobao.org/

4nrm

パッケージのイメージ ソースをより便利に切り替えるには、小さなツールnrm をインストールし、nrm が提供するターミナル コマンドを使用して、パッケージのイメージ ソースをすばやく表示して切り替えることができます。

// 通过 npm 包管理器,将 nrm 安装为全局可用的工具
npm i nrm -g

// 查看所有可用的镜像源
nrm ls

// 将下包的镜像源切换为 taobao 镜像
nrm use taobao

6.5 パッケージの分類

npm パッケージ管理ツールを使用してダウンロードされたパッケージは、 、 の 2 つのカテゴリに分類され项目包ます全局包

アイテムパック1個

プロジェクトの node_modules ディレクトリにインストールされるパッケージはプロジェクト パッケージです。

プロジェクト パッケージは、次の 2 つのカテゴリに分類されます。

  • 开发依赖包(devDependency ノードに記録されたパッケージは開発中にのみ使用されます)

  • 核心依赖包(依存関係ノードに記録されたパッケージは、開発中およびプロジェクトがオンラインになった後に使用されます)

npm i 包名 -D  	// 开发依赖包
npm i 包名		// 核心依赖包

2つのグローバルパッケージ

npm install コマンドを実行するときに、-gパラメーターが、パッケージは としてインストールされます全局包

グローバル パッケージは、C:\Users\user directory\AppData\Roaming\npm\node_modules ディレクトリにインストールされます。

npm i 包名 -g			// 安装指定的包到全局
npm uninstall 包名 -g	// 指定卸载全局安装的包

知らせ:

  • ツールのようなパッケージのみをグローバルにインストールする必要があります。便利な端末コマンドが提供されるからです。

  • パッケージを使用する前にグローバルにインストールする必要があるかどうかを判断するには、公式の使用説明書を参照してください。

3 i5ting_toc

i5ting_toc は、MD ドキュメントを HTML ページに変換できる小さなツールです。手順は次のとおりです。

// 将 i5ting_toc 安装为全局包
npm install -g i5ting_toc

// 调用 i5ting_toc 轻松实现 md 转 HTML 的功能。-o 表示转换完成后自动在浏览器打开 
i5ting_toc -f 要转换的md文件的路径 -o

6.6 正規のパッケージ構造

パッケージの概念とそれをダウンロードして使用する方法を明確にした後、パッケージの内部構造を詳しく見てみましょう。

標準化されたパッケージとその構成構造は、次の 3 つの要件を満たしている必要があります。

  • ① パッケージが单独的目录存在

  • ② パッケージ管理設定ファイルはpackage.jsonパッケージ

  • ③ package.json には、それぞれパッケージを表すname,version,mainこれら名字、版本号、包的入口

注: 上記の 3 つの要件は、標準化されたパッケージ構造が準拠する必要がある形式です。その他の制約については、次の URL を参照してください。

https://yarnpkg.com/zh-Hans/docs/package-json

6.7 npm でパッケージを公開する

1 npmアカウントを登録する

①https://www.npmjs.com/ Webサイトにアクセスし、サインアップボタンをクリックして登録ユーザーインターフェースに入ります。

② アカウント関連情報を入力します: フルネーム、公開メールアドレス、ユーザー名、パスワード

③「アカウント作成」ボタンをクリックしてアカウントを登録します。

④メールにログインし、認証リンクをクリックしてアカウントを認証します。

2 npmアカウントにログインします

npmアカウントの登録が完了したら、ターミナルでnpmloginコマンドを実行し、ユーザー名、パスワード、メールアドレスを順に入力するとログインに成功します。

**注意:**npm login コマンドを実行する前に、まずパッケージのサーバー アドレスを npm の公式サーバーに切り替える必要があります。そうしないと、リリース パッケージが失敗します。

3 パッケージを npm に公開します

ターミナルをパッケージのルート ディレクトリに切り替えた後、npm public コマンドを実行して、パッケージを npm に公開します (注: パッケージ名は同じであってはなりません)。

4 公開されたパッケージを削除する

npm unpublish 包名 --forceコマンドを実行して、公開されたパッケージを npm から削除します。

知らせ:

①npm unpublishコマンドは72時間以内に公開されたパッケージのみ削除できます

②npm unpublishで削除されたパッケージは24時間以内は再公開できません

③パッケージを公開するときは注意し、無意味なパッケージを npm 上に公開しないようにしてください


7 モジュールローディング機構

7.1 キャッシュからのロードを優先する

模块在第一次加载后会被缓存これは、複数の呼び出しによってモジュールのコードが複数回実行されることrequire()がないこと。

注: 組み込みモジュール、ユーザー定義モジュール、サードパーティ モジュールのいずれであっても、それらは最初にキャッシュからロードされるため、提高模块的加载效率.

7.2 内蔵モジュールのロード機構

組み込みモジュールは、Node.js によって公式に提供されるモジュールです内置模块的加载优先级最高

たとえば、require('fs') は、node_modules ディレクトリに fs という同じ名前のパッケージがある場合でも、常に組み込みの fs モジュールを返します。

7.3 カスタムモジュールのロードメカニズム

require() を使用してカスタム モジュールをロードする場合は、 ./ または .../ で始まるパス識別子を指定する必要があります。

カスタム モジュールをロードするときに、./ や .../ などのパス識別子が指定されていない場合、ノードはそれを組み込みモジュールまたはサードパーティ モジュールとしてロードします。

同時に、require()を使用してカスタムモジュールをインポートするときに、ファイル拡張子が省略されている場合、

次に、Node.js は按顺序次のファイルをそれぞれロードしようとします。

①に従って确切的文件名負荷をかける

.js拡張機能てロードする

.json拡張機能てロードする

.node拡張ロードする

⑤ロードに失敗し、端末がエラーを報告しました

7.4 サードパーティモジュールのロードメカニズム

require() に渡されたモジュール識別子が組み込みモジュールではなく、「./」または「.../」で始まらない場合、Node.js は現在のモジュールの親ディレクトリから開始し、そこからロードしようとします。 /node_modules フォルダーのサードパーティ モジュール。

対応するサードパーティ モジュールが見つからない場合は、次の親ディレクトリに移動し、ファイル システムのルート ディレクトリまでロードします。

たとえば、require('tools') が 'C:\Users\xiaoxu\project\foo.js' ファイルで呼び出されると仮定すると、Node.js は次の順序で検索します。

① C:\Users\xiaoxu\project\node_modules\tools

② C:\Users\xiaoxu\node_modules\tools

③ C:\Users\node_modules\tools

④ C:\node_modules\tools

7.5 モジュールとしてのディレクトリ

ロードのためにディレクトリをモジュール識別子として require() に渡す場合、ロード方法は 3 つあります。

①ロードされたディレクトリでpackage.jsonというファイルを見つけ、require()ロードのエントリとしてmain属性を探します。

②ディレクトリ内にpackage.jsonファイルが存在しない場合、またはメインエントリが存在しないか解析できない場合、Node.jsはディレクトリ内のindex.jsファイルをロードしようとします。

③上記の 2 つの手順が失敗した場合、Node.js はターミナルにエラー メッセージを出力し、モジュールが存在しないことを報告します: エラー: モジュール 'xxx' が見つかりません


8 エクスプレス

8.1 Express の概要

1 エクスプレスとは

公式から与えられたコンセプト:Express 是基于 Node.js 平台,快速、开放、极简的 Web 开发框架

一般的な理解: Express の機能は Node.js の組み込み http モジュールに似ており、特に Web サーバーの作成に使用されます。

Express の本質: これは、Web サーバーを迅速に作成する便利な方法を提供する npm 上のサードパーティ パッケージです。

Express の中国語公式 Web サイト: http://www.expressjs.com.cn/

2 Express についてのさらなる理解

感想: Express を使用せずに Web サーバーを作成できますか?

回答: はい、Node.js が提供するネイティブ http モジュールを使用できます。

考察: Ji Shengyu と He Shengliang (http モジュールが組み込まれているのに、なぜ依然として Express を使用するのですか)?

回答: http 組み込みモジュールは使用が非常に複雑で、開発効率が低くなりますExpress 是基于内置的 http 模块进一步封装出来的,能够极大的提高开发效率

考察: http 組み込みモジュールと Express の間にはどのような関係があるのでしょうか?

回答: ブラウザーにおける Web API と jQuery の関係に似ています。後者は前者に基づいてさらにカプセル化されます。

3 Expressでできること

フロントエンド プログラマにとって、最も一般的なサーバーは次の 2 つです。

  • Web 网站服务器: Web ページのリソースを外部に提供する専用のサーバー。

  • API 接口服务器: 外部に API インターフェースを提供するサーバー。

Express を使用すると可以方便、快速的创建 Web 网站的服务器或 API 接口的服务器

8.2 Expressの基本的な使い方

1 インストール

プロジェクトが存在するディレクトリで、次のターミナル コマンドを実行して、Express をプロジェクトにインストールします。

npm i express@4.17.1

2 基本的な Web サーバーを作成する

// 1 导入 express
const express = require('express')

// 2 创建 web 服务器
const app = express()

// 3 启动 web 服务器
app.listen(80,()=>{
    
    
    console.log('express server runing at http://127.0.0.1');
})

3 GET リクエストをリッスンします

app.get()メソッド。クライアントの GET リクエストを監視できます。

文法形式:

// 参数1:客户端请求的 URL 地址
// 参数2:请求对应的处理函数
// req:请求对象(包含了与请求相关的属性与方法)
// res:响应对象(包含了与响应相关的属性与方法)

app.get('请求URL', (req, res) => {
    
    
    ... 处理函数
})

4 POSTリクエストをリッスンする

app.post()メソッド。クライアントの POST リクエストを監視できます。

文法形式:

// 参数1:客户端请求的 URL 地址
// 参数2:请求对应的处理函数
// req:请求对象(包含了与请求相关的属性与方法)
// res:响应对象(包含了与响应相关的属性与方法)

app.post('请求URL', (req, res) => {
    
    
    ... 处理函数
})

5 クライアントに内容を返信します

res.send()メソッドを使用すると、処理されたコンテンツをクライアントに送信できます。

app.get("/user", (req, res) => {
    
    
  // 调用 express 提供的 res.send() 方法,向客户端响应一个 JSON 对象
  res.send({
    
     name: "xiaoxu", age: 20 });
});

app.post("/user", (req, res) => {
    
    
  // 调用 express 提供的 res.send() 方法,向客户端响应一个 文本字符串
  res.send('请求成功');
});

6 URL に含まれるクエリパラメータを取得します

req.query查询字符串クライアントがフォームを通じてアクセスできるオブジェクト、サーバーに送信されるパラメータ:

// req.query 默认是一个空对象
// 客户端使用 ?name=zs&age=20 这种查询字符串形式,发送到服务器的参数
// 可以通过 req.query 对象访问
// 例如:req.query.name  req.query.age

app.get("/", (req, res) => {
    
    
  console.log(req.query);
});

7 URL 内の動的パラメータを取得します

req.params:動的パラメータを照合することで URL に配置できるオブジェクト。

// req.params 默认是一个空对象
// 里面存放着通过 : 动态匹配到的参数值

app.get('/user/:id', (req, res) => {
    
    
  console.log(req.params); //{ id:1 }
})

// 注意:
// 其中冒号 : 是固定的,id不是固定的,可以是任意的,是匹配完成后参数的名称
// 动态参数可以有多个
app.get('/user/:id/:username', (req, res) => {
    
    
  console.log(req.params); // { id:1, username:'zs' }
})

8.3 静的リソースのホスティング

1 Express.static()

Express には、 という非常に便利な関数が用意されていますexpress.static()

これにより、非常方便地创建一个静态资源服务器たとえば、次のコードを使用して、パブリック ディレクトリ内の画像、CSS ファイル、JavaScript ファイルにアクセスできるようになります。

app.use(express.static('public'))

// 调用 app.use 这个函数,在函数中调用 express.static() 这个方法。
// 在这个方法中需要去指定哪个目录作为静态资源文件夹,进行共享向外托管。
// 指定 public 目录,即可访问 public 目录中的所有文件了。

これで、パブリック ディレクトリ内のすべてのファイルにアクセスできるようになります。

http://localhost:3000/images/bg.jpg

http://localhost:3000/css/style.css

http://localhost:3000/js/login.js

**注意: **Express は、指定された静的ディレクトリ内のファイルを検索し、リソースへのアクセス パスを提供します。

したがって、存放静态文件的目录名不会出现在 URL 中

2 複数の静的リソース ディレクトリをホストする

複数の静的リソース ディレクトリをホストしたい場合は、express.static()関数を。

app.use(express.static('public'))
app.use(express.static('public2'))

静的リソース ファイルにアクセスする場合、express.static() 函数会根据目录的添加顺序查找所需的文件.

3 マウントパスプレフィックス

管理対象静的リソースの前のパスにアクセスする場合は、挂载路径前缀次の方法を使用できます。

app.use('/public', express.static('public'))

これで、先頭に /public を付けることで、パブリック ディレクトリ内のファイルにアクセスできるようになります。

http://localhost:3000/public/images/kitten.jpg

http://localhost:3000/public/css/style.css

http://localhost:3000/public/js/app.js

8.4 nodemon

1 ノードモンを使用する理由

Node.js プロジェクトを作成およびデバッグするときに、プロジェクトのコードを変更すると、頻繁にプロジェクトを手動で閉じてから再起動する必要があり、非常に面倒です。

これで、プロジェクト ファイルの変更を監視できるツール nodemon (https://www.npmjs.com/package/nodemon) を使用できるようになりました。コードが変更されると、nodemon は自動的にプロジェクトを再起動します。開発とデバッグに便利です。

2 ノードモンをインストールします

npm install -g nodemon

3 ノデーモンを使用する

Node.js に基づいて Web サイト アプリケーションを作成する場合、従来の方法は、node app.js コマンドを実行してプロジェクトを開始することです。この欠点は、コードを変更した後、プロジェクトを手動で再起動する必要があることです。

これで、node コマンドを nodemon コマンドに置き換えて、プロジェクトを開始するnodemon app.jsことが。これを行うことの利点は次のとおりです。

代码被修改之后,会被 nodemon 监听到,从而实现自动重启项目的效果

node app.js

nodemon app.js

9 エクスプレスルーティング

9.1 ルーティングの概念

1 ルーティングとは

Express では、ルーティングは客户端的请求サーバーとのマッピング関係を指します务器处理函数

2 ルーティングの 3 つの要素

Express のルーティングは、次の 3 つの部分で構成されます请求的类型、请求的 URL 地址、处理函数

形式は次のとおりです: (タイプとアドレスはクライアントに関連付けられます)

app.METHOD(PATH, HANDLER)

METHOD	表示请求的类型		method
PATH	表示请求的地址 	path
HANDLER	处理函数		  handler

Express でのルーティングの例:

// 匹配 get 请求,且请求 url 为 / 
app.get('/', function(req, res){
    
    
  res.send("hello world");  
})

// 匹配 post 请求,且请求 url 为 / 
app.post('/', function(req, res){
    
    
  res.send("hello world");  
})

3 ルーティングマッチング処理

リクエストがサーバーに到着すると、需要先经过路由的匹配一致が成功した後にのみ、対応する処理関数が呼び出されます。

マッチングの際はルーティング順にマッチングを行い、同時にマッチングに成功した場合、Express はリクエストを対応する関数に転送して処理します请求类型请求的url

ルートマッチングの注意点:

  • ①定義どおりに先后顺序一致

  • ②合計请求类型と時刻の一致が成功した请求的URL場合のみ、対応する処理関数が呼び出されます。

9.2 ルーティングの使用

1 最も簡単な使い方

Express でルーティングを使用する最も簡単な方法は、アプリにルーティングをマウントすることです。

2 モジュラールーティング

ルートのモジュール管理を容易にするために、Express ではルートをアプリに直接マウントすることはお勧めしませんが、推奨されます将路由抽离为单独的模块

ルーティングを別のモジュールに抽出する手順は次のとおりです。

  • ①ルーティングモジュールに対応する.jsファイルを作成する

  • express.Router()関数ルーティングオブジェクトを作成する

  • ③特定のルートをルートオブジェクトにマウントする

  • ④ ルーティングオブジェクトをmodule.exports外部に

  • ⑤ ルーティングモジュールの登録app.use()機能

3 ルーティングモジュールを作成する

(1) 基本サーバーの作成

const express = require("express");
const app = express();

app.listen(80, () => {
    
    
  console.log("http://127.0.0.1");
});

(2) ルーティングモジュールの作成

// 1 导入 express
const express = require("express");

// 2 创建路由对象
const router = express.Router();

// 3 挂载具体的路由
router.get("/user/list", (req, res) => {
    
    
  res.send("Get user list.");
});
router.post("/user/add", (req, res) => {
    
    
  res.send("Add new user.");
});

// 4 向外导出路由对象
module.exports = router;

4 ルーティングモジュールを登録する

const express = require("express");
const app = express();

// 1 导入路由模块
const router = require("./router");

// 2 使用app.use() 注册路由模块
app.use(router);

app.listen(80, () => {
    
    
  console.log("http://127.0.0.1");
});

注:app.use()この関数の内容は次のとおりです注册全局中间件

5 ルーティングモジュールにプレフィックスを追加します

静的リソースをホストするときに静的リソースのアクセス プレフィックスを均一にマウントする方法と同様に、ルーティング モジュールにプレフィックスを追加する方法も非常に簡単です。

app.use("api", router);
// 使用 app.use() 注册路由模块,并添加统一的访问前缀 /api

10 エクスプレスミドルウェア

10.1 ミドルウェアの概念

1 ミドルウェアとは

ミドルウェア (Middleware) は、特にビジネスプロセス中间处理环节を指します。

2 例

下水を処理する場合、処理された廃水が排出基準を満たしていることを確認するために、一般に 3 つの処理ステップがあります。

これら 3 つの下水処理の中間処理リンクをミドルウェアと呼ぶことができます。ミドルウェアには入力と出力が必要です。

3 Expressミドルウェアの呼び出し処理

リクエストが Express サーバーに到着すると、複数のミドルウェアを継続的に呼び出してリクエストを前処理できます。

4 Expressミドルウェアのフォーマット

Express ミドルウェアは本質的には関数 処理機能であり、Express ミドルウェアの形式は次のとおりです。

注: ミドルウェア関数の仮パラメータ リストでは、必须包含 next 参数. ルート処理関数には
req と res のみが含まれます。

5 次の機能の役割

次の 関数は多个中间件连续调用実現の鍵であり、フロー関係を转交次の関数に転送することを意味します中间件或路由

10.2 Express ミドルウェアの初めての体験

1 ミドルウェア機能の定義

最も単純なミドルウェア関数を定義します。

const express = require("express");
const app = express();

// 产量 mw 所指向的,就是一个中间件函数
const mw = function (req, res, next) {
    
    
  console.log("定义一个最简单的中间件函数");
  // 注意:当中间件的业务逻辑处理完毕后,必须调用 next() 函数
  // 表示把流转关系转交给下一个中间件或路由。
  next()
};

app.listen(80, () => {
    
    
  console.log("http://127.0.0.1");
});

2 グローバルミドルウェア

クライアントによって開始され任何请求、サーバーに到達した後、都会触发的中间件が呼び出されます全局生效的中间件

を呼び出すことでapp.use(中间件函数)、グローバルに有効なミドルウェアを定義できます。サンプルコードは次のとおりです。

// 产量 mw 所指向的,就是一个中间件函数
const mw = function (req, res, next) {
    
    
  console.log("定义一个最简单的中间件函数");
  // 注意:当中间件的业务逻辑处理完毕后,必须调用 next() 函数
  // 表示把流转关系转交给下一个中间件或路由。
  next()
};

// 将 mw 注册为全局生效的中间件。
app.use(mw)

3 グローバルミドルウェアの簡略化

関数は app.use で渡されます。

app.use((req, res, next) => {
    
    
  console.log("定义一个最简单的中间件函数");
  next();
});

4 ミドルウェアの役割

複数のミドルウェアが同じ req resを共有します。このような機能に基づいて、下流のミドルウェアまたはルートで使用できるように、上流のミドルウェアの req または res オブジェクトにカスタム プロパティまたはメソッドを均一に追加できます。

app.use((req, res, next) => {
    
    
	// 获取到请求到达服务器的时间
    const time = Date.now();
    
    // req 对象,挂载自定义属性,从而把时间共享给后面的所有路由
    req.startTime = time

    next();
});

5 複数のグローバルミドルウェアを定義する

app.use()複数のグローバルミドルウェアを連続して定義できます。

クライアントリクエストがサーバーに到着すると、ミドルウェアで定義された順序に従って順番に呼び出されます。サンプルコードは次のとおりです。

6 ローカルで有効なミドルウェア

不使用 app.use() 定义的中间件、と呼ばれます局部生效的中间件

サンプルコードは次のとおりです。

const express = require("express"); // 导入 express 模块
const app = express(); // 创建 express 的服务器实例

// 1 定义中间件函数
const mw1 = (req, res, next) => {
    
    
  console.log("调用了局部生效的中间件");
  next();
};

// 2 创建路由
app.get("/", mw1, (req, res) => {
    
    
  // 该请求,会调用 mw1 中间件
  res.send("Home page.");
});
app.get("/user", (req, res) => {
    
    
  // 该请求不会调用 mw1 中间件
  res.send("User page.");
});

app.listen(80, () => {
    
    
  console.log("http://127.0.0.1");
});

7 複数の部分ミドルウェアを定義する

ルーティングでは、次の 2 つの等价方法があります使用多个局部中间件

// 一下两种写法是“完全等价”的,可以选择任意一种方式进行使用 
app.get("/", mw1, mw2, (req, res) => {
    
    
  res.send("Home page.");
});
app.get("/", [mw1, mw2], (req, res) => {
    
    
  res.send("Home page.");
});

8 ミドルウェア利用時の5つの注意点を理解する

  • ①必ず路由之前ミドルウェアを登録してください
  • ②クライアントから送信されたリクエスト可以连续调用多个中间件を処理する
  • ③ミドルウェアの業務コードを実行後、不要忘记调用 next() 函数
  • 防止代码逻辑混乱next()関数を呼び出した後に追加のコードを書かないでください。
  • ⑤ 複数のミドルウェアを連続して呼び出す場合、多个中间件之间,共享 req 和 res 对象

10.3 ミドルウェアの分類

Express は、一般的なミドルウェアの使用法を公式に次の 5 つのカテゴリに分類しています。

  • 应用级别ミドルウェア
  • 路由级别ミドルウェア
  • 错误级别ミドルウェア
  • Express 内置ミドルウェア
  • 第三方ミドルウェア

1 アプリケーションレベルのミドルウェア

app.use() または app.get() または app.post() を通じて、绑定到 app 实例上的中间件アプリケーション レベルのミドルウェアと呼ばれます。コード例は次のとおりです。

// 应用级别中间件(全局中间件)
app.use((req, res, next) => {
    
    
  next();
});

// 应用级别中间件(局部中间件)
app.get("/", mw1,(req, res) => {
    
    
  res.send("Home page.");
});

2 ルーティングレベルのミドルウェア

绑定到 express.Router() 实例上このミドルウェアはルーティングレベルミドルウェアと呼ばれます。

その使用方法はアプリケーションレベルのミドルウェアと何ら変わりません。ただし、アプリケーション レベルのミドルウェアはアプリ インスタンスにバインドされ、ルーティング レベルのミドルウェアはルーター インスタンスにバインドされます。コード例は次のとおりです。

const app = express()
const router = express.Router()

// 路由级别中间件
router.use((req, res, next) => {
    
    
    next()
})

app.use('/', router);

3 エラーレベルミドルウェア

**機能:**プロジェクト全体で発生し、防止项目异常崩溃問題を引き起こす異常なエラーを捕捉するために特別に使用されます。

**形式:** エラーレベルミドルウェアの関数処理関数では必ず があり4 个形参、仮パラメータの順序は(err,req,res,next)となります。

// 1 人为的制造错误
app.get('/', function(req, res){
    
    
  throw new Error('服务器内部发生了错误') // 抛出一个自定义的错误
  res.send('Home Page')
})

// 2 定义错误级别的中间件,捕获整个项目的异常错误,从而防止程序的崩溃
app.use((err, req, res, next) => {
    
    
  console.log('发生了错误!', err.message) // 在服务器答应错误消息 
  res.send('Error:', err.message) // 向客户响应错误相关的内容
})

**注意:** エラーレベルのミドルウェアはすべてのルートの後に登録する必要があります。

4 Express組み込みミドルウェア

Express 4.16.0 以降、Express には一般的に使用される 3 つのミドルウェアが組み込まれており、Express プロジェクトの開発効率とエクスペリエンスが大幅に向上します。

  • express.staticHTML ファイル、画像、CSS スタイルなどの静的リソースを高速にホストするための組み込みミドルウェア (互換性なし)
  • express.jsonリクエストボディデータを JSON 形式で解析します (互換性あり、バージョン 4.16.0 以降でのみ利用可能)
  • express.urlencodedURL エンコード形式のリクエスト本文データを解析します (互換性あり、バージョン 4.16.0 以降でのみ利用可能)
// 配置解析 application/json 格式数据的内置中间件
app.use(express.json());

// 配置解析 application/x-www-form-urlencoded 格式数据的内置中间件
app.use(express.urlencoded({
    
     extended: false}))

5 サードパーティ製ミドルウェア

Express が正式に組み込んでいない、サードパーティが開発したミドルウェアをサードパーティミドルウェアと呼びます。

プロジェクトでは、サードパーティのミドルウェアをオンデマンドでダウンロードして構成できるため、プロジェクトの開発効率が向上します。

例: [email protected] より前のバージョンでは、サードパーティのミドルウェアである body-parser がリクエスト本文データの解析によく使用されます。使用する手順は次のとおりです。

  • ① npm install body-parser を実行してミドルウェアをインストールします
  • ② require を使用してミドルウェアをインポートする
  • ③ app.use()を呼び出してミドルウェアの登録と利用を行う

**注意: **Express の組み込みの Express.urlencoded ミドルウェアは、サードパーティのミドルウェアのボディ パーサーに基づいてさらにカプセル化されています。

10.4 カスタムミドルウェア

https://www.bilibili.com/video/BV1a34y167AZ?p=49&vd_source=79669bc2885938b4485dee3a65450388


11 Express を使用してインターフェイスを作成する

11.1 基本サーバーの作成

// 导入 express 模块
const express = require("express");

// 创建 express 的服务器实例
const app = express();

// 调用 app.listen 方法,指定端口号并启动 web 服务器
app.listen(80, function () {
    
    
  console.log("Express server running at http://127.0.0.1");
});

11.2 APIルーティングモジュールの作成

apiRouter.js ルーティング モジュール

const express = require('express');

const router = express.Router();

// 在这里挂载路由

module.exports = router;

app.js はルーティング モジュールをインポートして登録します

const express = require("express");
const app = express();


// 导入路由模块
const router = require("./apiRouter");

// 把路由模块,注册到 app 上
app.use("/api", router);


app.listen(80, function () {
    
    
  console.log("Express server running at http://127.0.0.1");
});

11.3 書き込み取得インターフェース

クライアントは查询字符串データをサーバーに送信します。

const express = require("express");
const router = express.Router();

// 在这里挂载路由
router.get("/get", (req, res) => {
    
    
  // 1 通过 req.query 获取客户端通过查询字符串,发送到服务器的数据
  const query = req.query;

  // 2 调用 res.send() 方法,向客户端响应处理的结果
  res.send({
    
    
    status: 0, // 0 表示处理成功,1 表示处理失败
    msg: "GET 请求成功!", // 状态的描述
    data: query, // 需要响应给客户端的具体数据
  });
});

module.exports = router;

11.4 書き込みポストインターフェイス

クライアントは请求体传输数据サーバーに渡します。

const express = require("express");
const router = express.Router();

router.post("/post", (req, res) => {
    
    
  // 1 获取客户端通过请求体,发送到服务器的 URL-encoded 数据
  const body = req.body;

  // 2 调用 res.send() 方法,把数据响应给客户端
  res.send({
    
    
    status: 0, // 0 表示处理成功,1 表示处理失败
    msg: "POST 请求成功!", // 状态的描述
    data: body, // 需要响应给客户端的具体数据
  });
});

module.exports = router;

注:リクエスト本文データをURL-encoded形式で、ミドルウェア を設定する必要がありますapp.use(express.urlencoded({ extended: false }));

このミドルウェアが構成されていない場合、リクエスト本文のデータを req.body 経由で取得できません。

11.5 CORS クロスドメインリソース共有

1 インターフェースのクロスドメイン問題

次の GET および POST インターフェイスに非常に深刻な問題があります不支持跨域请求

インターフェイスのクロスドメイン問題を解決するには、主に 2 つの解決策があります。

  • CORS(主流の解決策、推荐使用)

  • JSONP(欠陥解決策: GET リクエストのみがサポートされます)

2 CORS ミドルウェアを使用してクロスドメインの問題を解決する

cors は、Express 用のサードパーティ ミドルウェアです。cors ミドルウェアをインストールして構成すると、クロスドメインの問題を簡単に解決できます。

利用ステップは以下の3ステップに分かれます。

  • ① npm install cors を実行する安装中间件

  • ② const cors = require('cors') を使用する导入中间件

  • ③ルーティング前に app.use(cors()) を呼び出す配置中间件

// 一定要在路由之前,配置 cors 这个中间件,从而解决接口跨域的问题
const cors = require("cors");
app.use(cors());
// 导入 express 模块
const express = require("express");

// 创建 express 的服务器实例
const app = express();

// 配置解析表单数据的中间件
app.use(express.urlencoded({
    
     extended: false }));

// 一定要在路由之前,配置 cors 这个中间件,从而解决接口跨域的问题
const cors = require("cors");
app.use(cors());

// 导入路由模块
const router = require("./apiRouter");

// 把路由模块,注册到 app 上
app.use("/api", router);

// 调用 app.listen 方法,指定端口号并启动 web 服务器
app.listen(80, function () {
    
    
  console.log("Express server running at http://127.0.0.1");
});

3 CORSとは何ですか

CORS (Cross-Origin Resource Sharing) は一連の HTTP 応答ヘッダーで構成されており、ブラウザーがフロントエンドJSコードによるドメイン間でのリソースの取得を妨げるかどうかを決定します

ブラウザの同源安全策略デフォルトでは、Web ページがリソースに「クロスドメイン」でアクセスすることはできません。ただし、インターフェースサーバーを使用すると配置了 CORS 相关的 HTTP 响应头、ブラウザ側のクロスドメインアクセス制限を解除できます。

4 CORS に関する考慮事項

  • ① CORS は主に にあります服务器端进行配置クライアント ブラウザは、追加の構成を行わなくても、 CORS が有効になっているインターフェイスを要求できます。

  • ②ブラウザのCORS 有兼容性通常、CORS が有効になっているサーバー インターフェイスにアクセスできるのは、XMLHttpRequest Level2 をサポートするブラウザーのみです (例: IE10+、Chrome4+、FireFox3.5+)。

5 CORS 応答ヘッダー - Access-Control-Allow-Origin

Access-Control-Allow-Originフィールドは応答ヘッダーに含めることができ、その構文は次のとおりです。

Access-Control-Allow-Origin: <origin> | *
    
// 冒号前面为响应头的 名称
// 冒号后面是响应头的 值。值可以是一个具体的域名,也可以是一个星号

このうち、origin パラメーターの値は、リソースへのアクセスを許可する外部ドメイン URL を指定します。

たとえば、次のフィールド値ではhttp://xxx.cn からのリクエストのみが許可されます。

res.setHeader('Access-Control-Allow-Origin:', 'http://xxx.cn')
// 表示这个服务器只支持 这个http://xxx.cn网页下所有的跨域请求

Access-Control-Allow-Origin フィールドの値がワイルドカードとして指定されている場合*、それは を意味します允许来自任何域的请求

res.setHeader('Access-Control-Allow-Origin:', '*')

6 CORS 応答ヘッダー - Access-Control-Allow-Headers

デフォルトでは、CORS はサーバーに次のものを送信するクライアントのみを9 个请求头サポートします。

Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width、Content-Type (値は text/plain、multipart/form-data、application/x-www- に限定されます) form-urlencoded の 3 つのうちの 1 つ)

クライアントが追加のリクエスト ヘッダー情報をサーバーに送信する場合、それはサーバー側にある必要があります。通过 Access-Control-Allow-Headers 对额外的请求头进行声明そうしないと、今度はリクエストが失敗します。

// 允许客户端额外向服务器发送 Content-Type 请求头和 X-Custom-Header 请求头

// 注意:多个请求头之间使用英文的逗号进行分割
res.setHeader('Access-Control-Allow-Headers:', 'Content-Type, X-Custom-Header')

7 CORS 応答ヘッダー - Access-Control-Allow-Methods

デフォルトでは、CORS はクライアントによって開始された GET、POST、および HEAD リクエストのみをサポートします。

クライアントが PUT、DELETE などを通じてサーバーにリソースを要求する場合は、サーバー側で行う必要があります通过 Access-Control-Alow-Methods来指明实际请求所允许使用的 HTTP 方法

サンプルコードは次のとおりです。

// 只允许 POST、GET、DELETE、HEAD 请求方法
res.setHeader('Access-Control-Allow-Methods:', 'POST, GET, DELETE, HEAD')

// 允许所有的  HTTP 请求方法
res.setHeader('Access-Control-Allow-Methods:', '*')

8 CORS リクエストの分類

クライアントが CORS インターフェイスを要求する場合、请求方式和请求头その違いに応じて、CORS 要求は次の 2 つのカテゴリに分類できます。

  • ①簡単なお願い

  • ②事前確認依頼

9つの簡単なリクエスト

次の 2 つの条件を同時に満たすリクエストは、単純なリクエストです。

  • ①リクエスト方法:GET、POST、HEAD 三者之一

  • ②HTTPヘッダー情報の以下のフィールド不超过:カスタムヘッダーフィールドなし、Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width、Content-Type(3つの値のみ application /x -www-form-urlencoded、multipart/form-data、text/plain)

10 プリフライトリクエスト

リクエストが次の条件のいずれかを満たしている限り、プリフライト リクエストが必要です。

  • ①リクエストメソッドがGET、POST、HEAD以外のリクエストメソッドの種類である

  • ② リクエストヘッダーにカスタムヘッダーフィールドが含まれる

  • ③application/json形式のデータをサーバーに送信

ブラウザがサーバーと正式に通信する前に、浏览器会先发送 OPTION 请求进行预检,以获知服务器是否允许该实际请求今回は OPTION リクエストが呼び出されます预检请求

服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据。

11 単純リクエストとプリフライトリクエストの違い

単純なリクエストの特徴: クライアントとサーバーの間只会发生一次请求

プリフライト リクエストの特徴: クライアントとサーバーの間で会发生两次请求、実際のリクエストは OPTION プリフライト リクエストが成功した後にのみ開始されます。

11.6 JSONPインターフェース

1 JSONPの概念と特徴

概念: ブラウザは<script>タグ、同時にサーバーは関数呼び出しを返します。このデータ要求方法は JSONP と呼ばれます。

特徴:

  • ① JSONP は XMLHttpRequest オブジェクトを使用しないため、実際の Ajax リクエストではありません。

  • ② JSONP は GET リクエストのみをサポートし、POST、PUT、DELETE などのリクエストはサポートしません。

2 JSONPインターフェース作成時の注意点

CORS クロスオリジン リソース共有がプロジェクトで構成されている場合、競合を防ぐために必须在配置 CORS 中间件之前声明 JSONP 的接口それ以外の場合、JSONP インターフェイスは CORS が有効になったインターフェイスとして処理されます。

サンプルコードは次のとおりです。

// 必须在配置 cors 中间件之前,配置 JSONP 的接口
app.get("api/jsonp", (req, res) => {
    
    
  // 定义jsonp接口的具体实现过程
});

// 一定要在路由之前,配置 cors 这个中间件,从而解决接口跨域的问题
const cors = require("cors");
app.use(cors());

3 JSONPインターフェースを実装する

  • ① クライアントから送信された情報を取得する回调函数的名字

  • ②JSONP形式で取得发送给客户端的数据

  • ③ 最初の 2 つのステップで得られたデータに従って、拼接出一个函数调用的字符串

  • ④ クライアントの<script>タグ

app.get("api/jsonp", (req, res) => {
    
    
  // 1 获取客户端发送过来的回调函数的名字
  const funcName = req.query.callback;

  // 2 得到要通过 jsonp 形式发送给客户端的数据
  const data = {
    
     naem: "zs", age: 20 };

  // 3 根据前两步得到的数据,拼接出一个函数调用的字符串
  const scriptStr = `${
      
      funcName}(${
      
      JSON.stringify(data)})`;

  // 4 把上一步拼接得到的字符串,响应给客户端的 <script> 标签进行解析执行
  res.send(scriptStr);
});

4 Web ページで JSONP リクエストを開始します


PUT、DELETE などを通じてサーバーにリソースをリクエストする場合は、 を使用する必要があります通过 Access-Control-Alow-Methods来指明实际请求所允许使用的 HTTP 方法

サンプルコードは次のとおりです。

// 只允许 POST、GET、DELETE、HEAD 请求方法
res.setHeader('Access-Control-Allow-Methods:', 'POST, GET, DELETE, HEAD')

// 允许所有的  HTTP 请求方法
res.setHeader('Access-Control-Allow-Methods:', '*')

8 CORS リクエストの分類

クライアントが CORS インターフェイスを要求する場合、请求方式和请求头その違いに応じて、CORS 要求は次の 2 つのカテゴリに分類できます。

  • ①簡単なお願い

  • ②事前確認依頼

9つの簡単なリクエスト

次の 2 つの条件を同時に満たすリクエストは、単純なリクエストです。

  • ①リクエスト方法:GET、POST、HEAD 三者之一

  • ②HTTPヘッダー情報の以下のフィールド不超过:カスタムヘッダーフィールドなし、Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width、Content-Type(3つの値のみ application /x -www-form-urlencoded、multipart/form-data、text/plain)

10 プリフライトリクエスト

リクエストが次の条件のいずれかを満たしている限り、プリフライト リクエストが必要です。

  • ①リクエストメソッドがGET、POST、HEAD以外のリクエストメソッドの種類である

  • ② リクエストヘッダーにカスタムヘッダーフィールドが含まれる

  • ③application/json形式のデータをサーバーに送信

ブラウザがサーバーと正式に通信する前に、浏览器会先发送 OPTION 请求进行预检,以获知服务器是否允许该实际请求今回は OPTION リクエストが呼び出されます预检请求

服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据。

11 単純リクエストとプリフライトリクエストの違い

単純なリクエストの特徴: クライアントとサーバーの間只会发生一次请求

プリフライト リクエストの特徴: クライアントとサーバーの間で会发生两次请求、実際のリクエストは OPTION プリフライト リクエストが成功した後にのみ開始されます。

11.6 JSONPインターフェース

1 JSONPの概念と特徴

概念: ブラウザは<script>タグ、同時にサーバーは関数呼び出しを返します。このデータ要求方法は JSONP と呼ばれます。

特徴:

  • ① JSONP は XMLHttpRequest オブジェクトを使用しないため、実際の Ajax リクエストではありません。

  • ② JSONP は GET リクエストのみをサポートし、POST、PUT、DELETE などのリクエストはサポートしません。

2 JSONPインターフェース作成時の注意点

CORS クロスオリジン リソース共有がプロジェクトで構成されている場合、競合を防ぐために必须在配置 CORS 中间件之前声明 JSONP 的接口それ以外の場合、JSONP インターフェイスは CORS が有効になったインターフェイスとして処理されます。

サンプルコードは次のとおりです。

// 必须在配置 cors 中间件之前,配置 JSONP 的接口
app.get("api/jsonp", (req, res) => {
    
    
  // 定义jsonp接口的具体实现过程
});

// 一定要在路由之前,配置 cors 这个中间件,从而解决接口跨域的问题
const cors = require("cors");
app.use(cors());

3 JSONPインターフェースを実装する

  • ① クライアントから送信された情報を取得する回调函数的名字

  • ②JSONP形式で取得发送给客户端的数据

  • ③ 最初の 2 つのステップで得られたデータに従って、拼接出一个函数调用的字符串

  • ④ クライアントの<script>タグ

app.get("api/jsonp", (req, res) => {
    
    
  // 1 获取客户端发送过来的回调函数的名字
  const funcName = req.query.callback;

  // 2 得到要通过 jsonp 形式发送给客户端的数据
  const data = {
    
     naem: "zs", age: 20 };

  // 3 根据前两步得到的数据,拼接出一个函数调用的字符串
  const scriptStr = `${
      
      funcName}(${
      
      JSON.stringify(data)})`;

  // 4 把上一步拼接得到的字符串,响应给客户端的 <script> 标签进行解析执行
  res.send(scriptStr);
});

おすすめ

転載: blog.csdn.net/qq_53931766/article/details/127511922