How to convert CommonJS/amd/umd npm package into browser script
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:
- Vue.js
- ReactJS
- AngularJS
- Other
Bundlers most often able to handle packages of the next formats:
- CommonJS
- AMD
- UMD
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.