preface

  • Under the root of each project, there is usually onepackage.json File that defines the various items needed to run the projectRely onAnd the project ofConfiguration information(such as name, version, license, and other metadata).

Most people’s knowledge of package.json files is limited to:

  • Definition of project name, project build version and license;

Dependency definitions (including dependencies field, devDependencies field); Use the scripts field to specify the NPM command line abbreviation to run the script command.

  • In fact,package.jsonWe can add new configuration items to achieve more powerful functions, which will be shown belowpackage.json.

Enrich your project’s package.json from simplicity to complexity

A simple version of package.json

  • When we create a new one calledmy-testWhen the project is usedyarn init -y 或 npm init -yCommand, a new one will be added to the project directorypackage.jsonFile, as follows:
{" name ":" my - test ", # project name "version" : "1.0.0", # project version (format: large version. Minor version) "description": "", # project description" main": "index.js", # entry file "scripts": {# specifies the NPM command line to run the script "test": "Echo \"Error: No test specified\" && exit 1"}," Keywords ": [], # keyword "author": "", # author": "ISC" # license}Copy the code
  • As you can see,package.jsonThe contents of the file are oneJSONObject, each member of which is a configuration item for the current project.

Install project Dependencies (Dependencies & devDependencies)

  • dependenciesField specifies the module (used in production) on which the project will run, as inantd,react,momentAnd other plug-in libraries:

They are the dependencies we need in our production environment. When we install the project as an NPM package, we only install the dependencies in dependencies.

  • devDependenciesField specifies the modules (used by the development environment) required for project development, such aswebpack,typescript,babelSuch as:

We don’t need these tools in the code package submission line, so we put them in devDependencies.

  • If a module is not therepackage.jsonFile, we can install the module separately, and use the corresponding parameters, write itdependenciesField /devDependenciesIn the field:
NPM install <package... > < span style = "box-sizing: border-box! Important; word-wrap: break-word! Important;" > < span style = "max-width: 100%; clear: both; min-height: 1em; > < span style = "box-sizing: border-box! Important; word-wrap: break-word! Important;" > --dev # writes the devDependencies propertyCopy the code
  • There are thepackage.jsonFiles developed directly for usenpm install / yarn installCommand, the required modules will be automatically installed in the current directory, and the runtime and development environment required to complete the installation will be configured.

Define project entry (Main)

  • mainThe fields arepackage.jsonIs another metadata facility that can be used to specify entry files to load. Suppose your project is anpmPackage, when the user installs your package,require('my-module')Returns themainOf the files listed in themodule.exportsProperties.
  • When not specifiedmainThe default value is under the module root directoryindex.jsFile.

Specify the Project Node version (Engines)

  • Sometimes, when a new project is pulled, due to the use of other developmentnodeDifferent versions lead to a lot of strange problems (such as some dependency installation errors, dependencies after the project runs, etc.).
  • To achieve the great ideal of a project out of the box, this can be usedpackage.json 的 enginesField to specify the project Node version:
"Engines ": {"node": ">= 8.16.0"},Copy the code
  • This field can also be specified as applicablenpmVersion:
"Engines ": {" NPM ": ">= 6.9.0"},Copy the code
  • Note that the Engines attribute serves only as an illustration and does not affect the installation of dependencies if the user version does not match the specified value.

Custom Command (bin)

  • The usedvue-cli.create-react-appAnd so scaffolding friends, I don’t know if you’ve ever wondered why after installing these scaffolds, you can use similarvue create/create-react-appOr something like that. Actually, it’s the samepackage.jsonIn thebinField about.
  • binField is used to specify the location of the executable file corresponding to each internal command. whenpackage.jsonprovidesbinThe command name is mapped to the local file name.
  • When the user installs withbinField when the package is installed globally,npmSymbolic links will be used to link these files to/usr/local/node_modules/.bin/; If it is installed locally, it will link to./node_modules/.bin/.
  • Take 🌰 if you want to usemy-app-cliWhen used as a command, you can configure the followingbinFields:
"bin": {
  "my-app-cli": "./bin/cli.js"
}
Copy the code
  • The code above specifies that,my-app-cliThe corresponding executable file isbinSubdirectorycli.js, so in the installationmy-app-cliPackage of projects, can be very easy to usenpmExecute the script:
"scripts": {
  start: 'node node_modules/.bin/my-app-cli'
}
Copy the code
  • Gee, how does it look likevue create/create-react-appOr something like that? Reason: When needednodeYou have to add it to the environmentnodePrefix if you addnodePrefix, you need to specifymy-app-cliThe path of the – > node_modules/.bin, otherwise,node my-app-cliWill look for the current pathmy-app-cli.jsIt can’t be right.
  • If you want to achieve the imagevue create/create-react-appAs simple as the command, can be mentioned abovebinExecutable files in a subdirectorycli.jsWrite the following command on the first line in:
#! /usr/bin/env nodeCopy the code
  • This command is used to tell the systemnodeParse, so that the command can be abbreviated asmy-app-cli.

React Project

Set the app root path (homepage)
  • When we usecreate-react-appscaffoldingReactProjects are built in by defaultwebpackThe configuration, whenpackage.jsonNot in the configurationhomepageProperty, the default file resource application path after the build package is /, as shown in the following figure:

  • Typically, the static resources we package are deployed inCDNIn order for our application to know where to load resources, we need to set a root pathpackage.jsonIn thehomepageField sets the root path of the application.

After we set the homepage property:

{
  "homepage": "https://xxxx.cdn/my-project",
}
Copy the code
  • The packaged resource path is addedhomepageAddress:

Development environment to solve cross-domain problems (Proxy)
  • Cross-domain problems can be encountered when interfaces are called when working on projects with separate front and back ends, which can be configured in a development environmentpackage.jsonIn theproxyTo solve the cross-domain problem, the configuration is as follows:
{"proxy": "http://localhost:4000" // configure the server address you want to request}Copy the code
  • Note that whencreate-react-appIs higher than version 2.0package.jsonCan only be configured.stringType, which means if you want to usepackage.jsonTo resolve cross-domain problems, only one server address can be proxy.
  • This is required if you want to proxy multiple server addresseshttp-proxy-middlewareIn thesrcCreating a DirectorysetupProxy.js :
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
    })
  );
};
Copy the code
Different global variable values (custom fields) depending on the development environment
  • Suppose you have a component that, when clicked, jumps to the test environment during developmentsentryAddress, which jumps to the formal environment in the formal environmentsentryAddress.
  • First, through the configuration mentioned earlierscriptsField to implement setting of the environment variable (NODE_ENV) :
