How to set up the NPM repository

There are two main schemes: CNPM and Verdaccio the following shows the specific process of using CNPM scheme

1. Preparation

  • Linux server and Node environment
  • The Mysql database

2. Install the cnpmjs.org

  • Install cnpmjs.org using Git on the server
git clone https://github.com/cnpm/cnpmjs.org.git
Copy the code
  • Installation project dependencies
cd ./cnpmjs.org
npm i // cnpm i
Copy the code

3. Initialize the database

Cnpmjs.org project docs directory has prepared for us to create the database script db.sql, copy and execute in mysql

cat ./docs/db.sql
Copy the code

4. Perform initial configuration

vim ./config/index.js
Copy the code

There are many configuration items for CNPM, and some important ones are listed below

{enableCluster: specifies whether to start services in cluster-worker mode. The default value is false and the value is recommended for production. RegistryPort: API dedicated Registry service port, default 7001; WebPort: Web service port. Default: 7002. BindingHost: specifies the Host for listening bindings. The default value is 127.0.0.1. SessionSecret: the salt used in the session; Logdir: log directory. UploadDir: temporary upload file directory; ViewCache: indicates whether view template caching is enabled. The default value is false. EnableCompress: whether to enable gzip compression. The default value is false. Admins: admins: this is a JSON Object corresponding to the user name of each administrator. The key value is their mailbox. The default value is {fengmk2: '[email protected]', admin: '[email protected]', dead_horse: '[email protected]'}; LogoURL: indicates the Logo address. AdBanner: the address of the advertising Banner; CustomReadmeFile: The long description in the middle of the cnPMjs.org homepage is actually a Markdown file. You can set this to replace this file by yourself. CustomFooter: customFooter template NpmClientName: the default is CNPM. If you have your own NPM client or fork it, please use your own CLI command. This should be replaced with the one you wrote in the description of some pages. BackupFilePrefix: indicates the backup directory. Database: {db: the name of the database; Username: indicates the database username. Password: indicates the database password. Dialect: Database adapter. Select "mysql", "sqlite", "postgres", "Mariadb", default "SQLite". Hsot: database address. Port: indicates the database port. Pool: {// Database connection pool configuration, as an object; MaxConnections: The maximum number of connections. The default value is 10. MinConnections: minimum number of connections. Default: 0. MaxIdleTime: indicates the maximum idle time of a link. The default value is 30000 milliseconds. }}, NFS: package file system processing object, a Node.js object, the default is the fs-cnpm package, and configured in the ~/.cnpmjs/ NFS directory, that is, all synchronized packages will be placed in this directory by default; Developers can use other file system plugins (such as uploads, etc.), or develop their own logical layer by interface, which is a later story; RegistryHost: specifies your own server address, r.cnpmjs.org by default. EnablePrivate: indicates whether to enable the private mode. The default value is false. // In private mode, only the administrator can publish the package, others can only synchronize the package from the source; // All logged-in users can publish packages in non-private mode; Scopes: Non-admin packages can only be published prefixed by the namespace listed in the scopes scopes scopes. If they are not set, they cannot be published. This is mandatory and defaults to ['@cnpm', '@cnpmtest', '@cnpm-test']. According to Su Qian greatly explained is to facilitate management and let the company's employees consciously on-demand release; For more information on NPM scope, see nPm-scope; PrivatePackages: As mentioned in the comments for the configuration items, for reasons of historical burden of some existing private package (may be installed in the Git way before) is not named in the form of a namespace, and this package cannot be uploaded to the CNPM originally, this configuration items array is used to add the exception of the white list, the default is an empty array; SourceNpmRegistry: update source NPM registry address, the default for https://registry.npm.taobao.org; SourceNpmRegistryIsCNpm: Whether the source registry is CNPM, default is true, if you are using an official NPM source, set it to false; SyncByInstall: If the package does not exist when you install it, try to synchronize it from the update source. Default is true. SyncModel: Update mode (but I think it's typo). There are several modes to choose from, default is "None "; // "None" : never synchronizes. Only packages uploaded by private users are managed. Other source packages are directly obtained from the source site. // "exist" : periodically synchronize packages that already exist in the database; // "all" : synchronize all source packets periodically; SyncInterval: synchronization interval. The default value is "10m" (10 minutes). SyncDevDependencies: Whether to synchronize the devDependencies packages in each package. The default value is false. BadgeSubject: The badge name of the package, default CNPM; UserService: user authentication interface, the default is NULL, that is, there is no user related function, that is, no user can upload the package, this part needs to realize the interface function and configuration, such as the company's Gitlab relative connection, this is also a later story; AlwaysAuth: Whether user authentication is always required, even with commands such as $CNPM install; HttpProxy: Proxy address Settings for when you are inside the wall and the source is outside the wall. }Copy the code

For these configurations, we focus on the following changes

  • Service access port
RegistryPort: 7001, // Warehouse service access port: 7002, // Web site access port: bindingHost: ", // listen to the binding Host, default 127.0.0.1, external access to comment out this item, generally we do not expose our internal port, can do a forwarding in the nginx layer, so this configuration can comment out. If the value is set to 0.0.0.0, registryHost: XXX // set to the address of your own server. NPM install prefered to pull the package from the private repository; otherwise, the private package cannot be pulledCopy the code
  • Database Configuration
Database: {db: 'NPM ',// username: 'admin',// username: 'admin123', // password: 'mysql',// default is sqLite, we select mysql host: '127.0.0.1', // database service address port: 3306, // port... },Copy the code
  • Whether to enable private mode
// In private mode, only administrators can publish modules. Non-admin publish module names must start with the scopes field e.g. @lxy/package scopes: ['@lxy'], // publish prefix enablePrivate: true, // enablePrivate modeCopy the code
  • Administrator Account Configuration
admins: {
    // username: email
    liuxueyong: '[email protected]'
}
Copy the code
  • Synchronous mode
// Exist: synchronizes only the modules already in the database. // all: synchronizes all the modules in the source Registry syncModel: 'exist'Copy the code

5. Start the project

Pm2 start. /dispatch.js //dispatch.js in the root directory of cnpmjs.org project // After startup, you need to expose the above two ports on the server to access the extranetCopy the code

6. Use

1 the initialization

  • Install NRM to manage NPM sources (YARN is YRM)
npm i nrm -g
// npm i yrm -g
Copy the code
  • Add your own private source to the NRM source list
/ / NRM add [name] [host] NRM add lxy HTTP: / / http://106.15.170.172:9010/ / / yrm add [name] [host] / / yrm add lxy http://106.15.170.172:9010/Copy the code
  • Switch to private source
nrm use lxy
// yrm use lxy
Copy the code
  • Register private source users
// Username and email correspond to the key and value configured in the admin object. In the admin object, they are administrator NPM adduserCopy the code

  • Logging into a private warehouse
npm login
Copy the code

2 Daily use

  • Publish private modules
npm publish
Copy the code
  • Installing private modules
npm i xxx
Copy the code
  • Package management front end page
/ / the server address + set web site http://106.15.170.172:9011/ access portCopy the code

7. Some weird potholes

1. The configuration itemssyncModel

After uploading a private library, such as syncModel: ‘None ‘, 404 will be reported when trying to install. SyncModel: ‘exist’ can install correctly, but will synchronize a large number of packages to the local root cause: when executing NPM install XXX, after completing authentication, enter proxyToNpm middleware, when syncModel: ‘None’ with a prefix that does not match the rules of scopedUrls is referred to NPM as a non-private package, but NPM does not have the package and reports the 404 solution: the private package name should match the scopedUrls

// ./servers/registry.js. app.use(auth()); app.use(proxyToNpm()); .Copy the code
// ./middleware/proxy_to_npm.js
  var redirectUrl = config.sourceNpmRegistry;
  var proxyUrls = [
    // /:pkg, dont contains scoped package
    // /:pkg/:versionOrTag
    /^\/[\w\-\.]+(? :\/[\w\-\.]+)? $/.// /-/package/:pkg/dist-tags
    /^\/\-\/package\/[\w\-\.]+\/dist-tags/,];var scopedUrls = [
    // scoped package
    /^\/(@[\w\-\.]+)\/[\w\-\.]+(? :\/[\w\-\.]+)? $/./^\/\-\/package\/(@[\w\-\.]+)\/[\w\-\.]+\/dist\-tags/,];return function* proxyToNpm(next) {
    if(config.syncModel ! = ='none') {
      return yield next;
    }

    // syncModel === none
    // only proxy read requests
    if (this.method ! = ='GET' && this.method ! = ='HEAD') {
      return yield next;
    }

    var pathname =  decodeURIComponent(this.path);

    var isScoped = false;
    var isPublichScoped = false;
    // check scoped name
    if (config.scopes && config.scopes.length > 0) {
      for (var i = 0; i < scopedUrls.length; i++) {
        const m = scopedUrls[i].exec(pathname);
        if (m) {
          isScoped = true;
          if (config.scopes.indexOf(m[1])! = = -1) {
            // internal scoped
            isPublichScoped = false;
          } else {
            isPublichScoped = true;
          }
          break; }}}var isPublich = false;
    if(! isScoped) {for (var i = 0; i < proxyUrls.length; i++) {
        isPublich = proxyUrls[i].test(pathname);
        if (isPublich) {
          break; }}}if (isPublich || isPublichScoped) {
      var url = redirectUrl + this.url;
      debug('proxy isPublich: %s, isPublichScoped: %s, package to %s',
        isPublich, isPublichScoped, url);
      this.redirect(url);
      return;
    }

    yield next;
  };
Copy the code

8. Other matters

1. Implement the rights management system

Status: There is only one administrator account that needs to publish unprefixed private packages to switch to this account for publishing (or multiple administrators?) , prefixed private package can be published by all (you can configure the prefix list that accounts can only be published to through the permission system); Install permission: Switch the source to the private source of the server. Ideal: When connecting to the OA system, only users with correct accounts and passwords can install private packages. Reference: github.com/cnpm/cnpmjs…

2. Configure nginx

As an enterprise application, IP + port is like streaking, using Nginx as a reverse proxy to a domain name

3. Private packages are stored in the cloud

During the synchronization and upload of the private repository, the corresponding function of the NFS object will handle the synchronization and upload, and the NFS object will return the download link after the return processing is complete. Therefore, customized NFS modules can be used to customize the storage of NPM packages. The official default fs – CNPM, the module will upload or synchronous packages exist root/.cnpmjs.org/doenloads/ directory server locally, storage resources can be a bottleneck. Putting private packages or synchronized resources in the cloud is a good solution. The following NFS modules are provided:

Upyun-cnpm: cloud storage plug-in FS-CNPM: local storage plug-in FSS-client: Simple FIle Store (SFS) storage plug-in QN-CNPM: Quniu cloud storage plug-in OSS - CNPM: Ali cloud OSS storage plug-inCopy the code
  • First install the OSS-CNPM module in the cnPMjs.org project directory
npm i oss-cnpm
Copy the code
  • Then a bucket was added in the CLOUD service console OSS administration to store the NPM package, and the project configuration file was modified to replace the default FS-CNPM module with OSS-CNPM
var oss = require("oss-cnpm"); var nfs = oss.create({ accessKeyId: 'xxxx', accessKeySecret: 'xxx', endpoint: 'oss-cn-beijing.aliyuncs.com', bucket: 'catfly-xxx', mode: 'private', }) var config = { ... , nfs:nfs, ... }Copy the code
  • When the project is restarted, the newly published or synchronized packages will not be found in the local directory of the server. The newly published or synchronized resources can be found in the corresponding bucket of the OSS.