整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Node.js 22 發布,require(esm)

          Node.js 22 發布,require(esm) 終于圓夢了!

          家好,很高興又見面了,我是"高級前端?進階?",由我帶著大家一起關注前端前沿、深入前端底層技術,大家一起進步,也歡迎大家關注、點贊、收藏、轉發,您的支持是我不斷創作的動力。

          2024 年 4 月 24 日 Node.js 22 如期發布,眾多亮點包括:ES 模塊支持 require、WebSocket 客戶端支持、V8 JavaScript 引擎更新等等。

          另外值得注意的是,Node.js 18 將于 2025 年 4 月終止生命周期,因此非常建議開發者升級到 Node.js 20 (LTS) 或 Node.js 22(即將成為 LTS)。

          重點關注點 1:支持 require() 同步 ESM

          下面是 CJS、ESM 模塊的代碼示例:

          // 下面是 CJS 模塊
          const a=require("./a")
          module.exports={a, b: 2}
          // 下面是 EMS
          import a from "./a"
          export default {a, b: 2}

          兩種模塊方式互不兼容,而且遷移非常麻煩。因此,Node.js 貢獻者一開始決定對 ESM 語法使用新的文件擴展名,即. mjs。

          因此,在聲明一個公共的庫的時候,開發者通常有兩種選擇:

          • 忽略 ESM 依然采用 CommonJS
          • 將 ESM 與 Babel 轉譯器結合使用
          • 同時支持 ESM 和 CommonJS

          然而,Node.js 已經提供了對 ES7 和 ES8 的全面支持,如果還需要轉譯代碼才能通過 ESM 語法導出和導入模塊確實多少有點不合時宜。

          Node.js 22 版本通過 --experimental-require-module 標志添加對同步 ESM 的 require支持。如果啟用了該標志,并且 require() 加載的 ECMAScript 模塊滿足以下要求:

          • 在最近 package.json 或 .mjs 擴展名中使用 "type": "module" 字段顯式標記為 ES 模塊
          • 完全同步、不包括 top-level-await,例如:await Promise.resolve(console.log(''));

          require() 會將請求的模塊作為 ES 模塊加載并返回模塊名稱空間對象 (Name Space Object)。 該模式與動態 import() 非常類似,但是會同步運行(Run Synchronously )并直接返回名稱空間對象。 同時,require(esm) 最終還會在不久的將來完全摒棄 flag 標記。

          重點關注點 2:Node.js 22 其他重大變化

          除了上面說明的支持 require() 同步 ESM外,下面也是 Node.js 22 版本帶來的諸多值得關注的變化。

          • V8 版本更新到 12.4,包括 WebAssembly 垃圾收集、Array.fromAsync、Set 方法和迭代器幫助程序等新功能。
          • V8 的 Maglev 編譯器在支持的架構上默認啟用 (https://v8.dev/blog/maglev),Maglev 顯著提高了 CLI 程序的性能。
          • Node.js 22 包含一個新的實驗性功能,用于使用 cli 標志 node --run <script-in-package-json> 從 package.json 執行腳本,其還支持 node --run test 在 package.json 腳本中執行測試命令。
          • 將 Stream 的默認高水位線(Stream default High Water Mark)從 16KiB 增加到 64KiB,從而帶來全面的性能提升,但是鼓勵內存敏感環境中的用戶顯式設置 setDefaultHighWaterMark。
          • 從 Node.js 22 版本開始,watch 模式基本穩定。 當處于 watch 模式時,監視文件中的更改會導致 Node.js 進程重新啟動。
          • 默認情況下將啟用 WebSocket 的瀏覽器兼容實現,為 Node.js 提供了一個 WebSocket 客戶端,無需外部依賴
          • 向 node:fsmodule 添加了用于模式匹配的 glob 和 globSync 函數。 開發人員現在可以利用這些函數根據指定模式匹配文件路徑。
          • 支持 AbortSignal 性能優化

          參考資料

          https://nodejs.org/en/blog/announcements/v22-release-announce#running-packagejson-scripts

          https://dev.to/emmabase/nodejs-22-is-live-49b1

          https://www.codingame.com/playgrounds/5262/native-es-modules-in-node-js

          https://www.youtube.com/watch?v=teDVlOjOCT0

          例3. 構建 Web 服務器

          這部分示例將致力于用 Node.js 模擬一個類似于 Apache 的 Web 服務器,處理瀏覽器端的請求,將相關的頁面響應給瀏覽器。首先,我們要在code目錄下執行mkdir 03_webSever命令來創建用于存放這一組示例的目錄。然后執行以下步驟:

          1. 在code/03_webSever目錄下執行mkdir www命令,創建網站目錄,然后在其中創建index.htm和login.htm兩個 HTML 文件以及一個名為style.css的 CSS 文件:

          1、index.htm:

          <!DOCTYPE html>
          <html lang="zh-cn">
          <head>
          <meta charset="utf-8" />
          <link rel="stylesheet" type="text/css" href="style.css" />
          <title>首頁</title>
          </head>
          <body>
          <h1>你好,nodejs!</h1>
          <p> <a href="login.htm">請登錄!</a> </p>
          </body>
          </html>

          2、login.htm:

          <!DOCTYPE html>
          <html lang="zh-cn">
          <head>
          <meta charset="utf-8" />
          <link rel="stylesheet" type="text/css" href="style.css" />
          <title>登錄頁面</title>
          </head>
          <body>
          <h1>你已經登錄。。。</h1>
          <p> <a href="index.htm">回首頁!</a> </p>
          </body>
          </html>

          3、style.css:

          body { 
          background: gray; 
          }

          2、在code/03_webSever目錄下執行touch 03-webServer.js命令,創建腳本文件,并輸入如下代碼:

          const http=require('http')
          const fs=require('fs')
          const server=http.createServer()
          
          server.on('request', function(req, res) {
          const webRoot='./www'
          const url=req.url
          if ( url==='/' ) {
          url='/index.htm'
          }
          
          fs.readFile(webRoot+url, function(err, data) {
          if ( err !==null ) {
          console.error('錯誤信息:' + err.message)
          return res.end('<h1>404 頁面沒找到!</h1>')
          }
          res.end(data)
          })
          })
          
          server.listen(8080, function(){
          console.log('請訪問http://localhost:8080/,按Ctrl+C終止服務!')
          })

          3、保存所有文件后,在code/03_webSever目錄下執行node 03-webServer.js命令,然后打開瀏覽器并訪問http://localhost:8080/,就會看到如下頁面:

          示例4. 使用art-template模版引擎生成網頁

          這一部分本示例將以生成個人信息頁面為例,演示在服務器端基于 Node.js 使用art-template模板引擎來生成網頁。為此,我們需要在code目錄下執行mkdir 04_templatingEngine命令來創建用于存放這一組示例的目錄。

          1. 單模版渲染

          首先來示范一下如何使用art-template模版引擎的渲染單一模版文件,請跟著以下步驟來構建示例:

          1. 在code/04_templatingEngine目錄下執行npm install art-template --save命令,安裝將art-template包安裝到當前示例項目中。
          2. 在code/04_templatingEngine目錄下執行touch singleTpl.htm命令,創建一個模版文件,并在其中輸入以下代碼:
          <!DOCTYPE html>
          <html lang="zh-cn">
          <head>
          <meta charset="utf-8" />
          <link rel="stylesheet" type="text/css" href="style.css" />
          <title>{{ name }}的個人信息</title>
          </head>
          <body>
          <h1>{{ name }}的個人信息</h1>
          <table>
          <tr><td>姓名:</td><td>{{ name }}</td></tr>
          <tr><td>年齡:</td><td>{{ age }}</td></tr>
          <tr><td>性別:</td><td>{{ sex }}</td></tr>
          <tr>
          <td>愛好:</td>
          <td>{{ each items }} {{ $value }} {{ /each }}</td>
          </tr>
          </table>
          </body>
          </html>

          3、在code/04_templatingEngine目錄下執行touch 04-useTemplating_engine.js命令,創建一個腳本文件,具體如下:

          const http=require('http')
          const fs=require('fs')
          const template=require('art-template')
          
          class human {
          constructor(name, age, sex, items=[])
          {
          this.name=name
          this.age=age
          this.sex=sex
          this.items=items
          }
          }
          
          const server=http.createServer()
          
          server.on('request', function(req, res){
          const url=req.url
          let boy=null
          if ( url==='/' ) {
          boy=new human('凌杰', '37', '男', ['看書', '看電影','旅游'])
          } else if ( url==='/wang' ) {
          boy=new human('蔓兒', '25', '女', ['看書', '看電影','寫作'])
          }
          
          if ( boy===null ) {
          return res.end('<h1>404 頁面沒找到!</h1>')
          }
          
          fs.readFile('./singleTpl.htm', function(err, data){
          if ( err !==null ) {
          return res.end('<h1>404 沒找到模版文件!</h1>')
          }
          
          const strHtml=template.render(data.toString(), {
          name : boy.name,
          age : boy.age,
          sex : boy.sex,
          items: boy.items
          })
          
          res.end(strHtml)
          })
          })
          
          server.listen(8080, function(){
          console.log('請訪問http://localhost:8080/,按Ctrl+C終止服務!')
          })

          4、保存所有文件后,在code/04_templatingEngine目錄下執行node 04-useTemplating_engine.js命令,然后打開瀏覽器并訪問http://localhost:8080/wang,就會看到如下頁面:

          2. 多模版組合渲染

          在同一 Web 應用中,所有的頁面通常都由相同的頭部和底部元素,所以為了減少代碼的冗余,提高重用率,開發者們通常會考慮將重復的部分獨立成一個單獨的模版文件,然后用相互包含的方式組合成頁面。下面就繼續以art-template模板引擎為例來演示一下如何將多個模版組合渲染成單一的 HTML 頁面,其具體步驟如下:

          1. 在code/04_templatingEngine目錄下執行touch tpl1.art tpl2.art命令,創建兩個模版文件,然后在這兩個文件中分別輸入以下代碼:

          1、tpl1.art :

          <header>
          <h1>查看個人信息</h1>
          <br>
          </header>

          2、tpl2.art :

          <footer>
          <div>
          <p>? 2016 owlman.org;本站系純HTML5站點。</p>
          </div>
          </footer>

          2、在code/04_templatingEngine目錄下執行touch multiTpl.htm命令創建用于組合的 HTML 頁面文件,并在其中輸入以下代碼:

          <!DOCTYPE html>
          <html lang="zh-cn">
          <head>
          <meta charset="utf-8" />
          <link rel="stylesheet" type="text/css" href="style.css" />
          <title>查看個人信息</title>
          </head>
          <body>
          {{ include './tpl1.art' }}
          <h2>{{ name }}的個人信息</h2>
          <table>
          <tr><td>姓名:</td><td>{{ name }}</td></tr>
          <tr><td>年齡:</td><td>{{ age }}</td></tr>
          <tr><td>性別:</td><td>{{ sex }}</td></tr>
          <tr>
          <td>愛好:</td>
          <td>{{ each items }} {{ $value }} {{ /each }}</td>
          </tr>
          </table>
          {{ include './tpl2.art' }}
          </body>
          </html>

          3、在code/04_templatingEngine目錄下執行

          cp 04-useTemplating_engine.js 04-useTemplating_engine2.js命令,將之前的代碼復制一份,并修改如下:

          const http=require('http')
          const fs=require('fs')
          const template=require('art-template')
          
          template.defaults.root=__dirname // 配置模版的查找根目錄
          
          class human {
          constructor(name, age, sex, items=[])
          {
          this.name=name
          this.age=age
          this.sex=sex
          this.items=items
          }
          }
          
          const server=http.createServer()
          
          server.on('request', function(req, res){
          const url=req.url
          let boy=null
          if ( url==='/' ) {
          boy=new human('凌杰', '37', '男', ['看書', '看電影','旅游'])
          } else if ( url==='/wang' ) {
          boy=new human('蔓兒', '25', '女', ['看書', '看電影','寫作'])
          }
          
          if ( boy===null ) {
          return res.end('<h1>404 頁面沒找到!</h1>')
          }
          
          fs.readFile('./multiTpl.htm', function(err, data){ // 修改了要讀取的模版文件
          if ( err !==null ) {
          return res.end('<h1>404 沒找到模版文件!</h1>')
          }
          
          const strHtml=template.render(data.toString(), {
          name : boy.name,
          age : boy.age,
          sex : boy.sex,
          items: boy.items
          })
          
          res.end(strHtml)
          })
          })
          
          server.listen(8080, function(){
          console.log('請訪問http://localhost:8080/,按Ctrl+C終止服務!')
          })

          4、保存所有文件后,在code/04_templatingEngine目錄下執行node 04-useTemplating_engine2.js命令,然后打開瀏覽器并訪問http://localhost:8080,就會看到如下頁面:

          3. 多模版繼承渲染

          當然,如果重復的元素只有頭部和尾部的話,有時候使用模版繼承語法來渲染頁面會是一個更好的選擇,下面就來繼續演示一下art-template模板引擎的繼承語法來渲染 HTML 頁面,其具體步驟如下:

          1. 在code/04_templatingEngine目錄下執行touch baseTpl.art命令,創建父模版文件,然后在該文件中輸入以下代碼:
          <!DOCTYPE html>
          <html lang="zh-cn">
          <head>
          <meta charset="utf-8" />
          <link rel="stylesheet" type="text/css" href="style.css" />
          <title>{{ name }}的個人信息</title>
          </head>
          <body>
          <header>
          <h1>查看個人信息</h1>
          <br>
          </header>
          
          {{ block 'message' }}
          {{ /block }}
          
          <footer>
          <div>
          <p>? 2016 owlman.org;本站系純HTML5站點。</p>
          </div>
          </footer>
          </body>
          </html>

          2、在code/04_templatingEngine目錄下執行touch extendTpl.htm命令,創建子模版文件,然后在該文件中輸入以下代碼:

          {{ extend 'baseTpl.art' }}
          
          {{ block 'message' }}
          <h1>{{ name }}的個人信息</h1>
          <table>
          <tr><td>姓名:</td><td>{{ name }}</td></tr>
          <tr><td>年齡:</td><td>{{ age }}</td></tr>
          <tr><td>性別:</td><td>{{ sex }}</td></tr>
          <tr>
          <td>愛好:</td>
          <td>{{ each items }} {{ $value }} {{ /each }}</td>
          </tr>
          </table>
          {{ /block }}

          3、在code/04_templatingEngine目錄下執行cp 04-useTemplating_engine.js 04-useTemplating_engine3.js命令,將之前的代碼復制一份,并修改如下:

          // 用Node.js生成動態頁面
          // 作者:owlman
          // 時間:2019年07月12日
          
          const http=require('http')
          const fs=require('fs')
          const template=require('art-template')
          
          template.defaults.root=__dirname
          
          class human {
          constructor(name, age, sex, items=[])
          {
          this.name=name
          this.age=age
          this.sex=sex
          this.items=items
          }
          }
          
          const server=http.createServer()
          
          server.on('request', function(req, res) {
          const url=req.url
          let boy=null
          if (url==='/') {
          boy=new human('凌杰', '37', '男', ['看書', '看電影','旅游'])
          } else if (url==='/wang') {
          boy=new human('蔓兒', '25', '女', ['看書', '看電影','寫作'])
          }
          
          if (boy===null) {
          return res.end('<h1>404 頁面沒找到!</h1>')
          }
          
          fs.readFile('./extendTpl.htm', function(err, data) {
          if ( err !==null ) {
          return res.end('<h1>404 沒找到模版文件!</h1>')
          }
          
          const strHtml=template.render(data.toString(), {
          name : boy.name,
          age : boy.age,
          sex : boy.sex,
          items: boy.items
          })
          
          res.end(strHtml)
          })
          })
          
          server.listen(8080, function(){
          console.log('請訪問http://localhost:8080/,按Ctrl+C終止服務!')
          })

          4、保存所有文件后,在code/04_templatingEngine目錄下執行node 04-useTemplating_engine3.js命令,然后打開瀏覽器并訪問http://localhost:8080,就會看到與之前相同的頁面。

          示例5. Web 表單處理

          這一部分示例將致力于演示用 Node.js 處理 Web 表單,我們將會分別示范如何用get和post兩種方法來處理表單的請求。首先,我們要在code目錄下執行mkdir 05_webForm命令來創建用于存放這一組示例的目錄。

          1. get 方法

          先用一個信息查詢程序來演示一下如何處理使用get方法來發送請求的表單。首先,在code/05_webForm目錄下執行mkdir get_form命令,并執行以下步驟:

          在code/05_webForm/get_form目錄下執行npm install art-template命令,將art-template安裝到當前示例項目中。
          在code/05_webForm/get_form目錄下執行touch index.htm,創建一個模版文件,具體如下: <!DOCTYPE html>
          <html lang="zh-cn">
          <head>
          <meta charset="UTF-8">
          <title>個人信息查詢</title>
          </head>
          <body>
          <h1>個人信息查詢</h1>
          <form action="/query" method="GET">
          <label for="message">請輸入要查詢的姓名:</label>
          <input type="text" name="qname" />
          <input type="submit" value="查詢" />
          </form>
          <br />
          {{ if name }}
          <table>
          <caption>{{ name }}的個人信息</caption>
          <tr><td>姓名:</td><td>{{ name }}</td></tr>
          <tr><td>年齡:</td><td>{{ age }}</td></tr>
          <tr><td>性別:</td><td>{{ sex }}</td></tr>
          <tr>
          <td>愛好:</td>
          <td>{{ each items }} {{ $value }} {{ /each }}</td>
          </tr>
          </table>
          {{ else if query_error }}
          <h2>沒有找到相關信息!</h2>
          {{ /if }}
          </body>
          </html>

          3、在code/05_webForm/get_form目錄下執行touch app.js,創建一個腳本文件,具體如下: const http=require('http')

          const fs=require('fs')
          const url=require('url')
          const template=require('art-template')
          
          class human {
          constructor(name, age, sex, items=[])
          {
          this.name=name
          this.age=age
          this.sex=sex
          this.items=items
          }
          }
          
          const db=[
          new human('凌杰', '37', '男', ['看書', '看電影','旅游']),
          new human('蔓兒', '25', '女', ['看書', '看電影','寫作']),
          new human('張語', '32', '女', ['看書', '旅游','繪畫'])
          ]
          
          const server=http.createServer(function(req, res){
          const query=url.parse(req.url, true)
          let obj=null
          let query_error=false
          if ( query.pathname==='/' ) {
          query_error=false
          }
          else if (query.pathname==='/query') {
          for(let i=0; i < db.length; ++i) {
          if (db[i].name==query.query["qname"]) {
          obj=db[i]
          }
          }
          if ( obj===null ) {
          query_error=true
          }
          } else {
          return res.end('<h1>404 頁面沒找到!</h1>')
          }
          
          fs.readFile('./index.htm', function(err, data){
          if ( err !==null ) {
          return res.end('<h1>404 沒找到模版文件!</h1>')
          }
          
          let strHtml=null
          if ( obj !==null ) {
          strHtml=template.render(data.toString(), {
          name : obj.name,
          age : obj.age,
          sex : obj.sex,
          items: obj.items,
          query_error: query_error
          })
          } else {
          strHtml=template.render(data.toString(), {
          name : false,
          query_error: query_error
          })
          }
          res.end(strHtml)
          })
          })
          
          server.listen(8080, function() {
          console.log('請訪問http://localhost:8080/,按Ctrl+C終止服務!')
          })

          4、保存所有文件后,在code/05_webForm/get_form目錄下執行node app.js命令,結果如下:

          2. post 方法

          先來演示如何處理使用post方法來發送請求的表單。首先,在code/05_webForm目錄下執行mkdir post_form命令,并執行以下步驟:

          1. 在code/05_webForm/get_form目錄下執行npm install art-template命令,將art-template安裝到當前示例項目中。
          2. 在code/05_webForm/post_form目錄下執行touch index.htm,創建一個模版文件,具體如下:
           <!DOCTYPE html>
          <html lang="zh-cn">
          <head>
          <meta charset="UTF-8">
          <title>個人信息管理</title>
          </head>
          <body>
          <h1>個人信息管理</h1>
          <table>
          <caption>個人數據表</caption>
          <tr><th>姓名</th><th>年齡</th><th>性別</th><th>愛好</th></tr>
          {{ each db }}
          <tr>
          <td>{{ $value.name }} </td>
          <td>{{ $value.age }} </td>
          <td>{{ $value.sex }} </td>
          <td>{{ each $value.items }} {{ $value }} {{ /each }}</td>
          </tr>
          {{ /each }}
          </table>
          
          <form action="/add" method="POST">
          <table>
          <caption>錄入新人員</caption>
          <tr><td>姓名:</td><td><input type="text" name="uname" /></td></tr>
          <tr><td>年齡:</td><td><input type="text" name="age"></td></tr>
          <tr><td>性別:</td><td><input type="text" name="sex"></td></tr>
          <tr><td>愛好:</td><td><input type="text" name="items"></td></tr>
          </table>
          <input type="submit" value="添加" />
          </form>
          </body>
          </html>

          3、在code/05_webForm/post_form目錄下執行touch app.js,創建一個腳本文件,具體如下:

          const http=require('http')
          const fs=require('fs')
          const url=require('url')
          const querystring=require('querystring')
          const template=require('art-template')
          
          class human {
          constructor(name, age, sex, items=[])
          {
          this.name=name
          this.age=age
          this.sex=sex
          this.items=items
          }
          }
          
          const db=[
          new human('凌杰', '37', '男', ['看書', '看電影','旅游']),
          new human('蔓兒', '25', '女', ['看書', '看電影','寫作']),
          new human('張語', '32', '女', ['看書', '旅游','繪畫'])
          ]
          
          const server=http.createServer(function(req, res){
          const query=url.parse(req.url, true)
          if ( query.pathname==='/' ) {
          fs.readFile('./index.htm', function(err, data) {
          if ( err !==null ) {
          return res.end('<h1>404 沒找到模版文件!</h1>')
          }
          
          const strHtml=template.render(data.toString(), {
          "db": db
          })
          
          res.end(strHtml)
          })
          }
          else if ( query.pathname==='/add' ) {
          req.on('data', function(chunk) {
          const obj=querystring.parse(chunk.toString())
          db.push(new human(
          obj['uname'],
          obj['age'],
          obj['sex'],
          obj['items'].split(','),
          ))
          })
          
          res.writeHead(302, {
          'location': `/`
          })
          
          res.end()
          } else {
          return res.end('<h1>404 頁面沒找到!</h1>')
          }
          })
          
          server.listen(8080, function(){
          console.log('請訪問http://localhost:8080/,按Ctrl+C終止服務!')
          })

          4、保存所有文件后,在code/05_webForm/post_form目錄下執行node app.js命令,結果如下:


          主站蜘蛛池模板: 天天视频一区二区三区 | 国产精品伦子一区二区三区| 97人妻无码一区二区精品免费| 亚洲国产av一区二区三区| 亚洲一区二区三区不卡在线播放| 男人的天堂亚洲一区二区三区| 国产福利一区二区三区在线观看 | 亚洲一区在线观看视频| 一区二区三区在线免费观看视频| 亚洲日韩一区精品射精| 日韩视频一区二区三区 | 正在播放国产一区| 精品亚洲AV无码一区二区| 中文字幕VA一区二区三区| 亚州国产AV一区二区三区伊在| 亚洲av无码一区二区三区天堂| 精品一区二区在线观看| 中文字幕无码一区二区三区本日| 蜜桃视频一区二区| 日韩一区二区三区在线精品| 正在播放国产一区| 国产婷婷色一区二区三区深爱网| 亚洲av综合av一区二区三区| 国产福利微拍精品一区二区| 亚洲福利一区二区三区| 97av麻豆蜜桃一区二区| 性色A码一区二区三区天美传媒 | 久久久91精品国产一区二区三区| 国产激情精品一区二区三区| 日韩精品一区二区三区中文字幕| 麻豆va一区二区三区久久浪| 国内精品一区二区三区最新| 精品国产区一区二区三区在线观看| 亚洲av无码一区二区三区人妖| 亚洲av无码一区二区三区天堂| 国精产品一区一区三区有限在线| 亚洲欧美国产国产一区二区三区| 国产精品毛片一区二区| 久久精品国产一区二区电影| 国产情侣一区二区三区| 中文字幕一精品亚洲无线一区|