"scripts": {
  "start": "NODE_ENV=development node scripts/start.js",
  "build": "NODE_ENV=production node scripts/build.js",
},
Copy the code
  • Once the project is up and running, in the code we can passprocess.env.NODE_ENVAccess to theNODE_ENVThe value of the.
Plan a
  • We can write judgement code in the component like the following, depending on the environmentsentryUrlSet different values:
let sentryUrl;
if (process.env.NODE_ENV === 'development') {
    sentryUrl = 'test-sentry.xxx.com';
} else {
    sentryUrl = 'sentry.xxx.com';
}
Copy the code
  • So well as the trouble, but deep thought, if there are multiple components, according to the different environment with different services (services) address, if written in accordance with the above, the project will have many repeat the judgment of the code, and when the service address changes, contains the service address components require corresponding change, this is obviously unreasonable.
Scheme 2
  • Solution: The address of the related service is configured inpackage.jsonAt the same time modify the projectwebpackConfiguration.
  • Note: modify the itemwebpackConfiguration required for the eject projectwebpackConfiguration (more details are available at 👉 :React + typescript project customization process).
  • Use in the project root directoryyarn ejectAfter successfully eject the configuration, you can see the following changes in the project directory:

  • If you need to customize your project, it is usually done inconfigDirectory under the defaultwebpackConfiguration changes are made, and we need to pay attention hereconfig/path.js 和 config/env.jsTwo files:

The main purpose of env.js is to read the env configuration file and give the env configuration information to the global variable process.env; The main purpose of path.js is to provide various paths for projects, including build paths, public paths, and so on.

  • Because the focus of this article is not studywebpackConfiguration, here only describes how to implement the function of using different global variable values according to the development environment.
  • First of all, you need to bepackage.jsonSet the following parameters:
"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"
 }
Copy the code
  • And then, modifypath.jsFile, as follows:
// 重写 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')), // 新增
};

Copy the code
  • Finally, modify the env.js file as follows:
Function getClientEnvironment(publicUrl) {const raw = object.keys (process.env) .filter(key => REACT_APP.test(key)) .reduce( (env, key) => { ... }, {NODE_ENV: process. The env. NODE_ENV | | 'development', PUBLIC_URL: publicUrl, SENTRY_URL: paths. SentryUrl / / new}); const stringified = { ... }; return { raw, stringified }; }Copy the code
  • With the above configuration, we can pass through the componentprocess.env.SENTRY_URLAccess to thesentryThe address of the service, although it looks more complicated than the scheme, but this benefit is long-term, such as to add a new onesonarqubeService, the same can be achieved by usingpackage.jsonYou can also clearly see the address used by the current service in different environments.

Original address :juejin.cn/post/684490…