Javascript - Getting Started - The Welcome Library - How to develop, publish and use a library ?

> (World Wide) Web - (W3|WWW) > Javascript (Js|ECMAScript)

1 - About

How to develop and use a Javascript library ?

We will:

  • Expose the library as a variable called welcome
  • Set the library name as prefix-welcome.js
  • Use only the ES2015 module syntax
  • Be able to access the library inside Node.js and the browser

The code is available in the following github repository. gerardnico/welcomejs

Advertising

3 - Toolchain

The tools used to create this library are:

  • Npm for the library dependency mechanism
    • it has a built-in knowledge of Node module mechanism
    • react use it in its start react app
  • Jest as test runner because:
    • react use it in its start react app

4 - Creation Steps

4.1 - Node

{
  "name": "welcomejs", // The name of the Node package - Verify if it's free at https://www.npmjs.com/package/<name>
  "description": "A welcome library",
  "version": "0.0.1",
  "keywords": [
    "getting_started",
    "webpack",
    "node",
    "library"
  ],
  "main": "dist/prefix-welcome.js",  
  "license": "BSD-3-Clause",
  "author": {
    "name": "Nicolas GERARD",
    "url": "https://gerardnico.com"
  },
  "module": "index.js",
  "dependencies": {},
  "scripts": {
    "build": "webpack" // Script functionality of Node that call webpack
    "test": "jest" // Script functionality of Node that call jest
  }
}
  • then install webpack and jest
npm install --save-dev webpack
npm install --save-dev jest
# to be able to use the ES6 javascript syntax with jest (webpack understands it natively)
npm install --save-dev babel-jest babel-core babel-cli babel-preset-es2015 

The main entry can be defined in:

  • The main property: the standard from node package.json, package.json main
  • and module only ES2015 syntax. See proposal to allow the JavaScript ecosystem upgrade to use ES2015 modules without breaking backwards compatibility.
Advertising

4.2 - Webpack

Webpack is a configuration based tool that gets its parameter from the webpack webpack.config.js file.

See the full content in Github.

webpack.config.js
module.exports = {
    entry: "./index.js",
    output: {
        filename: "prefix-welcome.js", // The output of the build
        library: "welcome", // The name of the global variable
        path: path.resolve(__dirname, "dist"), // The directory of the output
        libraryTarget: "umd", // The format of the library - umd = node + browser
        umdNamedDefine: true // ???
    },
    devtool: 'source-map' // Create source map to be able to map the generated code to the original code
};

where:

4.2.1 - Library Target

The libraryTarget property expose the library in the following ways:

  • Variable: (default) as a global variable made available by a script tag (libraryTarget:'var').
  • This: available through the this object (libraryTarget:'this').
  • Window: available trough the window object, in the browser (libraryTarget:'window').
  • UMD: available after AMD or CommonJS require (libraryTarget:'umd').

4.2.2 - Excluding Dependency in the build

The welcome package has no dependency but if you want to not include all dependency (known as peerDependency) in the final library, you must set it in the externals property

See https://webpack.js.org/configuration/externals/

webpack.config.js
externals: {
        // require("jquery") is external and available
        //  on the global var jQuery
        jquery: "jQuery"
}

or:

externals: [
  'library/one',
  'library/two',
  // Everything that starts with "library/"
  /^library\/.+$/
]
Advertising

4.3 - Module Structure

All functions and variable that you want to be publicly accessible must be exported.

  • In Node, the main is generally called the index.js
index.js
export {default as foo} from './src/foo.js';
export {default as bar} from './src/bar.js';
  • bar.js
src/bar.js
export default function welcome() {
    return 'A warm Welcome from the bar package !';
}
  • foo.js
src/foo.js
export default function welcome() {
    return 'A warm Welcome from the bar package !';
}

4.4 - Test

This welcome project use jest as test runner.

In the package.json, we have added:

"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-jest": "^21.2.0",
"babel-preset-es2015": "^6.24.1",
"jest": "^21.2.1"

jest is the test runner and babel is the transpiler in order to use the ES6 syntax (in our case the import statement).

The .babelrc configuration file was also added (otherwise nothing happens)

{
  "presets": ["es2015"]
}

4.5 - Build

The build will create the library prefix-welcome.js in the dist directory.

In a console on the project root home

npm run build # Run the content of the build property in the package.json which is webpack
> [email protected] build D:\git_js\javascript
> webpack

Hash: b131fdfad9791a76f4ca
Version: webpack 3.8.1
Time: 83ms
                Asset     Size  Chunks             Chunk Names
    prefix-welcome.js  4.14 kB       0  [emitted]  main
prefix-welcome.js.map  3.94 kB       0  [emitted]  main
   [0] ./index.js 147 bytes {0} [built]
   [1] ./src/foo.js 84 bytes {0} [built]
   [2] ./src/bar.js 91 bytes {0} [built]

4.5.1 - Production

4.6 - Publish

Publishing to NPM

Everything in the directory will be included unless it is ignored by a local .gitignore or .npmignore file

  • Create a user on the npm platform
npm adduser # npm login if you already have an account
Username: gerardnico
Password:
Email: (this IS public) gerard__nico ___at___ gmail.com
Logged in as gerardnico on https://registry.npmjs.org/.
npm publish
+ [email protected]

4.7 - Usage

4.7.1 - Node

Usage (if the name of your package is package-name)

example/welcomeLibInNode.js
var welcome = require("../dist/prefix-welcome");
 
console.log(welcome.foo());
console.log(welcome.bar());

require returns a value, depending on what the module exposes using exports or module.exports. See CommonJs (NodeJs) - Require

node ./example/welcomeLibInNode.js
Welcome from the foo package !
A warm welcome from the bar package !

4.7.2 - Browser

example/welcomeLibInBrowser.html
<html>
<!--
If published in Node
<script src="https://unpkg.com/myLibrary"></script>
Otherwised locally
-->
<script src="../dist/prefix-welcome.js"></script>
<body>
</body>
<script>
    // Global variable
    var welcomeFoo = welcome.foo();
    // Property in the window object
    var welcomeBar = window.welcome.bar();
    document.body.innerHTML = "<h2>"+welcomeFoo+"</h2><h2>"+welcomeBar+"</h2>";
</script>
</html>

5 - Support

When trying to publish to npm, you get the following message:

npm ERR!     at Error (native)
npm ERR!  { Error: EPERM: operation not permitted, unlink 'C:\Users\gerard\AppData\Local\Temp\npm-11188-4b1862cb\tmp\fromDir-75b125af\package.tgz'
npm ERR!     at Error (native)

If you are a new user, you need to create one:

npm adduser

or to login

npm login

6 - Documentation / Reference

web/javascript/library_build.txt · Last modified: 2019/02/16 17:40 by gerardnico