How to convert CommonJS/amd/umd npm package into browser script

CommonJS/amd/umd npm package

A lot of node npm packages are shipped only in Webpack (or another bundler) compatible format so they could be imported into your Webpack project and then bundled.

For example all SPA projects based on next frameworks/libraries are bundled:

Bundlers most often able to handle packages of the next formats:

Such formats allow install the package in the next way:

npm i pack

Then somewhere is sourcecode do:

import Pack from 'pack';
// use Pack  variable

So actually bundler (e.g. Webpack) resolves such "imports" for you and it all works.

But if you have no bundler you will try to include a package with a script tag:

<script src="static/js/pack.js" />

Some libraries intentionally are compiled to support both bundler and browser formats. For example, Painterro publishes releases to npm with npm publish and also uploads script-compatible js file to GitHub releases so guys who use browser-scripts can grab it to their project, put it to statics folder or CDN, and be happy. But not all projects doing it of course.

Example

For example, let's consider devforth-quill-markdown-shortcuts package, github source. Exactly such a case. This is a plugin for Quill rich editor. Quill itself supports both bundler import and script import, but the plugin was quickly crafted by the community guy, so he wanted to make support only for bundlers (because used only the bundler method, e.g. his project was on some SPA framework). So he had no time to make it compatible with the script input. If you use Quill without SPA you might want this plugin to be script compatible.

So let's turn it into the browser script.

First of all bundler-compatible format was used in a next way:

npm i devforth-quill-markdown-shortcuts

Then somewhere is sourcecode it was imported

import MarkdownShortcuts from 'devforth-quill-markdown-shortcuts';
// use MarkdownShortcuts 

Let's analyze source code from GitHub.

The current plugin was bundled itself with webpack (If you have no more statistics I would add, "most of the npm packages use Webpack". To understand it you can see webpack.config.js file in the root folder.

In this file, there is an output .libraryTarget setting /webpack.config.js#L11

The first action that we need, is to replace with var:

@@ -8,7 +8,7 @@ module.exports = {
     output: {
         path: path.resolve(__dirname, 'dist'),
         filename: '[name].js',
-        libraryTarget: 'umd',
+        libraryTarget: 'var',
         library: 'MarkdownShortcuts'        
     },
     externals: {
(END)
'var' target means that output script will contain global var variable, in our case it will be var MarkdownShortcuts = xx so once you will connect script library will be available as a global variable in whole scope.

For some packages it might be enough but not for all. Thing is that our library in source code tries to import Quill package (which it is intended for). After import code uses it in so-called "realtime mode", in other words when it is used.

For example, you can find and analyse such ussages here: /src/index.js#L28

Obviously, it expects Quill which will be imported in compile time. But our Quill objects is global var which will be delivered from the vendor script tag:

<script src="https://cdn.quilljs.com/1.3.6/quill.min.js"></script>

So we need just to remove such imports

diff --git a/src/formats/hr.js b/src/formats/hr.js

--- a/src/formats/hr.js
+++ b/src/formats/hr.js
@@ -1,4 +1,3 @@
-import Quill from 'quill';
 
 let BlockEmbed = Quill.import('blots/block/embed');
 
diff --git a/src/index.js b/src/index.js     
--- a/src/index.js
+++ b/src/index.js
@@ -25,8 +25,6 @@

-import Quill from 'quill';
-
 import HorizontalRule from './formats/hr';  
 (END)

Recompile

Common for most npm Webpack projects it is two commands:

npm ci
npm run build

If there is no build scrip, check the scripts section in package.json

Then grab dist/markdownShortcuts.min.js

In your project:

 <script src="static/js/markdownShortcuts.min.js"></script>

And finally, we can activate it.

Quill.register('modules/markdownShortcuts', MarkdownShortcuts);
quill = new Quill('#editor', {
        modules: {
            markdownShortcuts: {},
...

The same approach works for most of frontend libraries. If you want you can create multiple targets like we do it in Painterro.

#npm #webpack
0
Ivan Borshchov profile picture
May 08, 2021
by Ivan Borshchov
Did it help you?
Yes !
No

Best related