Monday, March 23, 2020

Adding Bootstrap to a Vue CLI Project (Not using bootstrap-vue)

The Vue CLI is an awesome tool to kick-start your Vue projects. But by default — and rightly so — it comes with very little in the way of styling. Follow along and I’ll show you how to add Bootstrap so you can take advantage of all of it’s front-end features.


The very short version

I recommend reading through the whole post below at least once. But if you’re just here to get this set up as fast as possible, the short version is this:
  1. npm i bootstrap jquery popper.js

Getting set up

In order to show every step from start to finish, I’m going to create a new project from scratch. If you already have a project (that you set up with Vue CLI 3), you can skip this section.
If you don’t already have Vue CLI version 3, install it.
Now create the app.
> vue create withbootstrap
? Please pick a preset: (Use arrow keys)
> default (babel, eslint)
I named my app “withbootstrap”, but you can name yours whatever you like. Also notice I used the default present, which uses Babel and ESLint.
Once the app is created, move into the directory and serve the app.
> cd withbootstrap
> npm run serve
Your new Vue app is available at http://localhost:8080/


Even though we haven’t installed it yet, I’m going to add a Bootstrap component to the app, just so we’ll be able to see it as soon as we get everything working.
Open withbootstrap/src/components/HelloWorld.vue and add the follow HTML below the existing <h1>.
<div class="alert alert-success alert-dismissible fade show" role="alert">
  With Bootstrap!
  <button type="button" class="close" data-dismiss="alert" aria-label="Close">
    <span aria-hidden="true">&times;</span>
  </button>
</div>
The updated page looks like this:


The end result we’re looking for is a styled <div> that looks like a “success” alert, and allows you to close it with the × button. So far, the text and the button are there, but the style and functionality will come from Bootstrap as soon as we add it.

Adding Bootstrap styles and JavaScript

Still inside the withbootstrap directory, install Bootstrap and its dependencies.
> npm install bootstrap jquery popper.js
Note: If you’re not going to use Bootstrap’s JavaScript, and only going to use its styles, don’t worry about installing jQuery or Popper.js.
Finally, import it into the main script by adding these lines to the top of withbootstrap/src/main.js:
import 'bootstrap'
import 'bootstrap/dist/css/bootstrap.min.css'
Again, if you only want the styles, and not the JavaScript functionality, just leave off the first line and only include the CSS.
That takes care of both the JavaScript and the styles. The alert we wrote earlier now has the look and functionality we were looking for!


If you need to customize Bootstrap, which I highly recommend so your site doesn’t look like every other bare-bones Bootstrap site, you can read my post for Customizing Bootstrap Styles, Step-by-Step.

Friday, March 20, 2020

Vue.js - How to Build Your First Package & Publish It on NPM

We'll learn how to make our own plugin for Vue.js, and distribute it on NPM for everyone to use.
Plugins are what makes our lives as developers so much more productive. Most of our projects depend on them as they allow us to ship new features with great speed.
As stated in the Official Vue.js documentationthere is no strictly defined scope for a plugin. It simply adds global-level functionality to your project. But they typically fall into these five categories based on the things we are trying to achieve with them:
  1. Add some global methods or properties (e.g. this is what Vuex or vue-router does).
  2. Add one or more global assets (e.g. something like a stylesheet with/or a JavaScript library).
  3. Add some component options by global mixin (e.g. this is what vue-html-to-paper does).
  4. Add some Vue instance methods by attaching them to Vue.prototype (e.g. this is what vue-axios does).
  5. A library that provides an API of its own, while at the same time injecting some combination of the above.
Now that you understand how handy plugins can be and what needs they can fulfill, let’s see how to add one to your project. Then, we’ll learn how to make our own and distribute it on NPM for everyone to use (yes, it’s going to be super fun!).

How to Add a Vue.js Plugin to Your Project.

To use your plugin after you’ve installed it with npm install (or yarn add), you need to go to your main.js file. This is the entry point that drives our Vue application. Import it and call the Vue.use() global method. One word of caution though: All plugins must instantiated before you start your app with new Vue().
import Vue from "vue";
import YourPlugin from "yourplugin";

Vue.use(YourPlugin);

new Vue({
// [...]
})
JavaScript
There is also another way to add a new plugin when the package author allows it: dropping the CDN link in your header’s script tag.
<script src="https://cdn.jsdelivr.net/npm/yourplugin@latest/dist/yourplugin.min.js"></script>
JavaScript
Sometimes, you would like to customize how a plugin behaves. You can easily do so by passing some options to it when calling Vue.use(). Here is how it works:
Vue.use(YourPlugin, {
 someOption: false,
 anotherOption: false
})
JavaScript
For instance with vue-chartist, you can choose the text to display when no data is available to properly draw the chart as follows:
Vue.use(VueChartist, {
 messageNoData: "You have not enough data"
});
JavaScript
Now let’s get back to the main event — building your first Vue.js plugin together. 💪

