🚲如何在npm轻快发布vite+vue组件 (aka教训总结

101 阅读4分钟

还记得人生第一次发布自己的npm是在一个阳光和煦的日子,还有那直到晚上十点半才圆满完成的不可置信和巨大成就感..

image.png

本文将区别于网上多数的 "教你怎么做" 类文章,实现告诉你 "为什么这么做",并总结出极为简易明了的步骤,尤其适合只发布单个或少量组件的年轻人。

目标

在npm上看到自己的项目,且支持下载后的局部引用和全局引用


概述

  1. 创建组件导出文件,即vite打包入口
  2. 修改vite.config.ts,调整打包入口即其余优化打包项
  3. 修改package.json ,增加npm上传信息
  4. run build & npm login & npm publish

详述

组件导入与导出

网上一般会说让你先建个package或者改个名,再建个文件夹,再建个index,云云,十分繁琐且不知为何,实际上如果你没有超复杂项目,甚至像我一样只发一个组件,那你只需要简单一步:

搞一个js/ts文件,将组件import进来,再统一导出出去,以下统一说ts

建议:在src目录下建个export.ts

// ts类型,js不需要这个
import type { App } from "vue"; 

// 导入你的组件,这个组件在哪都行,.vue都是可导入的模块,不固定哪个文件夹
import ImgViewer from "./components/ImgViewer.vue";
// 可以继续导入其它组件

// 导出你导入的,这里是为了支持局部引入,也就是import {...} form '...'
export { ImgViewer };

// 为了能放在app.use()里全局引入,需要整个他需要的install函数,这里用对象包起来是一样的
// 重点来了,下面的 ImgViewer.name 也就是组件名称,你必须要确定他有,而不是undefined,下面讲
// 这里默认导出,就是 import ... form '...' 不加大括号,叫啥都行
export default {
  install: (app: App): void => {
    app.component(ImgViewer.name, ImgViewer);
  },
};

关于组件名称

这个name很重要,如果是undefined是没办法传入app.use全局注册的

  • 如果你是vue2,那你直接可以在选项里填上name

  • 如果你是vue3,那么你大概率用setup语法糖,没办法直接设置name,这里有两个简单办法

    • 手动把 ImgViewer.name 改成你的项目名字,即直接传字符串 "ImgViewer"
    • 在组件里加一个script
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
  name: "ImgViewer",
});
</script>

验证方式是,在其它组件导入这个组件,然后输出他的名字,看有没有


修改vite.config.ts

vite是你拿来打包的,一般你不管他就是对着index.html去打包,沿途放入你使用的依赖,最后压缩转换成dist文件夹,所以这里我们换个打包入口,换成我们上一步写的

// 默认脚手架就有的
import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
// 这里可能要导入下
import path from "path";

export default defineConfig({
  // 默认不管
  plugins: [vue()],
  resolve: {
    alias: {
      "@": fileURLToPath(new URL("./src", import.meta.url)),
    },
  },
  // 你要加的 build 选项,参考vite文档 https://cn.vitejs.dev/guide/build.html#library-mode
  // 照着来就行,名字记得改
  build: {
    lib: {
      entry: path.resolve(__dirname, "src/export.ts"),
      name: "ImgViewer",
      fileName: (format) => `ImgViewer.${format}.ts`,
    },
    rollupOptions: {
      // 确保外部化处理那些你不想打包进库的依赖
      external: ["vue"],
      output: {
        // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
        globals: {
          vue: "Vue",
        },
      },
    },
  },
});

修改package.json

我会尽量给你接收每个属性的意义,竖起耳朵

{
  // 你的npm包名,不能有重名,自己去搜一搜看看
  "name": "vue3-img-viewer", 
   // 每次提交都必须和以前的不一样,可以unpublish这个版本,但是24小时不能提交刚删的
  "version": "0.0.9",
  // npm简介
  "description": "基于Vue3使用的图片查看组件", 
  
  // 你要上传的文件夹
  "files": [
    "dist" 
  ],
  
  //npm下面显示的关键词,丰俭由人
  "keywords": [
    "vue",
    "vue3",
    "imgViewer",
    "img",
    "image",
    "vue-img-viewer",
    "vueImgViewer"
  ],
  
  // 授权,一般大家都是这个,没啥功利要求的话
  "license": "MIT",
  "author": "minghe-lee",
  
  // 为支持es6的Tree Shaking,而设的module字段
  "module": "./dist/ImgViewer.es.ts",
  // 不支持es6就用es5版本
  "main": "./dist/ImgViewer.umd.ts",
  "exports": {
    // 配置这个就能识别别人的导入,直接 import 'pkgname' 就会导出es,require就会导出umd
    ".": {
      "import": "./dist/ImgViewer.es.ts",
      "require": "./dist/ImgViewer.umd.ts"
    },
    // 同理
    "./dist/style.css": {
      "import": "./dist/style.css",
      "require": "./dist/style.css"
    }
  },
  // 设置这个你才能发,表示你愿意发,因为npm是默认开源的,私有好像是收费的
  "private": false,
  
  // 默认配置
  "scripts": {
    "dev": "vite",
    "build": "run-p type-check build-only",
    "preview": "vite preview",
    "build-only": "vite build",
    "type-check": "vue-tsc --noEmit"
  },
  
  // 配置这个别人下你的包就不会连这下你这个依赖,peer表示共享依赖
  "peerDependencies": {
    "vue": "^3.2.45"
  },
  "devDependencies": {
    "@types/node": "^18.11.12",
    "@vitejs/plugin-vue": "^4.0.0",
    "@vue/tsconfig": "^0.1.3",
    "npm-run-all": "^4.1.5",
    "typescript": "~4.7.4",
    "vite": "^4.0.0",
    "vue-tsc": "^1.0.12"
  },
  "dependencies": {
    "vue": "^3.2.47",
  }
}

执行指令,打包发射

  1. run build

    查看自己的dist文件夹,必要时可以自己导入看看o不ok,因为这就是别人下回来的

  2. npm login

    登录,绑定邮箱,验证码 ...

  3. npm publish

    如果你设了淘宝源或其他非官方源要设回来

    npm config set registry https://registry.npmjs.org
    

    发布成功你会收到邮件