跳到主要内容

6 篇博文 含有标签「node」

查看所有标签

在离线服务器上安装 Node 模块

· 阅读需 7 分钟
1adybug
子虚伊人

最近有需求,需要在一台离线服务器上安装 node_modules,尝试了以下办法:

  1. 直接在外网 Windows 11 上将依赖安装好,将整个项目进行压缩,然后传输到离线服务器上,再进行解压。结果失败,因为某些包会执行 postinstall 脚本,编译一些系统相关的代码,导致失败。
  2. 先试用 npm install 安装依赖,然后使用 package-lock.json 文件将整个项目的依赖树全部下载成 tgz 文件,然后在内网执行 npm install --no-registry --cache ./npm-cache --prefer-offline 安装依赖。结果失败,原因未知。
  3. WSL 中创建与离线服务器相同的系统环境,然后执行 npm install 安装依赖。打包再解压,依旧失败,与方法 1 相同,依旧提示缺少某些依赖。

最后一个办法是使用 verdaccio 搭建一个私有仓库。

安装 verdaccio

这里使用 docker 安装 verdaccio,因为部署起来比较方便。

docker run -d --name verdaccio -p 4873:4873 verdaccio/verdaccio

或者进行目录挂载

docker run -d --name verdaccio -p 4873:4873 -v /path/to/verdaccio/conf:/verdaccio/conf -v /path/to/verdaccio/storage:/verdaccio/storage verdaccio/verdaccio

这里有两种选择,一种是将仓库数据挂载到 docker 容器中,一种是直接将仓库数据挂载到本地。

第一种方法,需要每次都将容器导出为新的镜像,然后推送到离线服务器上。

第二种方法,直接将仓库数据挂载到本地,然后每次启动容器时,将本地仓库数据挂载到容器中,需要注意的是,必须先使用第一种方法,先从容器中导出默认的配置文件,放在 /path/to/verdaccio/conf 目录下,或则复制下方配置文件 config.yaml/path/to/verdaccio/conf 目录下,否则容器会报错。

#
# This is the default configuration file. It allows all users to do anything,
# please read carefully the documentation and best practices to
# improve security.
#
# Do not configure host and port under `listen` in this file
# as it will be ignored when using docker.
# see https://verdaccio.org/docs/en/docker#docker-and-custom-port-configuration
#
# Look here for more config file examples:
# https://github.com/verdaccio/verdaccio/tree/6.x/conf
#
# Read about the best practices
# https://verdaccio.org/docs/best

# path to a directory with all packages
storage: /verdaccio/storage/data
# path to a directory with plugins to include
plugins: /verdaccio/plugins

# https://verdaccio.org/docs/webui
web:
title: Verdaccio
# comment out to disable gravatar support
# gravatar: false
# by default packages are ordercer ascendant (asc|desc)
# sort_packages: asc
# convert your UI to the dark side
# darkMode: true
# html_cache: true
# by default all features are displayed
# login: true
# showInfo: true
# showSettings: true
# In combination with darkMode you can force specific theme
# showThemeSwitch: true
# showFooter: true
# showSearch: true
# showRaw: true
# showDownloadTarball: true
# HTML tags injected after manifest <scripts/>
# scriptsBodyAfter:
# - '<script type="text/javascript" src="https://my.company.com/customJS.min.js"></script>'
# HTML tags injected before ends </head>
# metaScripts:
# - '<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>'
# - '<script type="text/javascript" src="https://browser.sentry-cdn.com/5.15.5/bundle.min.js"></script>'
# - '<meta name="robots" content="noindex" />'
# HTML tags injected first child at <body/>
# bodyBefore:
# - '<div id="myId">html before webpack scripts</div>'
# Public path for template manifest scripts (only manifest)
# publicPath: http://somedomain.org/

# https://verdaccio.org/docs/configuration#authentication
auth:
htpasswd:
file: /verdaccio/storage/htpasswd
# Maximum amount of users allowed to register, defaults to "+infinity".
# You can set this to -1 to disable registration.
# max_users: 1000
# Hash algorithm, possible options are: "bcrypt", "md5", "sha1", "crypt".
# algorithm: bcrypt # by default is crypt, but is recommended use bcrypt for new installations
# Rounds number for "bcrypt", will be ignored for other algorithms.
# rounds: 10

# https://verdaccio.org/docs/configuration#uplinks
# a list of other known repositories we can talk to
uplinks:
npmjs:
url: https://registry.npmmirror.com/

# Learn how to protect your packages
# https://verdaccio.org/docs/protect-your-dependencies/
# https://verdaccio.org/docs/configuration#packages
packages:
"@*/*":
# scoped packages
access: $all
publish: $authenticated
unpublish: $authenticated
proxy: npmjs