How to Build Your Own Vue.js Plugin from Scratch

If you are reading this, you are probably a frontend developer like me. And like any other frontend developer, you probably love having nice handsome buttons for your interfaces! So that’s what we’ll be building: a bunch of nice handsome buttons that we’ll be able to reuse. This will save us a lot of time for future projects! You’ll also have the knowledge to package all your remaining base components and why not release your own design system?

Step 1: Initializing the Plugin Structure

Let’s create an empty folder for our package and initialize NPM. This will generate a new package.json file. We’ll deal with it later.
$ mkdir nice-handsome-button && cd nice-handsome-button
$ npm init
# The command above will create a new package.json
# Press enter to answer all the following questions
Bash
Add a new folder called src at the root, in which you create a new file NiceHandsomeButton.vue. You can rapidly prototype with just a single *.vue file with the vue serve and vue buildcommands, but they require an additional global addon to be installed first:
npm install -g @vue/cli
npm install -g @vue/cli-service-global
Bash
Now if you run:
$ vue serve src/NiceHandsomeButton.vue
Bash
Visit http://localhost:8080/. A blank page should appear in your browser. Let’s work on our button component from now on! 👩‍💻👨‍💻
You can read more about @vue/cli-service-global in the official documentation. This addon is that it is quite useful for working on a single .vue file without scaffolding an entire project with vue create my-new-project.

Step 2: Working on Our Handsome Button Component

Template

As this tutorial is not about learning how to write Vue components, I expect you to be familiar with the basics. The full code of our nice handsome button is available below (the template, the JavaScript logic and the style). Copy it, open NiceHandsomeButton.vue and paste the content inside.
<template>
 <button
  @click="onClick"
  @dblclick="onDoubleClick"
  :class="[
   'nice-handsome-button',
   'nice-handsome-button--' + color,
   'nice-handsome-button--' + size,
   {
    'nice-handsome-button--rounded': rounded
   }
  ]"
 >
  <slot></slot>
 </button>
</template>
HTML
We have kept things simple, but here are a few things to note:
  • I am using BEM. If you are not familiar with it, please read this now: MindBEMding — getting your head 'round BEM syntax.
  • I added the props colorsize and rounded. As their names indicate, they will allow us to control the color, the size and whether or not our button should be rounded.
  • I’m also using a slot for the content so that we can use it like a normal button <nice-handsome-button>My Button Label</nice-handsome-button>.

JavaScript

Let’s define the props our component can accept as well as the two methods that will emit an event when we click/double-click on it.
<script>
export default {
 props: {
  color: {
   type: String,
   default: "blue",
   validator(x) {
     return ["blue", "green", "red"].indexOf(x) !== -1;
   }
  },
  rounded: {
   type: Boolean,
   default: true
  },
  size: {
   type: String,
   default: "default",
   validator(x) {
    return ["small", "default", "large"].indexOf(x) !== -1;
   }
  },
 },

 methods: {
  onClick(event) {
   this.$emit("click", event);
  },

  onDoubleClick(event) {
   this.$emit("dblclick", event);
  },
 }
};
</script>
JavaScript

Style

Last but not least, let’s style our component. 👩‍🎨
<style>
.nice-handsome-button {
 display: inline-block;
 outline: 0;
 border: 1px solid rgba(0, 0, 0, 0.1);
 color: #ffffff;
 font-weight: 500;
 font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
 user-select: none;
 cursor: pointer;
}

/* --> COLORS <-- */

.nice-handsome-button--blue {
 background-color: #0194ef;
}

.nice-handsome-button--green {
 background-color: #1bb934;
}

.nice-handsome-button--red {
 background-color: #e1112c;
}

/* --> SIZES <-- */

.nice-handsome-button--small {
 padding: 8px 10px;
 border-radius: 4px;
 font-size: 12px;
 line-height: 12px;
}

.nice-handsome-button--default {
 padding: 12px 14px;
 border-radius: 6px;
 font-size: 14px;
 line-height: 16px;
}

.nice-handsome-button--large {
 padding: 16px 18px;
 border-radius: 8px;
 font-size: 16px;
 line-height: 20px;
} 

/* --> BOOLEANS <-- */

.nice-handsome-button--rounded {
 border-radius: 60px;
}
</style>
Sass (Scss)
Our component is now ready to use and can be used like this:
<nice-handsome-button :rounded="true" color="red" size="large">My Button</nice-handsome-button>
HTML
Let’s package it now. 💪

