通常使用脚手架构建,并搭配打包/打包less、代码编译器、代码检查及格式化的工具。

一、理解 package.json

name 项目名称

  • name 和 version 字段,是 package.json 必填的。
  • 名称和版本一起构成一个标识符,该标识符被认为是完全唯一的。对包的更改应该与对版本的更改一起进行。

规则:

  • 必须小于等于214个字符,不能以.或_开头,不能有大写字母,
    • 因为名称最终成为URL、命令行参数和文件夹名称的一部分,因此不能包含任何非URL安全字符。

建议:

  • 不要使用与核心节点模块相同的名称。
  • 不要在名称中加js或node。如果需要可以使用engines来指定运行环境。
  • 该名称可能会作为参数传递给 require(),因此它应该是简短的,但也需要具有合理的描述性。

version 语义化版本

version:一般的格式是x.x.x, 并且需要遵循语义化版本 (semver, Semantic Versioning) 规则。版本必须可由 node-semver 解析,它与 npm 作为依赖项捆绑在一起

语义化版本格式:主版本号.次版本号.修订号,递增规则如下:

  • major 主版本号:当你做了不兼容的 API 修改,
  • minor 次版本号:当你做了向下兼容的功能性新增,
  • patch 修订号:当你做了向下兼容的问题修正。

先行版本号及版本编译信息可以加到“主版本号.次版本号.修订号”的后面,作为延伸。

版本范围是一组比较器,它们指定满足范围的版本。比较器由运算符和版本组成。

原始比较器

  • < 小于
  • <= 小于或等于
  • 大于

  • = 大于或等于

  • = 相等。 如果未指定运算符,则假定相等,因此此运算符是可选的,但可以包含。

    高级范围语法

    高级范围语法以确定的方式对原始比较器进行脱糖。
    高级范围可以以与使用空白或 || 的原始比较器相同的方式组合。

连字符范围 X.Y.Z - A.B.C

1.2.3 - 2.3.4 := >=1.2.3 <=2.3.4
1.2 - 2.3.4 := >=1.2.0 <=2.3.4
1.2.3 - 2.3 := >=1.2.3 <2.4.0-0
1.2.3 - 2 := >=1.2.3 <3.0.0-0

X 范围 1.2.x 1.X 1.2.

X、x 或 中的任何一个都可以用来“代替”[major, minor, patch] 元组中的一个数值。
`
:=>=0.0.0(任何非预发布版本都满足,除非指定了 includePrerelease,在这种情况下任何版本都满足)<br />1.x:=>=1.0.0 <2.0.0-0`(匹配主要版本)
1.2.x := >=1.2.0 <1.3.0-0(匹配主要和次要版本)
部分版本范围被视为 X-Range,因此特殊字符实际上是可选的。
"" := * := >=0.0.0
1:= 1.x.x := >=1.0.0 <2.0.0-0
1.2 := 1.2.x := >=1.2.0 <1.3.0-0

波浪号范围 ~1.2.3 ~1.2 ~1

表示大约相当于某版本

如果在比较器上指定了次要版本,则允许补丁级别的更改。 如果没有,则允许进行次要级别的更改。
~1.2.3 := >=1.2.3 <1.(2+1).0 := >=1.2.3 <1.3.0-0
~1.2 := >=1.2.0 <1.(2+1).0 := >=1.2.0 <1.3.0-0 (与 1.2.x 相同)
~1 := >=1.0.0 <(1+1).0.0 := >=1.0.0 <2.0.0-0 (与 1.x 相同)
~0 := >=0.0.0 <(0+1).0.0 := >=0.0.0 <1.0.0-0 (与 0.x 相同)
~1.2.3-beta.2 := >=1.2.3-beta.2 <1.3.0-0 请注意,如果 1.2.3 版本大于或等于 beta.2,则允许预发布。 因此,允许使用 1.2.3-beta.4,但不允许使用 1.2.4-beta.2,因为它是不同 [major, minor, patch] 元组的预发布。

插入符范围 ^1.2.3 ^0.2.5 ^0.0.4

表示与某版本兼容

