Create a distributive and an NPM package using one source code

Creating small open source tools is a passion of mine, and I strive to provide the best experience for my users. My packages usually consist of just one function, so here's what I aim to offer:

  1. A JavaScript file that users can easily add by including the src attribute in the script tag. This script will then allow them to call my function in their own scripts below. Ideal for those who prefer not to use a package manager:
<script src="https://amazingCDN.com/isEven.js"></script>
<script>
  isEven()
</script>
  1. A JavaScript file that can be packaged and published for NPM users to conveniently install with npm install isEven, followed by importing my package.

Both JS files should derive from the same source code. Let's assume the source code contains a named function that needs to be added to the window object and made importable when using Webpack. When packaging the files, I want only two JS output files generated. As for CDN support, let's say I utilize jsDelivr to fetch my GitHub-hosted JS file and handle minification without manual intervention.

I attempted writing my code as a module and utilizing Browserify with the standalone flag, which worked well with CommonJS modules. However, for ES modules compatibility, I had to resort to esmify, resulting in an object return with a default key. This forced me to refer to the function as foo.default() instead of foo(), which is less than ideal.

Another approach involved writing it as a standalone file and executing the following:

echo 'export default ' | paste -d'\0' - src.js > module.js

While somewhat successful, I am curious about more advanced and dependable solutions available.

Any suggestions on how to accomplish this effectively?

Answer №1

Are you considering packaging your project as a UMD?

Explore UMD on GitHub

If so, Rollup might be the right tool for outputting to UMD format, especially for smaller projects like single-function libraries.

isEven.mjs

function isEven(x) {
  return (x % 2) === 0 && x !== 0;
}

export {
  isEven
};

$ rollup isEven.mjs --format=umd --name=isEven

This command will generate:

(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.isEven = {}));
}(this, (function (exports) { 'use strict';

  function isEven(x) {
    return (x % 2) === 0 && x !== 0;
  }

  exports.isEven = isEven;

  Object.defineProperty(exports, '__esModule', { value: true });

})));

This should meet your requirements perfectly.

Answer №2

After successfully completing the task, I went ahead and crafted a template repository specifically tailored for it.

Utilizing this template, you have the option to generate your own repository that converts your library into an NPM package using ES modules. Once you push the code changes, a dist folder will automatically be generated containing the distributive js file named after your library. Users can easily incorporate this file into their projects by adding it within a script tag, making your library accessible at the global namespace.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

JavaScript error: You are trying to use Array.find() in Redux, but it

I am currently developing a react native application and I am using basic redux for managing the state, although I am a complete beginner to this. In a specific issue, I am facing an issue while fetching data from my redux store in the edit screen where th ...

What is the method to modify the text of an element without altering its existing properties?

https://i.stack.imgur.com/cBu6P.png $.ajax({ type: "GET", url: "my url" + x, datatype: "html", success: function(data){ //alert(x); //var Content = data; var sendId ; var data = $.parseJSON(data); ...

What is the reason why the "@wordpress/scripts" package does not produce the *.asset.php file when running "npm run build"?

I have been creating custom Gutenberg blocks using npm, webpack, and @wordpress/scripts. Everything was running smoothly until I encountered an issue with the block.json file. In order to use the block.json file, I discovered that I needed a block.asset.ph ...

Guide to refreshing extensive dataset using MySQL migration scripts

We are in the process of developing a Nodejs application for a client who has requested that we use migration scripts to streamline updating the production database. As someone new to MySQL, I am struggling with how to update table contents using only MySQ ...

`On mobile devices, the Bootstrap button no longer displays focus changes once clicked.`

When clicking a primary bootstrap button, it changes its background color to blue on mobile devices. For example, the first button appears normal and the second one turns blue after clicking. However, this background effect disappears when clicking anywhe ...

"Need to refresh localStorage in VueJS after navigating back with this.$router.go(-1)? Here's how

Below is my Login.vue code: mounted() { if (localStorage.login) this.$router.go(-1); }, methods: { axios.post(ApiUrl + "/login") { ... } then(response => { ... localStorage.login = true; this.$router.go(0); ...

Setting a background image as a variable in Vue.js

I am currently working on a vue.js component that includes a div.icon: Vue.component('obj', { props: ['img', 'name'], template: '<div><div class="icon"></div> {{ name }}</div>' }) While ...

The received data object appears to be currently undefined

I am currently using MapBox to display multiple coordinates on a map, but I am encountering an issue where the longitude and latitude values in my return object are showing up as undefined. Could there be a missing configuration that is preventing the data ...

Why does the text in a div display in Safari 8.2 and Chrome 39, but not in Firefox 34?

In my HTML document, I have a div tag located within the body like so: <div id="content_text"></div>​ Using javascript, I later set the contents of the div like this: var content_text = document.getElementById("content_text") c ...

Using a React component to send data through a POST request to an API

When attempting to send a selected value from a Dropdown to an API using a POST request, I keep encountering a 405 (Method Not Allowed) error. Despite trying different ways to handle the onChange event, such as: onChange{(e) => this.onChangeHandler(e.t ...

React-hook-form does not display the input length in a custom React component

Introducing a custom Textarea component designed for reusability, this basic textarea includes a maxlength prop allowing users to set the maximum input length. It also displays the current input length in the format current input length/max length. While ...

Clearing a leaflet layer after a click event: Step-by-step guide

When working with my map, I attempt to toggle the layer's selection using a mouse click. Initially, my map looks like this: Upon clicking a layer, my goal is to highlight and select it: If I click on a previously selected layer again, I want to dese ...

The Yeoman custom generator is failing to load dependencies specified in the package.json file

I've developed a custom Yeoman generator. In the index.js file, I am trying to replace some text within certain files. I added the dependency replace in the package.json, and then when I try to use require('replace') in index.js during the g ...

Exploring ways to transfer a function variable between files in React

Currently, I am working on a quiz application and have the final score stored in a function in app.js. My goal is to generate a bar graph visualization of the user's results (e.g. 6 right, 4 wrong) based on this score. To achieve this, I created anoth ...

PHP - Implementing a Submit Button and Modal Pop-up AJAX across multiple browsers in PHP

As a newbie in PHP AJAX coding, I'm facing a challenge with having two browsers. My goal is to click the submit button on one browser and have a modal popup on the other browser simultaneously. Essentially creating a chat system where only a button an ...

Reset checkboxes in Material UI data grid

Currently, I am immersed in a React Js project that involves various tabs, each containing a unique data grid table with rows featuring checkboxes. Issue: Whenever I select a row from Table 1 and navigate to Tab 2 before returning to Tab 1, the checkboxes ...

tag directive not functioning properly

I have encountered an issue while trying to create a simple custom directive. When I specify the directive as <div my-info></div> in my HTML file, it works fine. However, when I specify it as <my-info></my-info>, it does not work. ...

Utilizing Jquery to enhance table filtering functionality

I created a table listing various places, along with buttons to filter the list. The first filter is based on location (north, east, central, south, west) determined by postcode. The other filter is for "impress" which only displays places with a rating of ...

How to Retrieve the Access Token from Instagram using Angular 2/4/5 API

I have integrated Instagram authentication into my Angular 2 project using the following steps: Begin by registering an Instagram Client and adding a sandbox user (as a prerequisite) Within signup.html, include the following code snippet: <button t ...

Build a nested block containing a div, link, and image using jQuery or vanilla JavaScript

I have a button that, when clicked, generates a panel with 4 divs, multiple href links, and multiple images. I am new to web programming and understand that this functionality needs to be in the Javascript section, especially since it involves using jsPlum ...