"**":
# allow all users (including non-authenticated users) to read and
# publish all packages
#
# you can specify usernames/groupnames (depending on your auth plugin)
# and three keywords: "$all", "$anonymous", "$authenticated"
access: $all

# allow all known users to publish/publish packages
# (anyone can register by default, remember?)
publish: $authenticated
unpublish: $authenticated

# if package is not available locally, proxy requests to 'npmjs' registry
proxy: npmjs

# To improve your security configuration and avoid dependency confusion
# consider removing the proxy property for private packages
# https://verdaccio.org/docs/best#remove-proxy-to-increase-security-at-private-packages

# https://verdaccio.org/docs/configuration#server
# You can specify HTTP/1.1 server keep alive timeout in seconds for incoming connections.
# A value of 0 makes the http server behave similarly to Node.js versions prior to 8.0.0, which did not have a keep-alive timeout.
# WORKAROUND: Through given configuration you can workaround following issue https://github.com/verdaccio/verdaccio/issues/301. Set to 0 in case 60 is not enough.
server:
keepAliveTimeout: 60
# Allow `req.ip` to resolve properly when Verdaccio is behind a proxy or load-balancer
# See: https://expressjs.com/en/guide/behind-proxies.html
# trustProxy: '127.0.0.1'

# https://verdaccio.org/docs/configuration#offline-publish
# publish:
# allow_offline: false

# https://verdaccio.org/docs/configuration#url-prefix
# url_prefix: /verdaccio/
# VERDACCIO_PUBLIC_URL='https://somedomain.org';
# url_prefix: '/my_prefix'
# // url -> https://somedomain.org/my_prefix/
# VERDACCIO_PUBLIC_URL='https://somedomain.org';
# url_prefix: '/'
# // url -> https://somedomain.org/
# VERDACCIO_PUBLIC_URL='https://somedomain.org/first_prefix';
# url_prefix: '/second_prefix'
# // url -> https://somedomain.org/second_prefix/'

# https://verdaccio.org/docs/configuration#security
# security:
# api:
# legacy: true
# # recomended set to true for older installations
# migrateToSecureLegacySignature: true
# jwt:
# sign:
# expiresIn: 29d
# verify:
# someProp: [value]
# web:
# sign:
# expiresIn: 1h # 1 hour by default
# verify:
# someProp: [value]

# https://verdaccio.org/docs/configuration#user-rate-limit
# userRateLimit:
# windowMs: 50000
# max: 1000

# https://verdaccio.org/docs/configuration#max-body-size
# max_body_size: 10mb

# https://verdaccio.org/docs/configuration#listen-port
# listen:
# - localhost:4873 # default value
# - http://localhost:4873 # same thing
# - 0.0.0.0:4873 # listen on all addresses (INADDR_ANY)
# - https://example.org:4873 # if you want to use https
# - "[::1]:4873" # ipv6
# - unix:/tmp/verdaccio.sock # unix socket

# The HTTPS configuration is useful if you do not consider use a HTTP Proxy
# https://verdaccio.org/docs/configuration#https
# https:
# key: ./path/verdaccio-key.pem
# cert: ./path/verdaccio-cert.pem
# ca: ./path/verdaccio-csr.pem

# https://verdaccio.org/docs/configuration#proxy
# http_proxy: http://something.local/
# https_proxy: https://something.local/

# https://verdaccio.org/docs/configuration#notifications
# notify:
# method: POST
# headers: [{ "Content-Type": "application/json" }]
# endpoint: https://usagge.hipchat.com/v2/room/3729485/notification?auth_token=mySecretToken
# content: '{"color":"green","message":"New package published: * {{ name }}*","notify":true,"message_format":"text"}'

middlewares:
audit:
enabled: true

# https://verdaccio.org/docs/logger
# log settings
log: { type: stdout, format: pretty, level: http }
#experiments:
# # support for npm token command
# token: false
# # enable tarball URL redirect for hosting tarball with a different server, the tarball_url_redirect can be a template string
# tarball_url_redirect: 'https://mycdn.com/verdaccio/${packageName}/${filename}'
# # the tarball_url_redirect can be a function, takes packageName and filename and returns the url, when working with a js configuration file
# tarball_url_redirect(packageName, filename) {
# const signedUrl = // generate a signed url
# return signedUrl;
# }

# translate your registry, api i18n not available yet
# i18n:
# list of the available translations https://github.com/verdaccio/verdaccio/blob/master/packages/plugins/ui-theme/src/i18n/ABOUT_TRANSLATIONS.md
# web: en-US

按需选择。

配置 verdaccio

主要是将 npmjs 的地址改为国内的镜像地址,或者直接将 npmjs 的地址改为离线服务器地址。

uplinks:
npmjs:
url: https://registry.npmmirror.com/

