Write a custom plugin with Aurelia 2 and Lerna
In this article, We want to write a simple Bootstrap 5 plugin for Aurelia 2
and manage our packages via Lerna.
With help of my friend, Sayan, I want to discuss about writing a custom plugin. At the end, you will have a good knowledge to write your own plugins, so stay tuned.
What is Bootstrap?
Bootstrap is the most popular CSS Framework for developing responsive and mobile-first websites.
The main purpose of this article is to create a component of Bootstrap 5
as a plugin for Aurelia 2.
What is Lerna?
A tool for managing JavaScript projects with multiple packages.
Splitting up large codebases into separate independently versioned packages is extremely useful for code sharing. However, making changes across many repositories is messy and difficult to track, and testing across repositories becomes complicated very quickly.
To solve these (and many other) problems, some projects will organize their codebases into multi-package repositories (sometimes called monorepos).
To achieve the ultimate goal of this article, we will create our project in the form of monorepos.
What is a plugin?
In computing, a plug-in (or plugin, add-in, addin, add-on, or addon) is a software component that adds a specific feature to an existing computer program. When a program supports plug-ins, it enables customization.
I want the user to be able to customize their requirements while using this plugin so in the following we will examine how to add config to our plugin.
Aurelia 1 vs Aurelia 2
Aurelia 1
Writing a new Aurelia Plugin is not difficult but it requires a lot of work that you can read through here. To be honest, it was not really straightforward!
1 |
|
Aurelia 2
In version 2, everything is straightforward, just introduce the items you export to the register
method. In fact, everything is possible by the register
method so we will see how it works.
1 |
|
The structure
We want to separate our plugin in three packages.
- bootstrap-v5-core
We will add the Bootstrap 5 configurations in this package.
- bootstrap-v5
Our Bootstrap 5 components will define in this package. bootstrap-v5
depends bootstrap-v5-core
packages.
- demo
We will use our plugin in this package as a demo. demo
depends on bootstrap-v5-core
and bootstrap-v5
.
Lerna configuration
To config your monorepos, you should do as following:
Install Lerna
as a global tool.
1 |
|
Go to a folder that you want to make project and run
1 |
|
The result should contain
packages
: The folder you will create your repositories there.lerna.json
: Lerna’s configuration file.package.json
: Node’s configuration file.
Open your packages
folder and install the projects inside it.
1 |
|
After creating, delete all files inside src
folders of bootstrap-v5-core
and bootstrap-v5
. We will add our files there.
To continue we need to config Lerna
, Open your lerna.json
and paste the followimg code:
1 |
|
version: the current version of the repository.
npmClient: an option to specify a specific client to run commands with (this can also be specified on a per command basis). Change to “yarn” to run all commands with yarn. Defaults to “npm”.
command.bootstrap.hoist: Common dependencies will be installed only to the top-level node_modules
, and omitted from individual package node_modules
.
packages: Array of globs to use as package locations.
Dependencies
As described in the structure section defined packages depend on each other. So, we link them together and add the other prerequisites for each.
- bootstrap-v5-core
This package has no dependency.
- bootstrap-v5
Go to package.json
and add the following dependencies:
1 |
|
- demo
Go to package.json
and add the following dependencies
1 |
|
Note: All created packages have 0.1.0
version so pay attention if the version changes, update it in other packages.
Finally, run the below command inside your root folder (where lerna.json
is) to install packages.
1 |
|
Plugin configuration
Go to the src
folder of bootstrap-v5-core
package and create each of below files there.
Size
As I mentioned before, I want to write a configurable Bootstrap plugin so create src/Size.ts
file.
1 |
|
I made a Size
enum to handle all Bootstrap sizes. Next we can manage our components according to size value.
Global Bootstrap 5 Options
Create src/IGlobalBootstrapV5Options.ts
file.
1 |
|
You need to define your configs via an interface With its default values as a constant.
DI
Create src/BootstrapV5Configuration.ts
file.
1 |
|
We can define our IGlobalBootstrapV5Options
to DI container so this happened via IBootstrapV5Options
constant.
createIBootstrapV5Configuration
is the most important part of creating settings.
register(container: IContainer)
helps us to introduce our default config to DI container.customize(cb?: (options: IGlobalBootstrapV5Options) => void)
alse helps us to introduce our custom config to the DI container.
Finally, we should export our current configuration with default options via BootstrapV5Configuration
.
Exports
Create src/index.ts
file.
1 |
|
Create new index.ts
file inside bootstrap-v5-core
package.
1 |
|
Plugin implementation
Go to the src
folder of bootstrap-v5
package, create a button
folder then create each of below files there.
- Resource
Create resource.d.ts
file.
1 |
|
- View
Create bs-button.html
file.
1 |
|
- ViewModel
Create bs-button.ts
file.
1 |
|
As you can see we are able to access to plugin options easy via ctor
(DI) and react appropriately to its values.
In this example I get the size from the user and apply it to the button component.
- Button Index
Create src/button/index.ts
file.
1 |
|
- Src Index
Create src/index.ts
file.
1 |
|
- Global Index
Create new index.ts
file inside bootstrap-v5
package.
1 |
|
Plugin usage
Open demo
package and go to the src
and update main.ts
.
1 |
|
Importing is available for whole components
1 |
|
Or just a component
1 |
|
To register your components you should add them to register
method.
1 |
|
Proudly, we support configuration so we should introduce it to register
method too.
1 |
|
Now, You are able to use your bs-button
inside src/my-app.html
.
1 |
|
To run the demo
easily, go to the root folder (where lerna.json
is) and add the following script to package.json
.
1 |
|
Then, call the command
1 |
|
Enjoy!