Somewhere along the way, technical articles about a failed or successful interview and the questions that were asked during the interview became very popular on the Internet. Most of these articles are loose and unrelated. Perhaps these articles will help you understand that you have not mastered the point, but just to understand, really master only by interview questions is not enough, just like the usual study does not work hard, by doing several sets of elite school papers before the test, or simulation set of questions is not enough. Although I have a collection of interview articles, I still prefer to read some more technical articles, or even write one myself. This is my first post because of a requirement at work that several projects need to share some components, and it would be convenient to seal these components into a package and publish them to NPM. However, as these components are for the company’s own use and are closely related to the company’s business, it is not convenient to release them into public packages. Although NPM also provides private package services, due to some irresistible network factors, even if you pay for them, you may not enjoy good services. Therefore, we consider setting up an NPM private warehouse internally. This article is the build private warehouse involves knowledge, after summarizing found is a relatively complete knowledge chain, so share with everyone, level is not high, and limited ability to hope everybody excuse me, this paper refer to some content, also keep are authenticated yourself, if there are any errors or omissions are welcome to correct me.

1. Start with front-end modularity

When we now use JavaScript for large single-page applications and server-side applications, who would have thought that JavaScript was originally a language designed to do some input validation for the server-side? The complexity of functions means the increase of code volume, and modularization is to solve the maintenance difficulties, structural chaos, code duplication and redundancy. Unfortunately, prior to ES6, JavaScript did not naturally support modular programming. But although JavaScript does not support modular programming, but we can achieve the effect of “module” through the object, namespace, immediately execute functions and other methods, some specific methods can refer to Ruan Yifeng: JavaScript modular programming (a) : module writing.

CommonJs specification

This situation didn’t change until NodeJS came along and implemented modules with CommonJS in mind. Nodejs makes it easy to export and import modules:

// module.js
const name = 'wang';
const age = 18;
function showName() {
    console.log(wang);
}
function showAge() {
    console.log(age);
}

module.exports = {
    showName,
    showAge
};

// page.js
const module = require('./module.js');
module.showName(); // wang
module.showAge(); / / 18
Copy the code

AMD and CMD specifications

However, the CommonJS specification does not apply to the browser environment. The browser does not require the require method, and the server file requires a package that only reads a local file, while the client is network loading, and the network loading speed is not the same as the hard disk reading speed. This way of writing it doesn’t make the client require a dead end, and the first thing that comes to mind in the front end is asynchronous load callbacks. In order to enable the browser to support modular development, there are AMD based RequireJS and CMD based SeaJS. The differences between them are as follows:

  1. For dependent modules, AMD executes early and CMD executes late. Since 2.0, however, RequireJS has also been deferred (handled differently depending on how it is written). CMD advocates as lazy as possible.
  2. CMD advocates dependency nearby, AMD advocates dependency front

It is written as follows:

// CMD
define(function(require, exports, module) {
    var a = require('./a');
    a.doSomething();
    var b = require('./b'); // Dependencies can be written nearby
    b.doSomething();
});

// AMD's default recommendation is
define(['./a'.'./b'].function(a, b) {
    Dependencies must be written in the beginning
    a.doSomething();
    b.doSomething();
});
Copy the code

Modules specification for ES6

JavaScript finally came up with its modules specification in ES6 years later, written like this

//module.js
function showName() {
    console.log('wang');
}
function showAge() {
    console.log(18);
}

export { showName, showAge };

//page.js
import { showName, showAge } from 'module.js';

showName(); //wang
showAge(); / / 18
Copy the code

This feature can be used after chrome61 by adding type = ‘module’ to script tags as follows:

<script type="module" src="./module.js"></script>
<script type="module">
    import { showName } from './module.js';
    showName(); //wang
</script>
Copy the code

Some of the points to note are that type=’module’ is set for both the introduced side and the introduced side, and there are some requirements for the path, as described in the ES6 Module implementation of the browser in this article.

Using es Module in Node requires the command line argument –experimental-modules and the MJS file suffix. Please refer to the nodeJS documentation for details. Because it is the official specification, so the popularity is very fast, in addition to the direct use of node is not too convenient, now the front-end development basically refer to this writing style, the fact shows a truth, the official force, crushing everything.

webpack

One might ask how Webpack relates to them, but here’s a summary. CommonJS, AMD, CMD, ES Modules are all specifications. RequireJs and SeaJS are front-end modular concrete implementations based on AMD and CMD respectively. They are an online module compilation scheme. Webpack is a packaging tool, which is a precompiled module solution that can recognize and package any of the above specifications into browser-aware JS files for modularization. UMD is a mashup of AMD and CommonJS. UMD determines whether node.js modules are supported or not (exports exist or not) and uses node.js modules if they are. Then determine whether AMD is supported (define exists). If so, use AMD mode to load modules. This specification webpack can also be recognized.

2.NPM