重新安装依赖

  1. 删除 node_modules 文件夹

    npx rimraf node_modules
  2. 删除 package-lock.json 文件

  3. 删除 npm 缓存,这一步非常重要,否则某些依赖可能会无法被缓存到 verdaccio 中

    npm cache clean --force
  4. 安装依赖

    npm install --registry http://localhost:4873

离线环境安装

  1. 部署 docker 容器

  2. 安装依赖

    npm install --registry http://localhost:4873

非 npm 包安装

有一些依赖并非通过 npm 发布,而是自己的渠道,这时可以执行以下方案:

  1. 下载并解压 tgz 文件

  2. 执行 npm addUser --registry http://localhost:4873 登录

  3. 在项目根目录执行 npm publish --registry http://localhost:4873 发布

  4. 在内网环境中的 package.json 中添加以下配置:

    "overrides": {
    "your-package": "npm:your-package@version"
    }
  5. 安装依赖

使用 Node.js 作为 Next.js 中间件的运行时

· 阅读需 1 分钟
1adybug
子虚伊人

Next.js 中,如果你在中间件使用了 Node.jsAPI, 那么可能会产生以下报错

Error: The edge runtime does not support Node.js 'crypto' module.

解决方法如下:

  1. 安装 next@canary

  2. next.config.ts 中添加以下配置

    import { NextConfig } from "next"

    const nextConfig: NextConfig = {
    experimental: {
    nodeMiddleware: true,
    },
    }

    export default nextConfig
  3. middleware.ts 中添加以下配置

    export const runtime = "nodejs"

当然,最好的做法是不使用 Node.js 作为中间件的运行时,而是使用 Edge 作为中间件的运行时,尽量使用 Edge 的 API 来实现中间件的功能。

修改 nvm 源为淘宝镜像

· 阅读需 1 分钟
1adybug
子虚伊人

仅限 windows 版,一共两种方法:

修改文件

nvm 的安装路径下,找到 settings.txt 文件,设置 node_mirrornpm_mirror 为国内镜像地址,在文件末尾加入:

阿里云镜像

node_mirror: https://npmmirror.com/mirrors/node/
npm_mirror: https://npmmirror.com/mirrors/npm/

腾讯云镜像

node_mirror: http://mirrors.cloud.tencent.com/npm/
npm_mirror: http://mirrors.cloud.tencent.com/nodejs-release/

命令行

阿里云镜像

nvm npm_mirror https://npmmirror.com/mirrors/npm/
nvm node_mirror https://npmmirror.com/mirrors/node/

腾讯云镜像

nvm npm_mirror http://mirrors.cloud.tencent.com/npm/
nvm node_mirror http://mirrors.cloud.tencent.com/nodejs-release/

在开发环境中使用 https

· 阅读需 1 分钟
1adybug
子虚伊人

现在很多环境下的网络请求要求必须是 https 请求,但是在开发或者内网环境下,无法使用 CA 机构颁发的证书,这时候可以使用 OpenSSL 提供的自签证书功能:

安装

在 windows 系统下,可以使用 winget 来安装第三方分发版本:

winget search openssl
# 选择一个版本较新的分发版本
winget install FireDaemon.OpenSSL

重启终端

生成证书

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout your-key.pem -out your-cert.pem

使用

import { readFileSync } from "fs"
import { createServer } from "https"

import express from "express"

const app = express()

const server = createServer(
{
key: readFileSync("your-key.pem"),
cert: readFileSync("your-cert.pem"),
},
app,
)

server.listen(3000)

在 Node.js 中使用 fetch 请求接口可能会报错:

TypeError: fetch failed
at Object.fetch (node:internal/deps/undici/undici:11730:11)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
cause: Error: self-signed certificate
at TLSSocket.onConnectSecure (node:_tls_wrap:1674:34)
at TLSSocket.emit (node:events:514:28)
at TLSSocket._finishInit (node:_tls_wrap:1085:8)
at ssl.onhandshakedone (node:_tls_wrap:871:12) {
code: 'DEPTH_ZERO_SELF_SIGNED_CERT'
}
}

指定环境变量 NODE_TLS_REJECT_UNAUTHORIZED='0' 即可

npx cross-env NODE_TLS_REJECT_UNAUTHORIZED='0' node index.js

从 node-fetch 的响应中获取 readable

· 阅读需 1 分钟
1adybug
子虚伊人

node-fetchresponse.body 虽然类型标记为 ReadableStream,但实际上并不是,被 Readable.fromweb 调用时会报错,此时改为使用 Readable.from 即可成功。

import fetch from "node-fetch"

const response = await fetch("http://somewhere.com")

// ❌ 会报错
const readable = Readable.fromweb(response.body!)

// ✅ 不会报错
const readable = Readable.from(response.body!)