允许不修改 [major, minor, patch] 元组中最左边的非零元素的更改。换言之,这允许对 1.0.0 及更高版本进行补丁和次要更新,对 0.X >=0.1.0 版本进行补丁更新,对 0.0.X 版本不进行更新

许多作者将 0.x 版本视为 x 是主要的“重大变化”指标:
当作者可能在 0.2.4 和 0.3.0 版本之间进行重大更改时,插入符范围是理想的,这是一种常见的做法。但是,它假定 0.2.4 和 0.2.5 之间不会有重大变化。根据普遍观察到的实践,它允许被假定为附加(但非破坏性)的更改。

^1.2.3 := >=1.2.3 <2.0.0-0
^0.2.3 := >=0.2.3 <0.3.0-0
^0.0.3 := >=0.0.3 <0.0.4-0

main 入口点(模块ID)

  • 若您的包名为 foo,且用户安装了它,然后执行了 require(“foo”),那么您的主模块的导出对象将被返回。
  • 这应该是相对于包文件夹根目录的模块 ID。

main字段指定了加载的入口文件,require导入的时候就会加载这个文件。默认值是模块根目录下面的index.js

bin 可执行文件位置

  • 许多软件包都有一个或多个可执行文件,他们希望将它们安装到 PATH 中。
  • 要使用它,请在 package.json 中提供一个 bin 字段,它是命令名称到本地文件名的映射。安装时,npm 会将该文件符号链接到 prefix/bin 用于全局安装,或 ./node_modules/.bin/ 用于本地安装。

bin项用来指定每个内部命令对应的可执行文件的位置。
在模块以依赖的方式被安装,如果存在bin选项。在node_modules/.bin/生成对应的文件,
Npm会寻找这个文件,在node_modules/.bin/目录下建立符号链接。由于node_modules/.bin/目录会在运行时加入系统的PATH变量,因此在运行npm时,就可以不带路径,直接通过命令来调用这些脚本

所有node_modules/.bin/目录下的命令,都可以用npm run [命令]的格式运行。在命令行下,键入npm run,然后按tab键,就会显示所有可以使用的命令。

scripts 脚本

scripts指定了运行脚本命令的npm命令行缩写,比如start指定了运行npm run start时,所要执行的命令。

  1. "scripts": {
  2. "start": "node ./start.js"
  3. }

复制代码
使用scripts字段可以快速的执行shell命令,可以理解为alias。
scripts可以直接使用node_modules中安装的模块,这区别于直接运行需要使用npx命令。

  1. "scripts": {
  2. "build": "webpack"
  3. }
  4. // npm run build
  5. // npx webpack

config 配置

config字段用于添加命令行的环境变量。

  1. {
  2. "name" : "yindong",
  3. "config" : { "port" : "8080" },
  4. "scripts" : { "start" : "node server.js" }
  5. }

然后,在server.js脚本就可以引用config字段的值。

  1. console.log(process.env.npm_package_config_port); // 8080

用户可以通过npm config set来修改这个值。

  1. npm config set yindong:port 8000

dependencies 依赖

项目运行所依赖的模块。安装依赖的时候使用—save 参数表示将该模块写入dependencies属性。

对象由各自的模块名和对应的版本要求组成,表示依赖的模块及其版本范围。

devDependencies 开发依赖

项目开发所需要的模块。安装依赖的时候使用—save-dev 或 -D 参数表示将该模块写入devDependencies属性。

对象由各自的模块名和对应的版本要求组成,表示依赖的模块及其版本范围

  1. "devDependencies": {
  2. "standard-version": "^7.0.0",
  3. "less": "2.x",
  4. }

常见版本范围:

  • 固定版本: 比如5.38.1,安装时只安装指定版本。
  • 波浪号: 比如~5.38.1, 表示安装5.38.x的最新版本(不低于5.38.1),但是不安装5.39.x,也就是说安装时不改变主版本号和次要版本号
  • 插入号: 比如ˆ5.38.1, ,表示安装5.x.x的最新版本(不低于5.38.1),但是不安装6.x.x,也就是说安装时不改变主版本号
  • latest: 安装最新版本。