In the past, when we wanted to import a third-party package, we usually downloaded the package file and put it into our project, and then imported it in HTML through script tag, or the package has CDN service, so we could directly import the CDN network address of the package in script. This process is cumbersome and inefficient, so is there a tool that makes it easy to introduce third-party packages? NPM. NPM can be understood as a package repository and market. People can publish their code on NPM for others to download and share. NPM was originally installed along with NodeJS as a package management tool, but now it has basically become a standard package management tool for the whole front-end. NPM makes it easy to introduce third-party packages. I won’t go into that because it’s very common.

npm cnpm yarn

NPM is our most commonly used package management tool, but there were some flaws in earlier versions:

  1. The installation policy is not flat. The dependencies in node_modules are placed in their own folders, resulting in deep directory nesting and repeated installation dependencies.
  2. Module instance cannot be shared (related to article 1)
  3. Slow installation (also related to # 1)
  4. The dependency version is not clear (package-lock files were not available in earlier NPM)

The directory structure looks something like this:

├ ─ ─ node_modules │ └ ─ ─ moduleA │ └ ─ ─ node_modules │ └ ─ ─ moduleC │ └ ─ ─ moduleB │ └ ─ ─ node_modules │ └ ─ ─ moduleC └ ─ ─ package.jsonCopy the code

CNPM is taobao NPM mirror, the official saying is

This is a full nPMjs.org image, which you can use instead of the official version (read only). The synchronization frequency is currently 10 minutes to ensure as much synchronization as possible with the official service.

It solves the first three problems by placing all dependencies under node_modules and adding soft links (shortcuts). That’s why with a CNPM installation you’ll find a lot of folder shortcuts under node_modules. In addition, since the CNPM server is in China, the installation speed is very fast, but the fourth problem is still not solved. The directory structure looks something like this:

├ ─ ─ node_modules │ ├ ─ ─ _moduleA @ 1.0.0 │ │ └ ─ ─ node_modules │ │ └ ─ ─ moduleC │ ├ ─ ─ _moduleB @ 1.0.0 │ │ └ ─ ─ node_modules │ │ ├ ─ ├ ─ [email protected] │ ├ ─ [email protected] │ ├ ─ ├ ─ ├ ─ ModuleC // Soft Link (shortcut) [email protected] ├ ─ package.jsonCopy the code

Yarn is a great project. There was a time when it rubbed NPM to the ground. As an alternative package manager to NPM, it solved most of NPM’s pain points and added some features of its own.

  1. Flat install strategy, with all dependencies installed under node_modules
  2. Parallel download, offline support (this is a big reason for speed)
  3. Yarn run can find the executable command in node_modules/. Bin
  4. Specify dependencies through the yarn.lock file
  5. The command is simple and the output is concise

These advantages have led many people (including me) to embrace YARN, but it is the same word that the authorities have come out and crushed everything. After npm3:

  • Flat installation is adopted

After npm5:

  • Add the package-lock file
  • Optimization commands (no longer needed –save or -s when NPM I installs a package)
  • Add the temporary installation command NPX
  • Add offline and cache
  • Installation speed has also been greatly improved

There’s not much reason to leave the official package manager in favor of a third party. (This section refers to the article why DO I go from NPM to YARN to NPM?)

Package. json and version number

Modern front-end projects typically have a package.json file under the root directory, which is automatically generated by the NPM init command when initializing the project and contains the dependencies and configuration information needed for the project.

/ / package. Json {" name ":" demo ", "version" : "1.0.0", "description" : ""," main ":" index. Js ", "scripts" : {" test ": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "npmv-test": "^ 2.1.0}}"Copy the code

Npmv-test = nPMV-test = nPMV-test = nPMV-test ^2.1.0, which describes the version range, is followed by a summary of the relevant version numbers.

  • The version number is in the format of X.Y.Z, indicating the major version. Minor version: Patch version. The update principle is as follows:
    1. If you are just fixing a bug, you need to update the Z bit.
    2. If it is a new function, but backward compatibility, need to update the Y bit.
    3. If there is a big change, the x bits need to be updated because they are not compatible downward.
  • If y and z are omitted, it is equivalent to supplementing 0. For example, 2 equals 2.0.0 and 2.1 equals 2.1.0.
  • No description before the version number indicates that the installation is based on the specified version, which means that the version number is written out. For example, 2.0.0 is the installable version.
  • If the version number is an asterisk (*), any version can be installed, usually the latest version.
  • The version number is preceded by ~ :
    • If there is a minor version number, fix the minor version number to upgrade. For example, to 2.1.3, the installed version is 2.1.z (z>=3).
    • If there is no minor version number, fix the major version number for the upgrade. For example, if ~1 is used, the installed version is 1.y.z(y>0,z>0). The behavior is the same as ^1.
  • The version number is preceded by ^:
    • Fixed the first non-0 upgrade. For example, ^2.1.3, the installed version is 2.y.z(y.z>=1.3). ^0.1.3, the installed version is 0.1.z(z>=3). ^0.0.3, the installed version is 0.0.3.
  • When installing a package with NPM I, the version descriptors in package.json are set to ^ by default (even if you specify a version number to install, this is still set to ^, not dead versions without descriptors, as some people think, unless this is the case below), but if both major and minor versions of the package are 0, Like 0.0.3, this indicates that the package is in an unstable development phase and will omit ^ to avoid updates.

package-lock.json

Because the versions of dependencies described in package.json are ranges, this creates some uncertainty. There is no way to ensure that the versions of dependencies are the same each time you install them, and there is no way to determine the version of dependencies if there is a problem, which package-lock.json is designed to solve. This file describes dependencies and dependency versions in detail, and is a snapshot of the node_modules folder structure and information, with package-lock.json updated every time node_modules changes. Here is the package-lock.json file corresponding to package.json above, we can see the difference:

{
    "name": "demo"."version": "1.0.0"."lockfileVersion": 1."requires": true."dependencies": {
        "ms": {
            "version": 2.1.1 ""."resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz"."integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
        },
        "npmv-test": {
            "version": "2.1.0."."resolved": "https://registry.npmjs.org/npmv-test/-/npmv-test-2.1.0.tgz"."integrity": "sha512-tNUwr+sdUek+lyJFmGT2H6Jox50NwA5EmNKAZTL3N5fYU1W7Aucfw+rNVsDinnQnhOF1hNvdU5RCUOvgcRWzng=="."requires": {
                "ms": "^ 2.1.1"}}}}Copy the code

One problem is that package-lock.json files are excluded from tracking in the source repository because of their frequent changes. According to the official documentation, it is recommended to commit this file to the repository, both for the sake of consistent dependencies for each installation of the project, and because we generally exclude node_modules from the repository, we need to be able to restore node_modules in case of a problem.

NPM I and NPM Update

Json dependency. If NPM I does not install the package name, it installs all the packages in the package.json dependency. NPM update corresponds to update. However, sometimes there may be some confusion. It seems that the package has been updated when executing the NPM I command. Sometimes the version of package.json is obviously too low but the NPM update is not updated. The two graphs are just to help understand, the real execution process is not necessarily the same order, interested friends can go to see the implementation of the source code. npm i

npm update

3. Set up private warehouses

The same code reused in multiple projects is packaged into a common component library, which not only avoids reinventing the wheel, but also facilitates maintenance and management. There are several ways to implement this. First of all, since it is a library, it is necessary to separate these components and put them into a source repository for maintenance. If you pack these components directly and publish them on NPM, then it is a NPM public package that anyone can download and use. But if you don’t want to do that, here are the methods (source repository git) :

  1. Through git sub-module implementation, directly introduce the source repository as a sub-module into your project, the disadvantages are obvious, sub-module is also a Git project, to manually update, can modify upload, equivalent to maintaining a Git project in a Git project.
  2. NPM supports direct installation of Git resources by NPM + git. The advantage of NPM is that it is simple and convenient, but the advantage is that you need to use tag to control the version, and if it is a private Git repository, you need to ensure that you have access to it by configuring a public key or directly using a repository address with a username and password.
  3. By building a private warehouse to achieve.

The solution we choose this time is to build a private warehouse to achieve, the working principle of NPM private warehouse, is about the NPM command registration address to point to our private warehouse, when we install through the NPM command, if it exists in the private warehouse, it will be obtained from the private warehouse. If it is not in the private repository, obtain it from the CNPM or NPM official repository. At present, the more common private warehouse construction methods on the market are as follows:

  • Build through Sinopia or Verdaccio (Sinopia is out of maintenance, and Verdaccio is a Fork from Sinopia, which is essentially the same), which has the advantage of being easy to build and requiring no other services.
  • It is built by CNPM, which requires database service. Redis cache is also supported in the later stage (when redis sets the password, there seems to be some problems in accessing it). Currently, docker is recommended by CNPM as the container.
  • Through CPM construction, should be reference to some things of CNPM, and CNPM need database services and support Redis, the page is fresh, configuration is simpler, through the PM2 process daemon.

They all have the corresponding concrete structures, methods of document, the document link is pointing to the address above, here did not elaborate, I ran across these three methods are feasible, and finally chose the CPM, and because the CPM used currently, there are few people and can communicate with the developers quickly and timely feedback problems, here is a advertising, recommend project address.

The last

The purpose of this article is not to teach you how to set up a private repository (that’s what documentation does), but rather to set up a private repository to draw out relevant content and connect it to help you understand the whole picture, as far as you can, and as far as you can. Writing an article for the first time, I found that I was more tired than I imagined, but I felt a sense of accomplishment. I also appreciate the authors who share their knowledge with the community. I hope I can learn from them, share more things and discuss learning with everyone. (No qr code, no Github to like, go away).

Full list of articles

  • From modularization to NPM private warehouse construction
  • 10 minutes for Thanos to snap his fingers and disappear
  • It’s time to develop your own vscode extension
  • A quick guide to using Babel