json插件项目开发所需要的模块文件介绍

  前 言

  在每个项目的根目录下面,一般都会有一个 package.json 文件,其定义了运行项目所需要的各种依赖和项目的配置信息(如名称、版本、许可证等元数据)。

  大多数人对 package.json 文件的了解,仅停留在:

  项目名称、项目构建版本、许可证的定义;

  依赖定义(包括 dependencies 字段,devDependencies 字段);

  使用scripts字段指定运行脚本命令的 npm 命令行缩写。

  其实,package.json 的作用远不止于此,我们可以通过新增配置项实现更强大的功能,下面将带你重新认识 package.json。

  js 定义一个json对象_js 定义一个json对象_jquery 定义json对象

  简单版的 package.json

  当我们新建一个名称为 my-test 的项目时,使用 yarn init -y 或 npm init -y 命令后,在项目目录下会新增一个 package.json文件,内容如下:

  <pre class="code-snippet__js" data-lang="cs">{` "name": "my-test", # 项目名称 "version": "1.0.0", # 项目版本(格式:大版本.次要版本.小版本) "description": "", # 项目描述 "main": "index.js", # 入口文件 "scripts": { # 指定运行脚本命令的 npm 命令行缩写 "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], # 关键词 "author": "", # 作者 "license": "ISC" # 许可证}`</pre>

  可以看到,package.json 文件的内容是一个 JSON 对象,对象的每一个成员就是当前项目的一项配置。

  jquery 定义json对象_js 定义一个json对象_js 定义一个json对象

  安装项目依赖(dependencies & devDependencies)

  dependencies字段指定了项目运行所依赖的模块(生产环境使用),如 antd、 react、 moment等插件库:

  devDependencies 字段指定了项目开发所需要的模块(开发环境使用),如 webpack、typescript、babel等:

  如果一个模块不在 package.json 文件之中,我们可以单独安装这个模块,并使用相应的参数,将其写入 dependencies 字段/ devDependencies 字段中:

  <pre class="code-snippet__js" data-lang="sql"># 使用 npm`npm install --save # 写入 dependencies 属性npm install --save-dev # 写入 devDependencies 属性 # 使用 yarnyarn add # 写入 dependencies 属性`yarn add  --dev # 写入 devDependencies 属性</pre>

  有了 package.json 文件,开发直接使用 npm install / yarn install 命令,就会在当前目录中自动安装所需要的模块js 定义一个json对象,安装完成项目所需的运行和开发环境就配置好了。

  jquery 定义json对象_js 定义一个json对象_js 定义一个json对象

  简化终端命令(scripts)

  scripts 字段是 package.json 中的一种元数据功能,它接受一个对象,对象的属性为可以通过 npm run 运行的脚本,值为实际运行的命令(通常是终端命令),如:

  <pre class="code-snippet__js" data-lang="javascript">"scripts": {` "start": "node index.js"`},</pre>

  将终端命令放入 scripts 字段,既可以记录它们又可以实现轻松重用。

  jquery 定义json对象_js 定义一个json对象_js 定义一个json对象

  定义项目入口(main)

  main 字段是 package.json 中的另一种元数据功能,它可以用来指定加载的入口文件。假如你的项目是一个 npm 包,当用户安装你的包后,require('my-module') 返回的是 main 字段中所列出文件的 module.exports 属性。

  当不指定main 字段时,默认值是模块根目录下面的index.js 文件。

  jquery 定义json对象_js 定义一个json对象_js 定义一个json对象

  指定项目 node 版本(engines)

  有时候,新拉一个项目的时候,由于和其他开发使用的 node 版本不同,导致会出现很多奇奇怪怪的问题(如某些依赖安装报错、依赖安装完项目跑步起来等)。

  js 定义一个json对象_jquery 定义json对象_js 定义一个json对象

  为了实现项目开箱即用的伟大理想,这时候可以使用 package.json 的 engines 字段来指定项目 node 版本:

  <pre class="code-snippet__js" data-lang="javascript">"engines": {` "node": ">= 8.16.0"`},</pre>

  该字段也可以指定适用的 npm 版本:

  <pre class="code-snippet__js" data-lang="javascript">"engines": {` "npm": ">= 6.9.0"` },</pre>

  需要注意的是,engines属性仅起到一个说明的作用,当用户版本不符合指定值时也不影响依赖的安装。

  js 定义一个json对象_jquery 定义json对象_js 定义一个json对象

  自 定 义 命 令 (bin)

  用过 vue-cli,create-react-app等脚手架的朋友们,不知道你们有没有好奇过,为什么安装这些脚手架后,就可以使用类似 vue create/create-react-app之类的命令,其实这和 package.json 中的 bin 字段有关。

  bin 字段用来指定各个内部命令对应的可执行文件的位置。当package.json 提供了 bin 字段后,即相当于做了一个命令名和本地文件名的映射。

  当用户安装带有 bin 字段的包时,

  /usr/local/node_modules/.bin/;

  举个 ,如果要使用 my-app-cli 作为命令时,可以配置以下 bin 字段:

  <pre class="code-snippet__js" data-lang="javascript">"bin": {` "my-app-cli": "./bin/cli.js"`}</pre>

  上面代码指定,my-app-cli 命令对应的可执行文件为 bin 子目录下的 cli.js,因此在安装了 my-app-cli 包的项目中,就可以很方便地利用 npm执行脚本:

  <pre class="code-snippet__js" data-lang="css">"scripts": {` start: 'node node_modules/.bin/my-app-cli'`}</pre>

  jquery 定义json对象_js 定义一个json对象_js 定义一个json对象

  咦,怎么看起来和 vue create/create-react-app之类的命令不太像?原因:

  若要实现像 vue create/create-react-app之类的命令一样简便的方式,则可以在上文提到的 bin 子目录下可执行文件cli.js 中的第一行写入以下命令:

  <pre class="code-snippet__js" data-lang="javascript">#!/usr/bin/env node</pre>

  这行命令的作用是告诉系统用 node 解析,这样命令就可以简写成 my-app-cli 了。

  jquery 定义json对象_js 定义一个json对象_js 定义一个json对象

  React 项目相关

  设置应用根路径(homepage)

  当我们使用 create-react-app 脚手架搭建的 React 项目,默认是使用内置的 webpack 配置,当package.json 中不配置 homepage 属性时,build 打包之后的文件资源应用路径默认是 /,如下图:

  js 定义一个json对象_jquery 定义json对象_js 定义一个json对象

  一般来说,我们打包的静态资源会部署在 CDN 上,为了让我们的应用知道去哪里加载资源,则需要我们设置一个根路径js 定义一个json对象,这时可以通过 package.json 中的 homepage 字段设置应用的根路径。

  当我们设置了 homepage 属性后:

  <pre class="code-snippet__js" data-lang="json">{` "homepage": "https://xxxx.cdn/my-project",`}</pre>

  打包后的资源路径就会加上 homepage 的地址:

  js 定义一个json对象_jquery 定义json对象_js 定义一个json对象

  开发环境解决跨域问题(proxy)

  在做前后端分离的项目的时候,调用接口时则会遇到跨域的问题,当在开发环境中时,可以通过配置 package.json 中的 proxy 来解决跨域问题,配置如下:

  <pre class="code-snippet__js" data-lang="json">{` "proxy": "http://localhost:4000" // 配置你要请求的服务器地址`}</pre>

  注意,当 create-react-app 的版本高于 2.0 版本的时候在 package.json 中只能配置 string 类型,这意味着如果要使用 package.json 来解决跨域问题,则只能代理一个服务器地址。

  如果要代理多个服务器地址时,则需要安装 http-proxy-middleware ,在 src 目录下新建 setupProxy.js :

  <pre class="code-snippet__js" data-lang="php">const proxy = require("http-proxy-middleware");` module.exports = function(app) { app.use( proxy("/base", { target: "http://localhost:4000", changeOrigin: true }) ); app.use( proxy("/fans", { target: "http://localhost:5000", changeOrigin: true }) );};`</pre>

  根据开发环境采用不同的全局变量值(自定义字段)

  假设有这么一个组件,当组件被点击时,在开发环境时是跳转测试环境的 sentry 地址,在正式环境时则跳转正式环境的 sentry 地址。

  首先,通过配置前面提到的 scripts 字段,实现环境变量(NODE_ENV)的设置:

  <pre class="code-snippet__js" data-lang="javascript">"scripts": {` "start": "NODE_ENV=development node scripts/start.js", "build": "NODE_ENV=production node scripts/build.js",},`</pre>

  项目启动起来后,在代码中我们可以通过 process.env.NODE_ENV 访问到 NODE_ENV 的值。

  方案一

  我们可以在组件中写类似以下的判断代码,根据不同环境给 sentryUrl 设置不同的值:

  <pre class="code-snippet__js" data-lang="nginx">let sentryUrl;`if (process.env.NODE_ENV === 'development') { sentryUrl = 'test-sentry.xxx.com';} else { sentryUrl = 'sentry.xxx.com';}`</pre>

  这么做好像没毛病,但是深入一想,如果有多个组件,要根据不同的环境使用不同的服务(多种服务)地址,如果按照上面的写法,项目中将存在许多重复的判断代码,且当服务地址发生变化时,包含这些服务地址的组件都需要相应的做改动,这样明显是不合理的。

  jquery 定义json对象_js 定义一个json对象_js 定义一个json对象

  方案二

  解决方案:相关服务的地址配置在 package.json中,同时修改项目的 webpack 配置。

  注:修改项目的 webpack 配置需要 eject 项目的 webpack 配置。

  在项目根目录下使用 yarn eject 成功 eject 出配置后,可以发现项目目录的变化如下:

  jquery 定义json对象_js 定义一个json对象_js 定义一个json对象

  如果需要定制化项目,一般就是在 config 目录下对默认的 webpack 配置进行修改,在这里我们需要关注 config/path.js 和 config/env.js 两个文件:

  由于本文的重点不是学习 webpack 配置,这里仅介绍如何实现【根据开发环境采用不同的全局变量值】的功能。

  首先,需要在 package.json 中配置以下内容:

  <pre class="code-snippet__js" data-lang="javascript">"scripts": {` "start": "NODE_ENV=development node scripts/start.js", "build": "NODE_ENV=production node scripts/build.js",},"sentryPath": { "dev": "https://test-sentry.xxx.com", "prod": "https://sentry.xxx.com" }`</pre>

  然后,修改 path.js 文件,内容如下:

  <pre class="code-snippet__js" data-lang="javascript">// 重写 getPublicUrl 方法`const getPublicUrl = (appPackageJson, pathName) => { let path; switch (process.env.DEPLOY_ENV) { case 'development': path = require(appPackageJson)[pathName].dev; break; case 'production': path = require(appPackageJson)[pathName].prod; break; default: path = envPublicUrl || require(appPackageJson).homepage; } return path;} // 新增 getSentryPath 方法const getSentryPath = (appPackageJson) => { return getPublicUrl(appPackageJson, 'sentryPath');} // config after eject: we're in ./config/module.exports = { ..., sentryUrl: getSentryPath(resolveApp('package.json')), // 新增};` </pre>

  最后,修改 env.js 文件,内容如下:

  <pre class="code-snippet__js" data-lang="javascript">// 修改 getClientEnvironment 方法`function getClientEnvironment(publicUrl) { const raw = Object.keys(process.env) .filter(key => REACT_APP.test(key)) .reduce( (env, key) => { ... }, { NODE_ENV: process.env.NODE_ENV || 'development', PUBLIC_URL: publicUrl, SENTRY_URL: paths.sentryUrl // 新增 } ); const stringified = { ... }; return { raw, stringified };}` </pre>

  通过上面的配置,我们就可以在组件中通过 process.env.SENTRY_URL 获取到 sentry 服务的地址了,虽然看起来比方案一繁琐,但是这种收益是长期的,如要新增一个 sonarqube 服务,同理实现即可,通过使用 package.json 也可以清楚的看到当前服务在不同环境下使用的地址。

文章由官网发布,如若转载,请注明出处:https://www.veimoz.com/1939
0 评论
576

发表评论

!