DEV Community

Cover image for How to develop a svelte component and publish it as a package in NPM
Ernane Ferreira
Ernane Ferreira

Posted on

How to develop a svelte component and publish it as a package in NPM

Publish your favorite svelte component as a package on npm and make it available for use anytime.

When we like a certain component that we develop, we end up using and reusing it countless times, in different ways, that is; replicating your files and logic in many different places in the project, or in several other projects, or simply redeploying the same component over and over again. This will work, of course. However, it is not the best way to act in this situation.

Imagine that you will have to carry out maintenance, or simply change, say, the color of this component. Imagine that there are 10, 100, 200... Well, you will have to make this change in each component present in your project, correct? What if it is already applied to other projects? well, the change should be made too. The problem I think we already understood. But how to solve it?

When it comes to a project that uses the same technology, in the case that we will see in this post Svelte for example, you can create a component and publish it as a package in NPM and reuse it whenever you need it. That's what we'll see here! for cases where the projects do not share the same technology, this is a matter for another time. But if you like spoilers you can read about WebComponents.

What will we develop?

I recently made a simple svelte component - hence the idea of the post - to perform evaluations. It is simply a nest of stars and in it the user will be able to show his satisfaction with such content that the component will return the selected information in its configuration prop. He will be the one we will develop!

For this, you need to have an account on NPM, have NodeJs and NPM installed on your machine and be patient to venture out!

Initializing the project

The first step, like any project, is to create a directory for it. let's go!

$ mkdir svelte-star-rating
$ cd svelte-star-rating
Enter fullscreen mode Exit fullscreen mode

Now, we can actually initialize our project.

$ npm init -y
Enter fullscreen mode Exit fullscreen mode

This command will create a package.json file and will automatically fill in some information about the package we are developing like name, author, description, etc... the -y flag will perform a short auto-fill. If you want to do it manually run without it. But don't worry, you can always change package.json when needed.

Installing required dependencies

The next step is to install the necessary development dependencies of our package. That way, notice that package.json will add the dev dependencies section. In addition, I will take the opportunity to make some changes, such as name, author, keywords, etc. Feel free to fill in as you see fit.

Finally, the package.json should look like this:

{
  "name": "@ernane/svelte-star-rating",
  "version": "1.0.0",
  "description": "Simple component to assign scores based on stars.",
  "homepage": "https://github.com/ErnaneJ/svelte-star-rating",
  "bugs": {
    "url": "https://github.com/ErnaneJ/svelte-star-rating/issues"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/ErnaneJ/svelte-star-rating.git"
  },
  "keywords": [
    "svelte",
    "star",
    "ratting",
    "component",
    "sapper"
  ],
  "author": "ernane <ernane.junior25@gmail.com>",
  "license": "MIT",
  "devDependencies": {
    "rollup": "^2.39.0",
    "rollup-plugin-node-resolve": "^5.2.0",
    "rollup-plugin-svelte": "^7.1.0",
    "svelte": "^3.32.3"
  }
}
Enter fullscreen mode Exit fullscreen mode

Criação do componente

As usual, I create my logic files usually in a subdirectory named src, I'll follow that pattern here. In this way, we will create an index.js file, it will be the starting point of our component.

Basically we will import the main component of our package and export it as default in index. It will be something like this:

// src/index.js
import SvelteStarRating from './SvelteStarRating.svelte';
export default SvelteStarRating;
Enter fullscreen mode Exit fullscreen mode

As a consequence we will now have to create the file, which will be our svelte component itself, SvelteStarRating.svelte. To test it, let's just put a test message at the moment!

<!-- src/SvelteStarRating.svelte -->
<p>Hello World! It's my first package svelte component! ✨ SvelteStarRating ✨</p>
Enter fullscreen mode Exit fullscreen mode

In this file we will have all the logic and implementation of our package. In it we will add styles, necessary imports, among other things.. Let's go ahead, we'll be back in it!

Formalizing structure

Now that we have the main structure of our component, we need to formalize it in our package.json. For this, we will need to make some more changes to it.

// ...
"main": "dist/index.js",
"module": "dist/index.mjs",
"svelte": "src/index.js",
"scripts": {
    "build": "rollup -c",
    "dev": "rollup -c -w"
},    
// ...
Enter fullscreen mode Exit fullscreen mode

Since this part is a bit tricky, let's see what it's actually doing:

  • In main we define what will be the output after the execution of the compilation script,
  • In module we define the same, but as output an mjs extension file so that Node can differentiate it among the modules created with CommonJS and ES6.
  • In svelte, we are defining the path of our main file, the index.js that we created earlier.
  • And, finally, scripts will be the commands used for execution and compilation in development.

Note that the dist subdirectory, which we specified in the first two commands, does not exist as it will be automagically generated ✨.

After these small changes our package.json will look like this:

{
  "name": "@ernane/svelte-star-rating",
 "version": "1.0.0",
  "description": "Simple component to assign scores based on stars.",
  "main": "dist/index.js",
  "module": "dist/index.mjs",
  "svelte": "src/index.js",
  "scripts": {
    "build": "rollup -c",
    "dev": "rollup -c -w"
  },
  "homepage": "https://github.com/ErnaneJ/svelte-star-rating",
  "bugs": {
    "url": "https://github.com/ErnaneJ/svelte-star-rating/issues"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/ErnaneJ/svelte-star-rating.git"
  },
  "keywords": [
    "svelte",
    "star",
    "ratting",
    "component",
    "sapper"
  ],
  "author": "ernane <ernane.junior25@gmail.com>",
  "license": "MIT",
  "devDependencies": {
    "rollup": "^2.39.0",
    "rollup-plugin-node-resolve": "^5.2.0",
    "rollup-plugin-svelte": "^7.1.0",
    "svelte": "^3.32.3"
  }
}
Enter fullscreen mode Exit fullscreen mode