需要注意的是,如果大版本号为0,则插入号的行为与波浪号相同,这是因为此时处于开发阶段,即使是次要版本号变动,也可能带来程序的不兼容。

proxy 代理字段

Creat React App 的代理设置

Creat React App 的代理设置依赖库 react-scripts。package.json 中代理字段用于告诉开发服务器将任何未知请求代理到开发中的 API 服务器

  1. "proxy": "http://localhost:4000"

这样,当您在开发中 fetch(‘/api/todos’) 时,开发服务器将识别出它不是静态资产,并将您的请求代理到 [http://localhost:4000/api/todos](http://localhost:4000/api/todos) 作为后备。

方便地,这避免了开发中的 CORS 问题和错误消息:

  1. Fetch API cannot load http://localhost:4000/api/todos.
  2. No 'Access-Control-Allow-Origin' header is present on the requested resource.
  3. Origin 'http://localhost:3000' is therefore not allowed access.
  4. If an opaque response serves your needs,
  5. set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
  • 代理仅在开发中有效,您可以确保 /api/todos 之类的 URL 指向生产中的正确内容。 您不必使用 /api 前缀。 任何没有 text/html 接受标头的无法识别的请求都将被重定向到指定的代理。
  • 代理选项支持 HTTP、HTTPS 和 WebSocket 连接。

如果代理选项对您来说不够灵活,您也可以:

  • 自己配置代理:

    • 安装 http-proxy-middleware 代理中间件,直接访问 Express 应用程序实例并连接您自己的代理中间件

      1. $ npm install http-proxy-middleware --save
      2. $ # or
      3. $ yarn add http-proxy-middleware
    • 接下来,创建 src/setupProxy.js 并将以下内容放入其中,可以根据需要注册代理了 ```javascript const { createProxyMiddleware } = require(‘http-proxy-middleware’);

module.exports = function(app) { app.use( ‘/api’, createProxyMiddleware({ target: ‘http://localhost:5000‘, // target host changeOrigin: true, // needed for virtual hosted sites }) ); };

  1. - 在你的服务器上启用 CORS(这里是如何为 Express 做的)。
  2. ```javascript
  3. // express 示例
  4. app.use(function(req, res, next) {
  5. // update to match the domain you will make the request from
  6. res.header("Access-Control-Allow-Origin", "YOUR-DOMAIN.TLD");
  7. res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  8. next();
  9. });

二、理解跨域代理

开发环境跨域代理

Vue Cli 的代理设置

vue.config.js 中 devServer 类似 webpack-dev-server 的选项,其中的 devServer.proxy 字段可以是一个指向开发环境 API 服务器的字符串:

  1. module.exports = {
  2. devServer: {
  3. proxy: 'http://localhost:4000'
  4. }
  5. }

这会告诉开发服务器将任何未知请求 (没有匹配到静态文件的请求) 代理到http://localhost:4000

如果你想要更多的代理控制行为,也可以使用一个 path: options 成对的对象。完整的选项可以查阅 http-proxy-middleware

  1. module.exports = {
  2. devServer: {
  3. proxy: {
  4. '/api': {
  5. target: '<url>', // target host
  6. ws: true, // proxy websockets
  7. changeOrigin: true // needed for virtual hosted sites
  8. },
  9. '/foo': {
  10. target: '<other_url>'
  11. }
  12. }
  13. }
  14. }

注意:

  • 代理只对 devServer 配置中的端口请求生效;axios 中 baseURL 如果被配置过,此时proxy代理不生效
  • 对于 pageRewrite : 前端请求代理时添加 api 标记,若接口本身无 api 开头前缀则需将请求 path 前缀重写为 ‘’ 或 ‘/‘,详情参考
    1. '/api/': {
    2. // 要代理的地址
    3. target: 'http://localhost:8100',
    4. // 配置了这个可以从 http 代理到 https
    5. // 依赖 origin 的功能可能需要这个,比如 cookie
    6. changeOrigin: true,
    7. // 前端请求代理时添加 api 开头标记
    8. // 若后端接口本身无 api 开头则需将 api 开头的 path 重写为 '' 或 '/'
    9. pathRewrite: { '^/api': '' },
    10. },

生产环境跨域代理

代理:通常用于在多个服务器之间分配负载,无缝显示来自不同网站的内容,或通过 HTTP 以外的协议将处理请求传递给应用程序服务器。

正向代理:为了向服务器获取数据,客户端要向代理服务器发送一个请求,并指定目标服务器,代理服务器将目标服务器返回的数据转交给客户端。正向代理代理的是客户端

反向代理:客户端对代理是无感知的,将请求发送到反向代理服务器,由反向代理服务器去选择目标服务器获取数据后,返回给客户端。此时反向代理服务器和目标服务器对外就是一个服务器,暴露的是代理服务器地址,隐藏了真实服务器IP地址。反向代理代理服务器

上线后,通过 nginx 配置反向代理。通过不同的协议将请求从 NGINX 传递到代理服务器,修改发送到代理服务器的客户端请求标头,以及配置来自代理服务器的响应的缓冲。

  1. # Upstream模块实现负载均衡
  2. upstream mysvr {
  3. server localhost:10001;
  4. server localhost:10002;
  5. server 192.168.10.121:3333 backup; #热备
  6. }
  7. server {
  8. listen 5566; # 提供服务的端口,默认80
  9. server_name localhost; # 提供服务的域名主机名
  10. location ~*^.+$ { #请求的url过滤,~*为不区分大小写。
  11. root html # 站点的根目录,相当于Nginx的安装目录
  12. index index.html index.htm # 默认的首页文件,多个用空格分开
  13. proxy_pass http://mysvr; #请求转向mysvr 定义的服务器列表
  14. deny 127.0.0.1; #拒绝的ip
  15. allow 172.18.5.54; #允许的ip
  16. }
  17. }

通过该配置,访问nginx地址 http://localhost:5566 的请求会被转发到 mysvr 服务地址。实际使用中,可将请求转发到本机另一个服务器上,也可以根据访问的路径跳转到不同端口的服务中

proxy_pass 传递请求给代理服务器

要将请求传递给 HTTP 代理服务器,需要在 location 内指定 proxy_pass 指令:

  1. location /some/path/ {
  2. proxy_pass http://www.example.com/link/;
  3. }

此地址可以指定为域名或 IP 地址,可能包含端口。

  • proxy_pass 指令也可指向一组命名的服务器。 在这种情况下,请求根据指定的方法在组中的服务器之间分发
  • proxy_pass后面的url加/,表示绝对根路径;如果没有/,表示相对路径,把匹配的路径部分也给代理走

proxy_set_header 传递请求标头

默认情况下,NGINX 会重新定义代理请求中的两个 header 字段,“Host”设置为 $proxy_host 变量,“Connection”设置为关闭。并消除值为空字符串的 header 字段。

要更改这些设置以及修改其他标头字段,请使用 proxy_set_header 指令,该指令可在某个位置、更高位置、特定的服务器上下文或 http 块中指定。要防止标头字段被传递到代理服务器,请将其设置为空字符串:

  1. location /some/path/ {
  2. proxy_set_header Host $host;
  3. proxy_set_header X-Real-IP $remote_addr;
  4. proxy_set_header Accept-Encoding "";
  5. proxy_pass http://localhost:8000;
  6. }

proxy_bind 选择传出 IP 地址

如果您的代理服务器有多个网络接口,有时您可能需要选择一个特定的源 IP 地址来连接到代理服务器或上游。 如果 NGINX 后面的代理服务器配置为接受来自特定 IP 网络或 IP 地址范围的连接,这可能很有用。

指定 proxy_bind 指令和必要网络接口的 IP 地址:

  1. location /app1/ {
  2. proxy_bind 127.0.0.1;
  3. proxy_pass http://example.com/app1/;
  4. }
  5. location /app2/ {
  6. proxy_bind 127.0.0.2;
  7. proxy_pass http://example.com/app2/;
  8. }

参考资料