Vue3 + Vite package and release to npm process

Article directory

  • 1. Preparation work
  • 2. Initialization project
    • 2.1 Initialization:
    • 2.2 Create typescript configuration
    • 2.3 Install Vue3 and Vite
      • 2.4 Directory structure
  • 3. Write code
    • 3.1 Logical file code
    • 3.2 Declaration file code
  • 4. Configure Vite
  • 5. Configuration commands
    • 5.1 Write packaging commands
    • 5.2 Packaging components
  • 6. Release
    • 6.1 Register an account (first time use)
    • 6.2 Command to log in to NPM account
    • 6.3 Release
  • 7. Download the plug-in and use it

With the official release of Vue.js 3.0, the Vue ecosystem has entered a new stage. In Vue.js 3.0, Vite becomes the default development tool and replaces Vue CLI as the recommended build tool. At the same time, NPM, as a JavaScript package manager, is also an essential tool for developers. So this article will introduce how to package and publish a Vue component using Vue3, Vite and NPM.

1. Preparation

First, you need to ensure that Node.js, NPM and typescript are installed locally, which can be checked through the node -v, npm -v and tsc -v commands. If it is not installed, you need to download and install it first.

Then you need to create an empty folder as the root directory of the project.

2. Initialization project

2.1 Initialization:

npm init

Fill in the relevant information according to the prompts and generate the package.json file.

2.2 Create typescript configuration

implement

tsc --init

At this time, the tsconfig.json configuration file will be generated.

2.3 Install Vue3 and Vite

npm install vue vite -D

-g: global installation
-D: Development dependencies, suitable for dependencies we use in the development stage. The package name will be registered in devDependencies in package.json. Generally, this kind of package is only used during development. After development and packaging, we can use it without these packages. Continue running the project. For example: eslit, less, etc.
-S: Production environment, suitable for packages that we can continue to use after packaging and deployment. The package name will be registered in Dependencies in package.json. Packages that need to continue to be used after development and packaging to run normally, such as: echarts ,jquery etc.

Question: Why do you choose -D here?
Answer: We will also install vue and vite when creating the project, so there is no need to install it again when installing this plug-in.

2.4 Directory structure


After the installation is complete, you can create the corresponding ts file and d.ts declaration file as shown above.

3. Write code

3.1 Logical file code

Here, I use the custom instruction-watermark code I wrote before. For the implementation of custom instructions, please refer to my other blog: Vue3 Custom Instructions

code show as below:

//src/index.ts

import type {<!-- --> App } from "vue";
// watermark style
let style = `
display: block;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-repeat: repeat;
pointer-events: none;
opacity:0.5;
`;

const getDataUrl = (binding: any) => {<!-- -->
  const rotate = -20;
  const canvas = document.createElement("canvas");
  // canvas.style.width = "500";
  // canvas.style.height = "500";
  const ctx = canvas.getContext("2d");

  ctx?.rotate((rotate * Math.PI) / 180);
  ctx.font = binding.font;
  ctx.fillStyle = binding.fillStyle;
  ctx?.fillText(binding.text || "Confidential File", -10, 108);

  return canvas.toDataURL("image/png");
};

const waterMarker = {<!-- -->
  mounted(el: HTMLElement, binding: any) {<!-- -->
    init(el, binding);
  },
};

// initialization
const init = (el: HTMLElement, binding: any = {<!-- -->}) => {<!-- -->
  //Set watermark
  setWaterMark(el, binding.value);
  // Monitor
  createObserver(el, binding.value);
};

//Set watermark
const setWaterMark = (el: HTMLElement, binding: any = {<!-- -->}) => {<!-- -->
  const url = getDataUrl(binding);

  //Create waterMark
  const waterMark = document.createElement("div");
  waterMark.className = `water-mark`;
  style = `${<!-- -->style}background-image: url(${<!-- -->url});`;
  waterMark.setAttribute("style", style);
  el.setAttribute("style", "position: relative;");
  el.appendChild(waterMark);
};

