Construction of internal and external network NPM private service (verdaccio) and upload of dependent package

Time:2021-3-3

Due to the company’s development based on the Intranet environment, all dependent packages must be copied from the Internet to the intranet, and when there are dependent package changes, they must be updated to the intranet synchronously, which undoubtedly reduces the development efficiency. In addition, we can also package and publish common development components in our own NPM warehouse to facilitate reuse.

1、 Global installation of verdaccio on external network

npm install -g verdaccio

First, start verdaccio and execute commands from any console

verdaccio

The following message appears to indicate that the installation was successful

warn --- config file  - /home/yg/.config/verdaccio/ config.yaml   //Location of configuration file
   warn --- Plugin successfully loaded: htpasswd 
   warn --- Plugin successfully loaded: audit 
   warn --- http address -  http://localhost : 4873 / - verdaccio / 3.10.1 // the default port is 4873

Enter address in browserhttp://localhost:4873/, start the service. This shows the components I uploaded before.

Construction of internal and external network NPM private service (verdaccio) and upload of dependent package

2 config.yaml Configuration description

#After the #, there are notes
#Cache directory for all packages
storage: ./storage
#Plug in directory
plugins: ./plugins

#Open the web service and access it through the web
web:
  # WebUI is enabled as default, if you want disable it, just uncomment this line
  #enable: false
  title: Verdaccio
#Verification information
auth:
  htpasswd:
    #User information storage directory
    file: ./htpasswd
    # Maximum amount of users allowed to register, defaults to "+inf".
    # You can set this to -1 to disable registration.
    #max_users: 1000

# a list of other known repositories we can talk to
#Configuration of public warehouse
uplinks:
  npmjs:
    url: https://registry.npmjs.org/

packages:
  '@*/*':
    # scoped packages
    access: $all
    publish: $authenticated

    #The agent said that if there is no warehouse, it will go to the npmjs to find it,
    #Npmjs points to https://registry.npmjs.org/  , which is the configuration of uplinks above
    proxy: npmjs

  '**':
    #Three identities: owner, anonymous user and authenticated (login) user
    # "$all", "$anonymous", "$authenticated"

    #Can I access the required permissions
    access: $all

    #Permission to publish package
    publish: $authenticated

    #If the package does not exist, a request is made to the upstream service of the agent
    proxy: npmjs

# To use `npm audit` uncomment the following section
middlewares:
  audit:
    enabled: true
#Monitoring port, key, do not configure this, can only access this function
listen: 0.0.0.0:4873
#Allow offline Publishing
publish:
  allow_offline: true
# log settings
logs:
  - {type: stdout, format: pretty, level: http}
  #- {type: file, path: verdaccio.log, level: info}

It is important to note that it must be configuredlisten: 0.0.0.0:4873Can run other machine to visit!!!
To publish dependent packages offline, you must set theallow_offline: true !!!

3、 Add user and set NPM image source

#The current NPM service points to the local 
npm set registry http://localhost:4873
#Registered users register a user locally, point to our address, and then we can publish the package
npm adduser --registry http://xxx:4873
Username: xxx
Password: xxx
Password:  xxx
Email: (this IS public) xxx 
Logged in as yg-ui on  http://xxx/  (your IP address)
At this time, we will register a user, we can use the user name and password to log in, go to the window above to log in

The next time we log in again, we just need to type in

npm login

Then enter the account password in turn, and check the current user.

npm who am i

Check whether the current user has logged in successfully

4、 Publish dependency package

First, you must set the mirror source:

npm set registry http://localhost:4873

In order to manage NPM source conveniently, it is recommended to installnrm, specific how to use here is not much introduction, you can directly Baidu.
Then, taking the vuecli3 library pattern as an example, we publish Vue components to private servers
1、 package.jsAdd a command to compile as library in

“lib”: “vue-cli-service build –target lib –name vcolorpicker –dest lib packages/index.js”

  • –Target: build target, default to application mode. Here, it is modified to enable library mode for lib.
  • –Dest: output directory, dist by default. Here we change to lib
  • [entry]: the last parameter is the entry file, which is SRC by default/ App.vue . Here we specify the compile packages / component library directory.

    In library mode, Vue is external, which means that even if Vue is introduced into the code, the packaged file does not contain Vue.
    If we introduce dependencylodashAnd other production environment must install the dependency library, we canvue.config.jsMedium configurationexternalProperty so that it does not package the corresponding dependency package.

   module.exports = {
      configureWebpack:{
          externals: {
             'vue': 'Vue',
             'vue-router':'VueRouter',
             'axios': 'axios',
             'lodash' : '\_'
          }
      }
   }

2. Configurationpackage.json

{
    "name": "packagename",
    "version": "0.1.5",
    "Description": "based on Vue component library,",
    "main": "lib/index.js",
    "keyword": "vcolorpicker colorpicker color-picker",
    "files": ['dist', 'page'],
    "private": false
  }

among

  • Private: must be set tofasle
  • Files: set the file directory to upload to NPM library
  • Main: project entry, which is the entry of the same level directory by defaultindex.js
  • Name: NPM package name, that’s usimport xxx from packagenamePackage name in

It’s understandableimport xxx from packagenamexxxIt’s introductionmainIn the entrancelib/index.jsThe name of the exposed variable.

