Why Universal NPM Modules? There are a lot of inconsistency in the JavaScript world. Since 1997 (ECMAScript 1) and before 2015 (ECMAScript 6) there were no standards for JavaScript modules. ECMAScript specification is a standardised specification of the JavaScript language. In ES 2015 (ES6) modules were added to the specification and new and statements introduced. export import Before ECMAScript 2015, there were a few modules standards proposals, some of them are: CommonJS AMD RequireJS OSGI JavaScript Bundles and others On the way to universal modules, UMD wrapper has being proposed. Universal Module Definition (UMD) is an attempt to offer compatibility with the most popular scripts loaders (AMD and CommonJS). UMD builds are available in both, browsers and NodeJS. Open-Source Open-source approach will help your project to accept improvements and fixes from the community. In this example we will use a public GitHub repository . async-assets-loader Project Initialisation Working dir Create a directory: async-assets-loader mkdir Change directory: async-assets-loader/ cd Package config Create a file for scoped package. package.json init unscoped init --scope=@scope-name npm for or npm A scope allows you to create a package with the same name as a package created by another user or organisation without conflict. Scoped packages are preceded by their scope name. It will ask questions about package name, version, description, entry point, test command, git repository, keywords, author, license. As a result file will be generated, see example below: package.json Source files Main module source file is configured in file, property. In our case it will look for an file in the folder. package.json main async-assets-loader.js dist In the file, add a function as a property of the object. This will make the function available to others code. Example: exports exports.hello = { ;} ( ) function return "Hello World" is a reference to the that is shorter to type. However, be aware that like any variable, if a new value is assigned to , it is no longer bound to // OK // Not OK, exports module.exports exports module.exports module.exports.hello = true; exports.hello = true; // OK (shortcut) exports = { hello: false }; exports is re-assigned You can find the original module source code of file . index.js here Build and Test First of all we are using to export module as NodeJS module. This way is not compatible with browsers by default. To make it compatible with browsers we will use and it’s library. To add libraries, run module.exports webpack umd npm i webpack webpack-cli -- - save dev After installation is done, lets create webpack config, see example below: Check source code for . Now, we can run build command: webpack.config.js here . .bin /node_modules/ /webpack As result it will create and place it into the folder: async-assets-loader.js dist Because of mode in the webpack config file, it will also minify the resulting code of the module. production Now we are ready to test the module. First of all lets ensure it will be working in the browser. For test in browser let’s use , and karma chrome-launcher jasmine. npm i karma karma-chrome-launcher karma- --save-dev jasmine jasmine-core then npm i jasmine -- - save dev Now we are ready to create karma config: ./node_modules/.bin/karma init karma .conf .js See how it might looks like: Here is the link to the file. Note, is set as . karma.conf.js singleRun true Let’s add some tests to the file. test/loadAssetsSpec.js It’s time to start testing our code in Chrome browser. If you want to run tests in another browser, check page. available browsers launchers runs an arbitrary command from a package’s object. It is used by the test, start, restart, and stop commands, but can be called directly, as well. commands will automatically include local to the . npm run "scripts" npm run node_modules/.bin PATH Lets update command in property of file to webpack && karma start karma.conf.js. This will make a new build and run tests: npm test scripts.test package.json npm run test And it’s shortcut: npm test Awesome! Time to test in NodeJS environment. Generate basic jasmine config: ./node_modules/. init bin/jasmine It will create a file , we will not change it. Lets create file. spec/support/jasmine.json spec/testNodeSpec.js And update test command in package.json: "test": "webpack && karma start karma.conf.js && jasmine " Now will make a build, run browser tests and run basic NodeJS package test. npm test Publish to the Registry After all tests have being passed, we are ready to update module version and publish to the NPM repository. If you didn’t make a login yet run the login command. login npm All files in the package directory are included if no local or file exists. If both files exist and a file is ignored by but not by then it will be included. .gitignore .npmignore .gitignore .npmignore When you are ready to launch your first version, update your module version from 0.0.1 to 1.0.0: npm version 1.0 .0 And publish to the registry with command: publish npm All published packages are available on the npmjs website, example: https://www.npmjs.com/package/async-assets-loader Add Info Badges After publishing to the NPM registry we can add info badges about status of our open-source project with . It could be build status, code coverage, size, downloads, version, etc. Status is updating automatically. https://shields.io/ Add such lines to the top of README.md file in your project root: # -assets-loader [](https://www.npmjs.com/package/async-assets-loader) //img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](LICENSE) //img.shields.io/npm/dt/async-assets-loader.svg?style=flat-square)](https://www.npmjs.com/package/async-assets-loader) The README file will be shown on the package page. An npm package README file must be in the root-level directory of the package. Badges example: Setup CI When you are contributing with a team, a good option is to setup a continuous integration (CI). Popular tool for open-source projects is Travis CI. It has support of NodeJS and integration with GitHub and NPM. They have article with a short description of how to setup tests against a few NodeJS versions and deploy the package to the NPM. deploying to npm Source code I have being used in this article is available on the GitHub