const createObserver = (el: HTMLElement, binding: any) => {<!-- -->
  const waterMarkEl = el.querySelector(".water-mark");
  // prefixed in earlier versions of Firefox and Chrome
  const MutationObserver =
    window.MutationObserver ||
    window?.WebKitMutationObserver ||
    window?.MozMutationObserver;
  //Listen to node changes
  const observer = new MutationObserver((mutationsList) => {<!-- -->
    console.log("mutationsList", mutationsList);
    if (mutationsList.length) {<!-- -->
      const {<!-- --> removedNodes, type, target } = mutationsList[0];
      const currStyle = waterMarkEl?.getAttribute("style");

      if (removedNodes[0] === waterMarkEl) {<!-- -->
        // Stop observing
        observer.disconnect();

        init(el, binding);
      } else if (
        type === "attributes" & amp; & amp;
        target === waterMarkEl & amp; & amp;
        currStyle !== style
      ) {<!-- -->
        waterMarkEl.setAttribute("style", style);
      }
    }
  });

  observer.observe(el, {<!-- -->
    childList: true,
    attributes: true,
    subtree: true,
  });
};

const install = (app: App) => {<!-- -->
  app.directive("waterMarker", waterMarker);
};

export default {<!-- -->
  install,
};

3.2 Declaration file code

//index.d.ts
import type {<!-- --> App } from "vue";
declare const waterMarker: {<!-- -->
  install: (app: App) => void;
};
export default waterMarker;

4. Configure Vite

import {<!-- --> defineConfig } from "vite";

export default defineConfig({<!-- -->
  build: {<!-- -->
    lib: {<!-- -->
      // Could also be a dictionary or array of multiple entry points
      entry: "src/index.ts",
      name: "waterMarker",
      // the proper extensions will be added
      fileName: "water-marker",
    },
    rollupOptions: {<!-- -->
      // Make sure to externalize dependencies that you don't want to package into the library
      external: ["vue"],
      output: {<!-- -->
        // Provide a global variable for these externalized dependencies in UMD build mode
        globals: {<!-- -->
          waterMarker: "waterMarker",
        },
      },
    },
  },
});


Here, the lib configuration item is used to tell Vite that what is to be packaged is a library file, and the entry file, library name and output file name are specified. At the same time, use the rollupOptions configuration item to externalize Vue so that it will not be packaged into the component file when building, thereby reducing the packaging size.

5. Configuration commands

5.1 Writing packaging commands

Add the packaging command in the package.json file:

{<!-- -->
  "scripts": {<!-- -->
    "build": "vite build"
  }
}

5.2 Packaging components

Execute the following command to package:

npm run build

After packaging is completed, a dist folder will be generated in the project root directory

Next, you need to add the necessary fields to the package.json file:

{<!-- -->
  "name": "water-marker-vue",
  "version": "0.0.2",
  "description": "",
  "main": "dist/my-lib.umd.js",
  "module":"dist/my-lib.mjs",
  "scripts": {<!-- -->
    "test": "echo "Error: no test specified" & amp; & amp; exit 1",
    "build":"vite build"
  },
  "author": "",
  "license": "ISC",
  "files": [
    "dist",
    "index.d.ts"
  ],
  "devDependencies": {<!-- -->
    "vite": "^4.5.0",
    "vue": "^3.3.7"
  }
}



Note

  • The name field must be unique and cannot contain uppercase letters and spaces;
  • The main field should point to the packaged UMD format file;
  • The module field should point to the packaged ES Module format file;
  • The files field specifies the files that should be included in the release package; the files specified in the package.json, license, README and main fields are included by default when publishing. Ignore node_modules, lockfile, etc. files. Under normal circumstances, the built products and type files will be specified in files, and files in src, test and other directories do not need to be released accordingly.
  • The dependencies field specifies the dependent Vue and Vite version range

6. Publishing

6.1 Register an account (first time use)

Register and log in on npm official website

6.2 Command to log in to NPM account

npm login # Log in to NPM account

6.3 Release

npm publish # Publish components

After the release is successful, you can search for the package name you released on npm, if it can be found. The release is successful.
Note: The package name must be unique and cannot contain uppercase letters or spaces. Otherwise you will get the following error

7. Download the plug-in and use it

After the above steps, we have successfully packaged and published a Vue3 component to NPM. Next, we can install and use the component with the npm install command.

import waterMarker from "water-marker-vue";

app.use(waterMarker);

<div class="box" v-water-marker="watermarkObj"></div>

The above is the main code, we can see the watermark style on the page