Import NPM modules into JavaScript applications without frameworks using TypeScript & Browserify
Ever tried importing an NPM library into your vanilla JS application only to find out that it throws random errors and that you need to manage all the dependencies yourself? Well today, we’re going to set up the complete process with just a few lines of code.
So why Browserify? Why not Webpack, Parcel, Rollup, etc?
- Requires little to no configuration
- Supports TypeScript
- Compiles and reloads on save (with the help of Live Server)
- Does the job
Let’s get started!
First up you need to have Node.js installed on your machine. I’ll be using NPM as a package manager, but you can use YARN too.
Setup NPM project dependencies
Go to the desired directory on your computer, open up a terminal and type:
npm init -y
This will create a package.json file in the directory and allow us to install any third-party package we want. Let’s try Rx.js.
npm i rxjs
If we open up the directory in the code editor, we should see package.json, package-lock.json (or yarn.lock if you’re using YARN), and node_modules folder.
Now we’ll add a public directory where we’re going to create an index.html file.
Then we create another directory in the root directory called src. Inside I’ll create an app.js file which is the file where we’ll write JavaScript.
But you’re probably asking, why am I separating HTML and JavaScript files? Shouldn’t they go together?
Yes, they should, but not in this case. I’ll explain.
Change The Rules of Web
In our everyday web application, we use HTML, CSS, and vanilla JavaScript. In HTML we write the structure, with CSS we style it and then we add the logic with JavaScript.
The three blend together to form a website.
The trio can work together as long as we have a valid CSS and a valid file JavaScript file.
However, the file we’re going to write (app.js) is not going to be a valid JavaScript file. Instead, it’s going to contain a whole bunch of nasty logic that browsers don’t understand — like importing thirty-party dependencies we’ve just installed (Rx.js).
Then we’re going to make use of our transpiler (Browserify) to convert this app.js file into browser-readable vanilla JavaScript file and we’ll pack it like the example above.
Hence why we separated the app.js file from the public directory to not import it into the index.html by accident.
Add NPM packages to the project
Now let’s import and set up the Rx.js package we’ve recently installed in our application. You can do the same with Lodash, Day.js, or any NPM library that runs on the browser or is cross-platform.
If you’re completely new to Rx.js, this is the place to get started:
const { of } = require('rxjs');
of('Hello World')
.subscribe(console.log)
Now how do we run this thing?
Add Browserify
We start by installing Browserify in the project directory.
npm i browserify
Now we open up the package.json file, find the “scripts” selection and add the following script:
"build-js": "browserify ./src/app.js -o ./public/bundle.js"
Run the Script
npm run build-js
# if you're using yarn
yarn build-js
What this will do is:
- transpile our nasty app.js file into a regular JavaScript file
- output (-o) the regular JavaScript file as a newly created bundle.js file in a public directory
Link HTML & JavaScript files
Now we’re going to import the bundle.js file into the index.html file using the script tag:
<script src="bundle.js"></script>
And double click the index.html file to run in the browser. Viola!
Now if we can change the app.js code, run the script again, reload the browser and we should see new changes.
const { of } = require('rxjs');
of('Rx.js is the way to go!')
.subscribe(console.log)
npm run build-js
But we’re not quite there yet.
As you recall, in order to have the latest code, we need to save, then run the same script, and then manually reload the browser. Wish there was a way to automate just by hitting the save button.
Automate The Build Process
This one is a little bit tricky to set up as the library we’re going to install is going to transpile app.js into a bundle.js automatically, but it won’t reload the browser until we install the other dependency.
Watch for Changes
Install another Watchify dependency
npm i watchify
Watchify and Browserify work together to transpile files on changes. To accomplish this we need to add another script to the package.json file and run it:
"watch-js": "watchify ./src/app.js -o ./public/bundle.js",
npm run watch-js
Then we make changes, hit save and the updated text should be instantly reflected in the bundle.js file.
However, the browser will still show the old version until we manually hit reload. Let’s fix that as well.
Reload Browser
There are two ways to accomplish this, the quick is to set up a Visual Studio Code Live Server extension that can reload the browser on changes. The second option is to look for and set up an NPM library that can do the same thing.
Option 1: Live Server Extension
Open up the extensions tab in Visual Studio Code and search for Live Server.
Once you find it, just click on the install button.
What Live Server is going to do is reload the browser whenever there is any kind of change in the index.html or the dependencies it imports (bundle.js)
Then we go back to the public directory where our index.html file is. Right-click on it and choose the first option — Open with Live Server.
This will start a new server on your machine on port 5500 that will display the contents of your index.html file.
The final little detail we need to add is to change the import of bundle.js file from regular script to type module.
<!-- BEFORE -->
<script src="bundle.js"></script>
<!-- AFTER -->
<script type="module" src="bundle.js"></script>
With the Watchify script running the back and Live Server monitoring the index.html file, the browser should automatically reload whenever we update our app.js file.
Option 2: LiveReload NPM package
If your editor does not support the Live Server extension, you can make use of the LiveReload package. Install it on your machine and run the index.html file. It has very extensive docs, so I won’t go into too much detail.
But basically, you’re going to install this package on your machine and then run the index.html file using the LiveReload package. The rest of the work will be handled by Browserify/Watchify just like above.
TypeScript Support with Watch Mode
The last piece of the puzzle is to add TypeScript support. We start by adding the app.ts file in the src directory. There we’re going to write our TypeScript code and once again transpile it and import a bundle file in the index.html.
We’ll start by installing TypeScript and Tsify, which is like Watchify for TypeScript.
npm i typescript tsify
We also need to initialize TypeScript in our project by running:
tsc -init
This will create a tsconfig.json file in the root directory. This is where we set up the TypeScript configuration for our project.
Now we create the app.ts file in the src directory and import Rx.js.
import { of } from 'rxjs';
of('Hello TS!')
.subscribe(console.log)
The next step is to add scripts in package.json to build and watch for changes.
"build": "browserify ./src/app.ts -p [ tsify --noImplicitAny ] > ./public/bundle.js",
"watch": "watchify ./src/app.ts -p [ tsify --noImplicitAny ] -o ./public/bundle.js"
The output file is going to stay the same, bundle.js in the public directory.
We’re using some TypeScript rules within square brackets. You can find these rules in tsconfig.json.
With all of this in place, we run the build script first and then the watch.
npm run build
npm run watch
We also run the index.html file with Live Server.
Demo
Live Reload in action!
Note: Although this is a console application, this process can be used to manipulate the DOM as well.
Caveats
The browser auto-reload process may not work on your first try. So you may need to repeat the steps:
- Open the index.html file with Live Server
- Run the build script
- Run the watch script
- Give it a try
GitHub Repo
If you lost track, don’t worry. I have a whole Rx.js TypeScript Browserify project already set up on GitHub. Feel free to clone it and play around.
Remember to not include the bundle.js file when pushing changes to GitHub as it’s too large and can be generated on the fly just by running either the build or watch script.
This article demonstrated how we can import third-party dependencies into our vanilla JavaScript/TypeScript applications and automate the build process.
See you in the next one!