"The beginning is more than half of everything."This is a very ancient
GTD principle: its age is probably thousands of years old. (For example, Wikiquote
currently attributes it to Aristotle, although without confirming the source.) Its essence is that starting
a project can be very difficult (and even have to force yourself) from a clean slate; but if there are several simple initial steps, the implementation of which leads to the appearance of a partially finished project, then it becomes much easier to continue working on it “by inertia” - as easy as if the project was already not only started, but even more ready. than half. And besides, when you know in advance what the initial steps should be, then it is difficult to make a mistake in making them.
I happened to write more than a dozen modules for Node.js with open source and publish them as packages npm. The more modules I did, the more I understood (including through trial and error) that the initial steps for their creation can be the same and can even be performed in the same order. Today, I publish this procedure in the hope that it will help in the work of programmers who write their own JavaScript code for the Node engine.
')
Pay attention to the fact that each of these steps is quite simple and logical.
Step 1. Coming up with the npm package name and the repository
Without a name, nothing happens. Without having a name for your project, you will not be able to create for it either a repository on GitHub, or the npm package.
Make sure in advance that the npm package name is not yet taken. (Here is an example: if in the fall you decide to call your package “autumn”
or “fall”, then visit the addresses
https://www.npmjs.org/package/autumn and https://www.npmjs.org/package/fall without labor will convince you that npm packages with such names already exist.)
If the name of your package npm
is a simple word or a well-known technical term, then consider whether to add
the “node-” prefix to it in order to get the name of the repository. (For example, the code for the
sqlite3 package is stored in the
node-sqlite3 repository , and the code for the
open package is stored in the
node-open repository.) This addition is made for the convenience of programmers working on projects of the same name in other programming languages. (For example, if
someone already has a project called “open” on Rust, Ruby, or Python, then he will still be able to fork the
“node-open” repository and not experience the consequences of a name conflict.)
Is the short name of your package npm or long? If it is short, then it is easier to manually type it (for example, on the command line after
“ npm install ”), and if it is long, then it will be copied (this action is more error-free, but longer - and therefore is perceived as less convenient). Also note that the
nodei.co site provides such histograms with statistics on downloads of the npm package, the width of which depends on the length of the package name (so that the whole name can fit on the histogram). Here are two examples:
![[histogram №1: uue]](https://habrastorage.org/getpro/habr/post_images/868/ece/ee6/868eceee623da3c1bacd792decf19e67.png)
![[histogram number 2: fidonet-jam]](https://habrastorage.org/getpro/habr/post_images/261/b5b/f3b/261b5bf3b9fe1e77b8f02d0128e7ac4a.png)
For modules endowed with too long names, an increase in the width of such a histogram may cause (and will cause, will certainly cause!) The need to place statistics on a separate line, rather than to the right or left
of some other picture, when you start preparing summary information about your module. - even as simple as the README on Github.
Step 2. Coming up with a brief description.
A brief description is useful when creating a project on Gitkhab, and later (for example, when filling in the
description field in the
package.json file).
It is best to place there just one short sentence with a description of what your module does. It will facilitate searchable search and accompany the name of the package or repository on many hyperlinked sites. If you make the description too long, it will not fit
on the card on Twitter (and on other sites that cut descriptions in length); besides, even if it fits, then at a quick reading of the lists, the public will still not finish reading it to the end.
Step 3. Creating a repository on Github with an automatically filled README file.
As a rule, Node module repositories are created on GitHub; I came across exceptions to this rule, but rarely. Therefore, I will begin to present all the steps here with reference to the use of GitHub and Git, and for readers from among users of other DVCS
and (or) other open source hosting companies, I offer to adapt these steps for themselves: this is not a tricky thing.
On the page
https://github.com/new offer to fill in the name and description of the repository (you could come up with both in the two previous steps), and also automatically create a
README file (project description), a
file with the license text (to designate how much your code is open) and the
.gitignore file (so you don’t download any extra temporary, auxiliary, junk files into the repository).
When there is at least one file in the repository on Github from the very beginning, you can simply clone the repository (for example, with the
“ git clone ” command) - it is faster and simpler (approximately one and a half or even twice) than initializing the local repository first ( for example, with the
“ git init ” command), and then in the settings with the hands, prescribe the address of the gitkhabovsky repository
as origin .
But a license file auto-created by Github often has to be edited by itself (for example, instead of a gitkhabovsky login, you must specify your full name or organization name), and you can also wish to add
something to the auto-
created .gitignore according to your idea of which files in repositories are not needed. Therefore, if you are not creating the first Node module in your life, then it’s best to limit yourself to auto-creating the README file alone, but to copy the license
and .gitignore from one of your previous modules as a finished file. Doing them again (albeit not from scratch, but from the results of the GitHab
autogeneration) is both a muda (無 駄 、 extra work) and a vain clutter with the history of edits.
After creating the repository on Gitkhab, do not forget to make all those changes in the repository settings that you consider necessary for it. For example, if there is not enough time and therefore there is no time to keep an eye on the wiki, then you can disable wiki support in the repository. And if, for example, you are used to seeing in the Starred list (in the list of repositories marked with stars) not only some other repositories, but all of your repositories, then you can immediately put the newly created repository to its first star.
Step 4. Adding a text file with the license
With this step, it is best not to delay: the sooner you make it clear under which license all subsequent edits apply, the better.
As I said in the previous step, if you are not creating the first Node module in your life, you can copy the
LICENSE file from another module, correct the year in the text if necessary - and you can commit.
If, for the first time, you decide on which license to distribute your open source code, you can follow the example of the community (and in the Node.js community, as far as I can tell, the MIT license is the most popular, although there are exceptions to this rule ), or consult the website
choosealicense.com , or both together.
Step 5. Add the .gitignore and .npmignore files .
As you know, the
.gitignore file lists the names of those files and directories that should not go into the Git repository, because they would only clutter it in vain. These include, as a rule, project archives and distributions, logs, databases, operating system auxiliary files (for example, repositories of thumbnails of images contained in a subdirectory).
When developing a project in which one or several Node modules are used as dependencies, it is quite appropriate to add the
node_modules directory name to the
.gitignore file , because the correspondence between the version and the contents of the npm package is one-to-one — therefore, it is enough to store only the file in your Git repository
Package.json (which lists the names and versions of dependencies), but not the necessary modules themselves.
(To broaden my horizons, I will mention that Mikeal Rogers
made and actively promoted the very opposite recommendation. But this happened
before in 2014 the correspondence between the version and the contents of the npm package became
unambiguous .)Also in the
.gitignore file,
it is useful to add the name of the report
npm-debug.log , which appears if
any error occurred while working with the npm packages.
As a result, the
.gitignore file
takes on
this form:
.gitignore# , *.7z *.dmg *.gz *.iso *.jar *.rar *.tar *.zip # , *.log *.sql *.sqlite # Thumbs.db Desktop.ini .DS_Store* ehthumbs.db Icon? # Node, npm node_modules npm-debug.log
The
.npmignore file
is approximately the same as the
.gitignore file
— but it lists the names of those files and subdirectories that should not be included
in the npm package of your module.
I recommend copying the entire contents of your
.gitignore into .npmignore , and then adding to it the name of the
test subdirectory or another such place where you are going to store your module tests. Tests are extremely useful in development, so it is quite appropriate
in the Git repository - but downloading and storing tests would be an extra burden for the end users of your module, and it’s one of the majority of users of the
npm package.As a rule, starting work on a new Node module, you can copy the
.gitignore and .npmignore files in an unchanged form from one of your previous modules (unless you are creating the first Node module in your life). It is necessary to correct them in rare cases, but you need to know that such cases are. (In particular, if
any module deals
with ZIP archives, then the line
" * .zip " from the
.gitignore file
will inevitably have to be removed at least in order to place one or several test cases in the repository - and such a need arose me when developing a
module for reading fidonet nowallists , for example.)
Step 6. Description of the module in README.md, mention of the license and incompleteness of development.
I remind you that in the third step, a
README file was automatically created, consisting only of the name and a brief description of the module.
Now this description can be replenished a little by talking about the goals and objectives of the project. In addition, in a separate description section, it is appropriate to mention the type of license (for example, MIT or BSD) and the name of the file (usually
LICENSE ), which contains the full text of the license.
In order for readers to learn about the module’s capabilities at this stage not to cause disappointment (and even better, so that such attempts have not yet taken place at all), it is useful to immediately post a warning mention that the module’s development is not only not completed, but early stage.
After this replenishment, the README file is suitable as an initial description of the original version of the
npm package.However, if you happen to mention the planned package name in the README, then do not rush to put the results of this step in the repository (for example, with the
git- commit command ), and even less so do not rush to publish them (for example, with the
git- push command ) on GitHub . The fact is that if the initial registration of the package with the planned name (namely, we will deal with it in the next step) fails, then another name will have to be entered into the README (and it will be better if it does not lead to an unpleasant choice between clogging ); publication on Github (if it precedes publication in npm) is capable of alerting not only
some cybersquatters (who wish to stake out the specified package name before you), but also ordinary users (who will try the “npm install
package-name” and wonder why it doesn't work as it should).
In general, I recommend considering that at this step it would be a bit early to mention the planned package name in the README.
Step 7. Writing package.json and registering the very initial version of the npm package.
The ultimate goal of this step is to register the
npm-package under the previously conceived name in order to stake out this name.
This step has to be
started by creating the
package.json file and filling in at once several fields of the object inside it. In this case, you must simultaneously comply with
the JSON format and the description of the meaning of the fields, which is given
on the npm website .There is a “
npm init ” command that asks you questions about the module and fills
package.json in accordance with the answers. However, I prefer to fill in
package.json in a text editor — it allows you to view all the JSON code in its pure form (not diluted with questions) and, moreover, it gives you an easy way to go back a couple of lines above to correct or change
something as needed.
In fact, the documentation
on the npm site should be enough for everyone; but I will not restrain myself and on Habrahabr I will briefly touch on the meaning of the main fields that are placed
in package.json .
The value for the “
name ” field indicates the desired npm package name. You could think of it earlier (in the first step).
The value for the “
version ” field indicates the version of the package in accordance with the
Semantic Versioning standard. To register the very initial version, I recommend
" " 0.0.1 " ".The value for the “
description ” field is a brief description of the package. You could come up with it earlier (in the second step).
The value for the “
keywords ” field indicates the array of keywords by which the package can be found in the search on the npm site. Anyone who
has ever listed tags under the text of the blog on Habrahabr, will easily cope with this task.
The value for the “
license ” field indicates the identifier string that conforms to the
SPDX ID standard and means the license that you selected for your code earlier (in the fourth step).
The value for the “
author ” field indicates the string (or object) with the name of the author of the package (as well as, perhaps, with contact information). Point yourself out there.
The value for the “
repository ” field indicates the object containing the type and address of the repository.
The value for the field “
main ” indicates the path to the main file of the module code (this is the same file that will be called from
“ require ( moduleName ) ” from Node if
you specify the name of the module instead of
moduleName ).
If a module is meant as a command-line utility, then the module will
prefer the preferGlobal property with a value of
“ true ” (which would recommend a global installation of the module) and
the bin property with a value like
“ " ./ moduleName.js " ", containing the path to some javascript (to the one that will be launched upon a command that matches the module name). The line
“ #! / Usr / bin / env node ” should be the first in such a javascript, because npm expects to see it there (even if the installation and the subsequent operation of the module is done under Windows).
The module code in this step may be the simplest — for example, contain
some “ hello world ” or even
“use strict ”.It is appropriate to place the phrase “package is registered” (or “package published”) in the description of the commit and make this commit only after the
“ npm publish ” command is successful (if it turns out). Thus, a commit will not be premature (submitting the
“ npm publish ” command may reveal one or several simple errors, the correction of which would only in vain litter the editing history).
Step 8. Explaining the installation in README.md
During this step, it is appropriate to place explanations in the README.md file, informing future users of the meaning of two commands:
- npm install PackName is the command that installs the npm package from the npm repository,
- npm install https://github.com/username/repository/tarball/master is the command that installs the module from the master branch of the githabov repository.
It is also useful to explain to future users the difference between the results of the one and the other team - for example, to tell about the decision taken earlier (in the fifth step) to store the tests only on Github, and not in npm (so as not to increase the size of the
npm package).You can also tell that the latest version of the README.md file will only be on the GitHub (unless you plan to create and publish the next new version of your
npm-package not only after changes in the code, but also after changes in the README).
During the same step, you can also get the appropriate code of informative statistical counters and histograms indicating the number of dependencies and module installations on the
nodei.co site and also place them in the README.md file.
Step 9. Getting started on the main module code
At this stage, the germ of a module (that is,
some kind of “ hello world ” or even
“use strict” ) is slowly transformed into code that does something rational, which means that it contains one or several functions (or object methods, or utility commands).
As all of the features of the source code are generated, it should be carefully documented in the README.md so that the code itself does not remain the only documentation for the open source code.
In addition, as soon as the source code reaches this stage, it will immediately become good to cover it with tests that verify the correctness of the code and its behavior. This is the next step.
Step 10. Facilitate testing and explain it.
At this step, it is necessary to put in README.md clear information on how to install and how to use the means of testing the correctness of writing source code (for example, JSHint) and its behavior (for example, Mocha).
At this stage, configuration files for test tools (for example,
.jshintrc for JSHint) are also added to the repository.
In the object inside the
package.json file, the
scripts.test field is
filled (and if there are two or three testing tools, then the
scripts.pretest fields
and scripts.posttest are also filled in ).Example:
"scripts": { "pretest": "jshint .js test/", "test": "mocha --reporter spec --timeout 60s" }
Starting from this step, before each commit it is advisable to make sure that the
npm test command passes without errors. (To make the work of this team more meaningful, when using Mocha, at least one test should also be written and placed in the
test / subdirectory
.)Step 11. Configuring Travis CI
Travis CI is a service that provides a free open source testing service: after each commit, it is able to automatically download code from GitHub and run tests in various environments to see if the code works well.
It would be nice to prepare for the initial use of Travis CI, that is,
read the documentation and be registered.
Connecting a new javascript module is much simpler and consists of two simple steps.
First, you must go to
https://travis-ci.org/profile/ in your user profile. There will appear switches, each of which corresponds to one of the repositories on GitHub; It looks something
like this:![[screenshot]](https://habrastorage.org/getpro/habr/post_images/489/6cf/062/4896cf0624be89081f4be378cd5a7ab4.png)
The switch corresponding to the new module should be pulled to the on position.
Secondly, right after this, you need to commit the .travis.yml file to the root of the repository. This file describes the environment required to run the tests. You can read more about it in the Travis documentation, but its usual content is pretty simple and looks
something like this: language: node_js node_js: - "0.10" - "0.12" - iojs before_install: - "npm install -g npm" - "npm config set spin false" before_script: - "npm install jshint" - "npm install mocha"
In the “
language ” section, you can see the “language” (more precisely, engine) Node indication, and in the
“ node_js ” section
- the enumeration of versions, in each of which the module will be tested.
In the "
before_install " section,
there are commands that update
npm to the latest stable version, as well as turn off the spinning cursor animation (which is still not displayed in the Travis CI logs, so there is nothing to waste time on it).
The “
before_script ” section lists commands that install test tools (in this example, JSHint and Mocha).
Step 12. Adding the Travis CI indicator to the README.md .
Travis CI
provides the URL of the image that can be placed once in the README on the GitHub and then every time there to see if the results of the last commit passed successfully on the Travis CI.
The server
shields.io provides the opportunity to get a slightly different form of this image - for example, change the volume, or rounding of the edges, or part of the inscription.
Generalization method
Here ends a list of simple initial steps of developing a module
for Node.js.Clearly, I hope that such a method (that is, the ability to give yourself an initial impetus by starting work by reproducing previously prepared steps) is suitable not only for the development of modules for Node.
I will give an example. In the article about
developer paralysis (which
PerseptronYar translated), you could see on Habrahabr the story that every modern
website builder , when starting work, immediately faces the pressing need to make an unobvious choice between various possibilities of approximately equal attractiveness like
Buridan donkey : You can, however, greatly simplify your life in the future, if you can not only make such a choice once, but in the future simply stick to it. To do this, it is enough to fix in writing the choice made at each such step, write all these steps in their finished form (that is, for example, not “select the CSS framework”, but “install Bootstrap” if you chose Bootstrap), and then follow at the beginning of each new project, unless there is a reason to deliberately try
something new in between projects (well, for example, you can
refuse Underscore.js in favor of the newest features of JavaScript, when a gradual transition of readers to new browsers will provide you with such a cart ozhnost).