Working With 3rd-Party Script and CSS In Angular
Tags: angular, javascript, beginners
Published: 2022-10-15 07:11:12

In Angular, we have a few ways to add libraries, for example, using Angular schematics or using Angular libraries, which export modules to add to the `app.module`. But what happens when we have a standard `library.js` or `ui.css` and need to add it to use in Angular? 

Angular.json is a file with all the settings of our Angular project, and also it helps us to work with 3rd party libraries with standard JavaScript and CSS files to merge into the final bundle or defer in a single file.

Instead of manually adding CSS and Javascript files into the index.html, the Angular CLI does it for us, creating a bundle file for CSS and javascript and injecting it into the index.html automatically.

> Note: This example use @angular/core v12.2.0 

## The Scenario

We are building an Angular application but want to use an external web component, `button-upload` with two files, `button-upload.css` and `button-upload.js`.

> For simplicity, the files are in the `external/` directory, but they should be `node_modules`.


The button-upload.css

```css
.fancy-uploader {
  background-color: red;
  color: whitesmoke;
  border: 1px solid gray;
}

```

button-upload.js

```javascript
class ButtonUpload extends HTMLElement {
  constructor() {
    super();
  }

  connectedCallback() {
    this.innerHTML = `
    <div class="fancy-uploader">
      <label for="avatar">Image Uploader:</label>
      <input type="file"
           id="avatar" name="avatar"
           accept="image/png, image/jpeg">
    </div>
    `;
  }

}

window.customElements.define("button-upload", ButtonUpload);
```

## First Approach
The first easy and fast approach is to import the javascript and CSS into the index.html. It works but comes with a price to pay:

- Execution order and maintenance.
- You add files manually, but the Angular CLI also adds files and css.
- What happens if you have more scripts like tracking stuff? 
- What happens to keep the problem isolated in his bundle? 

The Angular.json solve all of them, providing a single place for the maintenance of CSS and Javascript files, with the option of eager loading, bundling, and optional injection in the index.html

Let's give an overview of angular.json.

## The Angular.json

The Angular CLI uses angular.json to help us with the administration and configure the projects for building, serving, testing, and localization.

> we are focused on how to add the third-party css and scripts. Learn more in the official [Angular docs](https://angular.io/guide/workspace-config).

Angular.json configure every application or library in the project's node. We work in the section `architect> build > options` focus in  `styles` and `scripts` to add our styles and CSS.

```json
"architect": {
	    "build":{
		    "options":{
 				"styles":[],
                "scripts":[]
    		}
	}
}
```

## Bundle Files

The Angular.json take the styles and scripts declared in these section for the final `script.js` and `styles.css` and Injecting into the index.html


Add the `button-upload.css` file in the styles array and the `button-upload.js` in the script.

```javascript
   "styles": [
              "external/button-upload/button-upload.css"
            ],
   "scripts": [
              "external/button-upload/button-upload.js"
   ]
```

> Remember add [`CUSTOM_ELEMENTS_SCHEMA`](https://angular.io/api/core/CUSTOM_ELEMENTS_SCHEMA)  in the  `@NgModule` to use custom elements. Read more

Run the `ng build` to merge all css files into the script file and styles in the styles.css

```bash
> ng build
✔ Browser application bundle generation complete.
✔ Copying assets completely.
✔ Index html generation complete.

Initial Chunk Files               | Names         |      Size
main.437835c56f488f70355e.js      | main          | 101.96 kB
polyfills.fc6cfcbe5c3a0e94edad.js | polyfills     |  33.11 kB
runtime.df8927e5b1e564860c37.js   | runtime       |   1.03 kB
scripts.5cf64c63898afa29a094.js   | scripts       | 370 bytes
styles.de2e542873613fb23f4a.css   | styles        |  73 bytes
```

Also, inject these files in the index.html

![Bundle all](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s42bvhlf0ue7jtuk5fk1.png)

## Separate Bundles
Everything is working, but sometimes we want to split our code from the global CSS and JavaScript files into a bundle file.

The script allows adding files with an object configuration with the following options :

__input__: the path of file (CSS or JS), 
__inject__: set to true to add by default in the index file.
__bundleName__: change the name of the bundle file.

```json
"styles": [
      "src/styles.css",
      {
          "input": "external/button-upload/button-upload.css",
            "inject": true,
            "bundleName": "upload-button-css"
      }
     ],
"scripts": [
             {
                "input": "external/button-upload/button-upload.js",
                "inject": true,
                "bundleName": "upload-button-js"
              }

]
```
> Old versions like eight use `lazy` instead `inject`.

The build creates a new file for each object with a bundle name:

```bash
PS C:\Users\dany.paredes\Desktop\labs\learn-ng-script> ng build
✔ Browser application bundle generation complete.
✔ Copying assets complete.
✔ Index html generation complete.

Initial Chunk Files                        | Names             |      Size
main.437835c56f488f70355e.js               | main              | 101.96 kB
polyfills.fc6cfcbe5c3a0e94edad.js          | polyfills         |  33.11 kB
runtime.df8927e5b1e564860c37.js            | runtime           |   1.03 kB
upload-button-js.5cf64c63898afa29a094.js   | upload-button-js  | 370 bytes
upload-button-css.de2e542873613fb23f4a.css | upload-button-css |  73 bytes
styles.31d6cfe0d16ae931b73c.css            | styles            |   0 bytes

```

The inject option injects the `upload-button-css` and `upload-button-js` bundles in the index.html. 

![Bundle Image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nvxsb4dqn3f31cdk57jq.png)

## Conclusion

We work with external JavaScript and CSS files in the global styles.css and script.js and split them into bundle files.

> The source code [Github](https://github.com/danywalls/bundle-external-files)