3. Add.npmignoreFile, setting ignore publish file
andpackage.jsonOffilesAttribute, we publish to NPM, only compiledlibpackage.jsonREADME.mdIt’s the documents that need to be published. So we need to set ignore directories and files.
Grammar is the same.gitignoreThe syntax is the same, the specific need to submit what documents, depending on their actual situation.

#Ignore directory
examples/
packages/
public/
 
#Ignore specified file
vue.config.js
babel.config.js
*.map

4. Log in to NPM

npm login

The specific login process is the same as above.

5. Publish to NPM

npm publish

After execution, it shows that you can find your own package on the NPM private service if the publishing is successful. If the publishing is not successful, it may be that the package name or version is repeated. Just change the configuration.

5、 Construction of Intranet NPM private service

Copy the following corresponding external directory to the Intranet environment

File:C: \ \ users \ \ user name \ \ appdata \ \ roaming \ \ NPM \ \ verdaccio

File:C: \ \ users \ \ user name \ \ appdata \ \ roaming \ \ NPM\\ verdaccio.cmd

catalog:C: \ \ users \ \ user name \ \ appdata \ \ roaming \ \ NPM \ \ node\_ modules\\verdaccio

File:C: \ \ users \ \ user name \ \ appdata \ \ roaming \ \ verdaccio\\ config.yaml

catalog:C: \ \ users \ \ user name \ \ appdata \ \ roaming \ \ verdaccio \ \ storage

Note thatstorageThe directory is for storagenpmWhere it depends on the package,We can publish it on the Internet firstnpmThen copy the storage folder to the intranet, and then open the intranetverdaccioAddress, you can find that these dependent packages are automatically published to the intranet

There are two kinds of packages, one is the package developed by ourselves, the other is the open source package on the external network NPM. If you want to publish the open source package to your own private service, please pay attention to the following points (step on the pit)!) :

  • 1: To publishnpmDepending on the package, it’s best to use itnpmDownload, don’t use itcnpmBecausecnpmContains a variety of shortcuts, copy to other computers will have a variety of problems
  • 2: Pay attention to the information in the published NPM packagepackage.jsoIn nscriptDoes it containrepublishAnd so on,republishThe command will be executed before it is published, but often we do not have the environment to execute the command, so we report an error and we can delete it
  • 3: It is possible that other dependent packages are nested in the dependent package, and the subdirectory of the dependent package isnode_modulesTo view the dependency of a folder, you must publish it before publishing it. becausenode_modulesThe public version is extracted to the outermost layer of the dependency package, and the special version can only exist under the current directorynode_modulesfolder
  • 4: If you want to publish the specifiedpackage.jsonUnder normal circumstances, there are at least 100 dependent packages. It’s very hard for us to publish them manually. But,verdaccioIt doesn’t support one click Import, so we can only publish one by one. Here I wrote onenodeAuto readnode_modulesAnd automatically publish the dependency package to thenpmOfpublishThe document, for everyone to try!
const fs = require('fs');
const path = require('path');
const process = require('process');
//Methods of importing and executing console commands
const exec = require('child_process').execSync;
//Save root path
const rootPath = __dirname;
let result = fs.readdirSync(rootPath);
const consoleLogPath = path.join(rootPath, 'log');
result.forEach(fName => {
    const dPath = path.join(__dirname, fName);
    const stat = fs.statSync(dPath);
    if (stat.isDirectory()) {
        const modulePath = path.join(dPath, 'node_modules');
        if (!fs.existsSync(modulePath)) return;
        const statModules = fs.statSync(modulePath);
        if (statModules.isDirectory()) {
            const res = fs.readdirSync(modulePath)
            getVersion(res, consoleLogPath, modulePath, fName)
        }
    }
})

function getVersion(result, logPath, modulePath, fName) {
    result.forEach(item => {
        //Splicing current package path
        const dPath = path.join(modulePath, item);
        //Get the stat of the path
        const stat = fs.statSync(dPath);
        //Determine whether the package path is a directory
        if (stat.isDirectory()) {
            //If it is a directory, do the following
            //In the current package directory package.json File path
            const packageJsonPath = path.join(dPath, 'package.json');
            if (fs.existsSync(packageJsonPath)) {
                //Read the data in the current package directory package.json File content, return string
                const packageJsonContentString = fs.readFileSync(packageJsonPath, 'utf8');
                //Analysis package.json The contents of the file are objects in JSON format
                const parsedPackJson = JSON.parse(packageJsonContentString);
                if (parsedPackJson.scripts && Object.keys(parsedPackJson.scripts).length !== 0) {
                    parsedPackJson.scripts = {};
                    fs.writeFileSync(packageJsonPath, JSON.stringify(parsedPackJson));
                }
                //Switch the current directory to the current package path
                process.chdir(dPath);
                //Execute the command NPM publish under the package path
                try {
                    exec('npm publish');
                } catch {
                    console.log ('package ${fname}: ${item} has been published ');
                }
                //When the operation is completed, switch the current path to the original root directory
                process.chdir(rootPath);
                console.log(fName, parsedPackJson.name, parsedPackJson.version)
                //If the scripts attribute exists in the parsed object in JSON format and the attribute is not an empty object, set its content to an empty object
                fs.appendFileSync(logPath, `${fName} / ${parsedPackJson.name} /@${parsedPackJson.version}\n`);
            }
        }
    })
}

Reference documents

  1. Introduction to NPM module installation mechanism
  2. 《node_ Modules dilemma