Creating the rollup.config.js file

You are probably already familiar with this file because it is Svelte. But basically we perform the basic build configuration of our simple project.

import svelte from "rollup-plugin-svelte";
import resolve from "rollup-plugin-node-resolve";
const pkg = require("./package.json");
export default {
    input: "src/AtButton.svelte",
    output: [
        { file: pkg.module, format: "es" },
        { file: pkg.main, format: "umd", name: "Name" },
    ],
    plugins: [svelte(), resolve()],
};
Enter fullscreen mode Exit fullscreen mode

Wow! Package successfully configured for use. 🥳

Testing component locally

Before we publish our new component on NPM, it's always good to test it to see how it really is and if its result is satisfactory. For this, we can use it on our machine even before we send it for publication. For this, let's create, in parallel, a simple project in Svelte. For this case, I'll use svelte-playground itself.

$ npx degit sveltejs/template svelte-playground
Enter fullscreen mode Exit fullscreen mode

Then we access the cloned project and install two initial dependencies.

$ cd svelte-playground
$ npm install
Enter fullscreen mode Exit fullscreen mode

Now, in order to use our component as an npm package and apply it to this project, we can run the following command in the directory of our svelte-star-rating package.

$ npm link
Enter fullscreen mode Exit fullscreen mode

With it we will get a response similar to this:

# npm WARN svelte-star-rating@1.0.0 No repository field.

# audited 17 packages in 0.711s

# 3 packages are looking for funding
#   run npm fund for details

# found 0 vulnerabilities
Enter fullscreen mode Exit fullscreen mode

After that, now in the svelte-playground test project we can run the same command, but now, going to the directory of our new package on our machine.

$ npm link /path/svelte-star-rating
Enter fullscreen mode Exit fullscreen mode

That way we can use our component as a package locally, and best of all, in realtime!

Using component locally

Access the test project we created, svelte-playground, and run the project under development using the command present in your package.json.

$ npm run dev
Enter fullscreen mode Exit fullscreen mode

EThen access the browser at the suggested port and see the application running. After that, we can now apply our component to this project and thus visualize its changes at runtime.

for that, we go to the src/app.svelte file, to make some changes.

<!-- src/app.svelte -->
<script>
  ...
  import StarRating from "@ernane/svelte-star-rating";
  ...
</script>

...
<StarRating/>
...
Enter fullscreen mode Exit fullscreen mode

And then we'll have our component running locally. Fantastic, isn't it!?

Now we just have to develop our new component the way we want and check if the changes made match what we want. Here is the current development status of my svelte-star-rating.

Publishing package in NPM

Great, we already have our component working we would like. And now? well, now we publish it! Publishing is as simple as a push, check it out...

First, you must be logged into your NPM account, if you are not or don't know, just follow the steps described here.

After being logged in, and sure you want to publish the first version of your package, just run the following command:

$ npm publish --access public
Enter fullscreen mode Exit fullscreen mode

Ready! you can access your profile on the NPM page and you will see a new package added! 🎉 Simple no?!

Testing new NPM package

You've undoubtedly done this here hundreds of times, or maybe less 😅.. Access your package information that will tell you how to install it. But following the standards you can do it with the simple npm install passing the name, defined in the package.json, of your project!

i.e,

$ npm i @ernane/svelte-star-rating
Enter fullscreen mode Exit fullscreen mode

Usage will be the same as before, import and use. Well, that you already know!

If you have any questions, here is the repository that I used to store the package mentioned here in the post and the link to it already published on npm!

I hope you enjoyed this post and that it helped you, in some way, to find what you were looking for! 💙

Top comments (4)

Collapse
 
webjose profile image
José Pablo Ramírez Vargas

I like this because it explains how to do it from scratch. However, I must ask: What do you think about using SvelteKit to create a component library? It is the current recommended way of doing it, officially.

Collapse
 
ernanej profile image
Ernane Ferreira

Glad you liked it! I tried to be as clear as possible and do everything from scratch for those who never did!

But yeah, it really is better to do it with SvelteKit as that's the current recommended way. The only reason I did without SvelteKit is because I had already written it by the time I developed the Star-ratting project and this post was in my notes just waiting to be published. But, in the future, I intend to update it or write a new version for a new component using SvelteKit.

Thanks for your comment!

Collapse
 
webjose profile image
José Pablo Ramírez Vargas

+1 to a new version (as opposed to editing this one). If you remember, please make the comparison and whether or not you find issues. Personally, I found the issue that main in package.json seems to be required, although SvelteKit doesn't add it. If I remember correctly, some ES standard/convention says it shouldn't be required, but it ends up being anyway.

Someone with your expertise can probably unveil this mystery for us mortals. 😄

Thread Thread
 
ernanej profile image
Ernane Ferreira

Thank you for your enthusiasm for the new version! I'll try to make sure to compare it to the previous one and see if there are any issues. Regarding the "main" entry in the package.json file, you are right that according to some ES standards/conventions this should not be mandatory. However, in certain cases, it may still end up being necessary. Possibly I will delve into this mystery and share my findings here when possible. It's always exciting to explore these details and demystify them! 🔥