Creating NPM packages with @dizmo/generator-module
- Generation: the process of generating an NPM based module (based upon a template);
- Minification: the process of compressing a large module into a smaller one;
- Linting: the process of checking that the coding style meets certain standards;
- Testing: the process of testing code for expected behavior;
- Coverage analysis: the process of checking how much of the code is covered by tests;
- Continuous integration: the process of automatically running tests (on a remote server).
Our module generator is based on Yeoman. After installing Yeoman and the @dizmo/generator-module package, you can create an NPM project with:
yo @dizmo/module [--git] [--typescript|--coffeescript]
yo @dizmo/module --git
_-----_ | | ╭──────────────────────────╮ |--(o)--| │ Welcome to the awesome │ `---------´ │ dizmo module generator! │ ( _´U`_ ) ╰──────────────────────────╯ /___A___ / | ~ | __'.___.'__ ´ ` |° ´ Y ` ? Name your module: @dizmo/my-module ? Describe it: library module ? And your URL? https://github.com/hsk81 create package.json create cli/run-build.js create cli/run-lint.js create cli/run-prepack.js create cli/run-test.js create cli/run-utils.js create lib/index.js create test/test.js create LICENSE create README.md create .travis.yml create .eslintrc.json create .gitignore create dist/.gitignore create dist/.npmignore Setting the project root at: /home/hsk81/my-module.git
tree my-module.git/ -a
my-module.git/ ├── cli │ ├── run-build.js │ ├── run-lint.js │ ├── run-prepack.js │ ├── run-test.js │ └── run-utils.js ├── dist │ ├── .gitignore │ └── .npmignore ├── .eslintrc.json ├── .gitignore ├── lib │ └── index.js ├── LICENSE ├── package.json ├── README.md ├── test │ └── test.js ├── .travis.yml └── .yo-rc.json 4 directories, 16 files
where we have omitted above the
.git sub-directory. Let’s have an even closer look at the various sub-directories:
./cli — the embedded build system
tree my-module.git/cli/ -a
my-module.git/cli/ ├── run-build.js ├── run-lint.js ├── run-prepack.js ├── run-test.js └── run-utils.js 0 directories, 5 files
These scripts beneath the
./cli folder provide support for all the features listed above: building (transpilation), linting (code standard adherence), testing (code correctness with coverage analysis), and prepackaging (bundling with minification).
The totality of this embedded build systems is less than
100 lines of code, and thanks to it being directly embedded into the project, it allows for specific adjustments of the build process.
./dist — the distribution folder
tree my-module.git/dist/ -a
my-module.git/dist/ ├── .gitignore └── .npmignore 0 directories, 2 files
./dist folder is the target location of the transpilation, bundling and minification processes. The
.gitignore file here ensures that no bundle (which can be rather large) is committed to the GIT repository, while the (empty)
.npmignore file ensures that the bundle is published to the NPM repository.
Hence, these two files should never be removed: Sometimes, it is necessary to clean-up the remaining files under
./dist, upon which great care should be taken to not also accidentally remove these
./lib — the source folder
tree my-module.git/lib/ -a
my-module.git/lib/ └── index.js 0 directories, 1 file
./lib folder contains all the source files, which collectively make up the library; it is also possible to create sub-folders within it. By default a single
index.js is given, which with its
export statements provides the API of this library.
./test — the test folder
tree my-module.git/test/ -a
my-module.git/test/ └── test.js 0 directories, 1 file
./test folder contains test scripts (beginning with a
test prefix), which together test the code under
./lib for expected behavior. By default a single
test.js is given containing test cases for
npm run build
npm run -- build --no-lint
with UMD support (incl. minimization):
npm run -- build --prepack
with UMD support (excl. minimization):
npm run -- build --prepack --no-minify
npm run build all scripts under
./test) are by default transpiled and linted. Optionally, they are bundled and then minified. The transpilation is performed with Babel, linting with ESLint, (UMD) bundling with Browserify and minification with Terser.js.
npm run lint
npm run -- lint --fix
npm run lint the linting process can also be triggered separately (outside of a build process), and it is performed with ESLint, whereas the
.eslintrc.json file is used for configuring the set of linting rules.
npm run test
npm run -- test --no-build
npm run test by default a build step is performed, after which the (transpiled) test scripts are executed — using the Mocha framework.
npm run cover
npm run -- cover --no-build
npm run cover by default a build step is performed, after which the (transpiled) test scripts are executed — using Mocha in combination with the Istanbul.js coverage framework (to provide corresponding statistics).
initially (if public):
npm publish --access=public
npm publish the transpiled scripts under
./dist are prepackaged by bundling and minifying them, after which the bundle is then published to the NPM registry. While for bundling Browserify is used, for minification Terser.js is facilitated.
$ cat .travis.yml
language : node_js node_js : - stable install: - npm install script: - npm run cover after_script: "npx nyc report --reporter=text-lcov | npx coveralls"
When the source code of the NPM library is pushed to a GIT repository (for example on GitHub.com), it can automatically be tested using the Travis CI service. For this to work a
.travis.yml configuration (as shown above) needs to be provided (which is generated by @dizmo/generator-module). Further, the Travis CI needs to have access to the corresponding GIT repository — to be able to pull and test the most recent commits.
Finally, the results of the tests is reported to the Coveralls service, which offers a user interface to interactively investigate the portions of the code base, which are (or are not) covered by the provided test cases (under
Author: Hasan Karahan, Software Engineer at dizmo
Disclaimer: This blog post has first been published on Hasan’s personal blog