🔨 Build a web package with typescript! 🔥
Tags: webdev, typescript, javascript, devops
Published: 2020-11-27 10:13:59

# 👋🏻 Introduction

Here at Pixium we often find ourselves creating web packages for various websites. 

This means a simple package that you can integrate via the script tag and then use in your code for example:

```html
<script src="https://mycdn.a/latest/bundle.js"></script>
<script>
    pixiumPackage.helloWorld()
</script>
```

During the development of this package we often find ourselves recreating all the `package.json` scripts and information. Thus we decided to create a template that can easily be setup.

In this post we will look at what tools we use and how we came to creating this kick-ass template!

![power gif](https://media.giphy.com/media/D7z8JfNANqahW/giphy.gif)

# 🔧 Tools Used

Here is a quick list of tools used and a quick description of how it is used in the project

| Tool         | Description                                           |
|--------------|-----------------------------------------------|
| Yarn         | Handle package installation                            |
| Npm          | Publish the package to npm registry                    |
| Typescript   | Strongly typed JavaScript                              |
| Webpack      | Bundle the typescript into a single JavaScript Library |
| Snowpack     | Hot Module Reload for testing                          |
| Concurrently | Start multiple commands at the same time               |

# 🗄️ Managing Structure

Let's take a look now at how we manage folders and files in our current project

 ![code gif](https://media.giphy.com/media/CTfg7SZKO10Pe/giphy.gif)

```bash
webpack-demo/
├── README.md
├── dist
├────...
├── node_modules
├────...
├── package.json
├── snowpack.config.js
├── src
├────...
├── test
├────...
├── tsconfig.json
├── webpack.config.js
└── yarn.lock
```

As we can see we have 4 main folders in our project:

| Folder        | Use                                                      |
|---------------|----------------------------------------------------------|
| dist          | Contains compiled ready for release bundle               |
| node\_modules | All the npm packages needed for the project              |
| src           | The source files of the library                          |
| test          | A index file referencing the bundle to test in real time |

# 🕸 Webpack 

In this project we use [webpack](https://www.npmjs.com/package/webpack) and [ts-loader](https://www.npmjs.com/package/ts-loader).

`Webpack` is used for bundling everything in a library that is exposed in the browser while `ts-loader` let's us handle all the typescript necessities.

For the webpack config we use the `output:library` property to specify the name of the exposed library.

**webpack.config.js**
```js
const path = require('path');

module.exports = {
    entry: './src/index.ts',
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                use: 'ts-loader',
                exclude: /node_modules/,
            },
        ],
    },
    resolve: {
        extensions: ['.tsx', '.ts', '.js'],
    },
    output: {
        // Define the package name
        library: 'pixiumPackage',
        libraryTarget: 'umd',
        globalObject: 'this',
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist'),
    },
};
```

This means we can then access the library like this:
```html
<script>
    pixiumPackage.myFunctionName()
    pixiumPackage.myClassName()
</script>
```

# ❄️️ Snowpack

[Snowpack](https://www.snowpack.dev/) is an awesome tool that we discovered recently at Pixium. It is a modern frontend build tool that is so fast!

![fast gif](https://media.giphy.com/media/3ornjIhZGFWpbcGMAU/giphy.gif)

In this project Snowpack has a very simple use. Rendering a test environment to visualize changes in real time. It supports Hot Module Replacement which means everytime webpack will recompile a new bundle after making some changes the test environment will reload

![snowpack](https://dev-to-uploads.s3.amazonaws.com/i/ufcsgmnnibje99234y09.gif)

**snowpack.config.js**
```js
/** @type {import("snowpack").SnowpackUserConfig } */
module.exports = {
    mount: {
        test: '/',
        dist: '/dist',
    },
    plugins: ['@snowpack/plugin-typescript'],
    install: [
        /* ... */
    ],
    installOptions: {
        installTypes: true,
    },
};
```

Here the `mount` parameter is the most important. 

- `test: '/',` means we will mount the test folder as the root of the web
- `dist: '/dist'` means we will mount the dist folder to `/dist`. This means that we can then require scripts from dist for instance `<script src="./dist/bundle.js"></script>`

# 💻 Exposing our Code

And now let's finish off with taking a look at the code and how we can expose our constants, functions, class.

![typing gif](https://media.giphy.com/media/PiQejEf31116URju4V/giphy.gif)

To make code accessible through our library we simply have to use the `export` method. For instance:

```ts
/**
 * Say hello world in the console
 */
export const PixiumHello = () => {
    console.log(`hello world`)
}
```

We can then call this in the following way:

```html
<script>
pixiumPackage.PixiumHello()
</script>
```

You can also easily interact with the `DOM` through classic functions:

```ts
// Set the inner text
document.getElementById("pixiumBanner").innerText = "Pixium Digital Pte Ltd";
```

# 🏁 Conclusion

We now have a very simple typescript bundling in place with a HMR system in place for easy testing.

There are a few command shortcuts implemented to easily push patches, minors, majors to npm.

All this coupled with a CDN and you get an awesome blazing fast library for your frontend.

Full repo bellow

{% github pixiumdigital/typescript-package-boilerplate %}

---

**Pixium Digital** - Shaping your project with technology and innovation
https://pixiumdigital.com
https://github.com/pixiumdigital