Step 3: Write the Install Method

Before we start this section, let’s create an index.js file in your src folder.
Remember that Vue.use() global we talked about earlier? Well… what this function does is call the install() method that we will define now.
This function takes two parameters: the Vue constructor and the options object that a user can set. You can skip the last argument if you don’t need it as it is optional. But if you want to make your plugin customizable, remember this is where you will catch the different parameters:
Vue.use({
 param: "something"
})`;

// Then in your install method options.param will equal to "something"
JavaScript
Back to our pluging. Now in index.js, let’s import our component and define our install method.
import NiceHandsomeButton from "./NiceHandsomeButton.vue";

export default {
 install(Vue, options) {
  // Let's register our component globally
  // https://vuejs.org/v2/guide/components-registration.html
  Vue.component("nice-handsome-button", NiceHandsomeButton);
 }
};
JavaScript
Congratulations, you almost made it! 👏

Step 4: Reworking package.json

Open your package.json file that you created when running npm init.
{
 "private": false,
 "name": "nice-handsome-button",
 "version": "0.0.1",
 "description": "A nice handsome button to help you learn basin plugin craftsmanship 🎨",
JSON
 "author": "Nada Rifki",
 "license": "MIT",
 "main": "./dist/index.js",
 "scripts": {
  "dev": "vue serve NiceHandsomeButton.vue",
  "build": "bili --name index --plugin vue --vue.css false"
 },
 "files": [
  "dist/*"
 ]
}
JSON
A few notes:
  • private is set to false. This means your package is public (i.e. everyone is able to see and install it).
  • Choose a name for your package. You have to make sure that it’s not already taken.
  • The version number is set to 0.0.1. You will have to increment this number every time you publish an update for your package. If you are not familiar with semantic versioning, I highly recommend you read this.
  • Choose a description that describes your package in a few words. This will help other developers understand what pain your plugin solves.
  • The main is the primary entry point to your program. That is, if your package is named foo, and a user installs it, and then does require("foo"), then your main module’s exports object will be returned.
  • The scripts property is a dictionary containing script commands that you can easily run with npm run.
  • The files property specifies which files should be published on NPM. It is usually a bad idea to publish everything. We’ll be using bili, so all files in dist folder should be included.

Bundling Your Library

In case you don’t know, bundling is the process of grouping all your code from all your files in your project into one single file. The reason behind this is simply to increase performance. This will also minify the code and accomplish some other cool things.
To do so, we’ll use Bili, a fast and zero-config library bundler that uses Rollup.js under the hood.
First make sure you have the latest version of Node.js (Bili requires Node.js 8 or above):
# Check your Node.js version
$ node -v
Bash
If the version of Node you’re using is outdated, head to node.js.org to update it.
Now, let's install Bili.
$ npm install --save-dev bili

# We'll need these two packages to transpile .vue files
# https://bili.egoist.moe/#/recipes/vue-component
$ npm install --save-dev rollup-plugin-vue
$ npm install --save-dev vue-template-compiler
Bash
Now, create our bili.config.js file in the root folder and add our bundling settings:
module.exports = {
  banner: true,
  output: {
    extractCSS: false,
  },
  plugins: {
    vue: {
      css: true
    }
  }
};
JavaScript
All you have left to do is run the command below on your terminal and your package is bundled — it’s as easy as 1-2-3!
$ npx bili --bundle-node-modules
Bash
You should obtain a new dist folder with a index.cjs.js file.
By default <style> tag in Vue SFC will be extracted to the same location where the JS is generated but with .css extension. That’s why we added --vue.css false in the command above.
To learn more about Bili and how to customize it, I recommend you take a look at the documentation.

Sharing Your Wonder on NPM

Now that your package is ready, the only thing left for you is to publish your package on NPM.
Start by creating an account on NPM (you can also run npm adduser if you prefer using the command lines). Then go to your terminal and run npm login. You will have to input your username, password and email.
You can check that you are logged in by typing npm whoami. This should display your username.
There is now only one terminal command that stands between you and publishing your package:
$ npm publish
And voilà! 🎉
To update your package, just increment the version number in your package.json and rerun npm publish.

How to Use Your Newly Published Library

You can install it like any other package:
$ npm install --save nice-handsome-button
Bash
In your main.js, or a similar entry point for your app:
import NiceHandsomeButton from "nice-handsome-button";
import Vue from "vue";

Vue.use(NiceHandsomeButton);
JavaScript
Now, the nice handsome button should be able in any of your .vue files.
<nice-handsome-button :rounded="true" color="red" size="large">My Button</nice-handsome-button>
HTML