用VUE 3和VITE制作和分发UI组件
#javascript #网络开发人员 #vue #vite

介绍

在多个项目上工作时往往会发生的情况是,每个项目都需要相同的通用组件,例如有程式化的文本字段或更复杂的诸如日期选择器之类的东西。

最好的行动过程是编写一个组件并从单个点进行更新,它是从中分发的软件包。

我们将要做的是编写一个NPM软件包,该软件包将带有打字稿类型定义的VUE 3组件进行启动!我选择制作的组件是此演示的三态复选框。

开始

我将在此项目中使用Vite,因为它是WebPack作为构建工具和开发服务器的不错替代方法。使用您选择的软件包管理器来创建一个项目,我会选择yarn

yarn create vite

选择这些设置并命名您的项目理想情况下,您将如何命名最终组成部分:

√ Project name: ... vue-tri-state-checkbox
√ Select a framework: » Vue
√ Select a variant: » TypeScript

清除您不需要的任何文件或代码的项目,我通常只使用App.vue进行测试目的,并使用components文件夹用于存储组件并导出它们。

您的src文件夹应该看起来像:

src folder

组件

在VUE 3的工作原理上写下您的组件,我将使用它作为我的组件的示例:

<template>
  <label>
    <input
      type="checkbox"
      :disabled="disabled"
      :indeterminate="val === null"
      :checked="val === true"
      @click="change"
    />
    <span>
      {{ label }}
    </span>
  </label>
</template>

<script setup lang="ts">
import { ref, watch } from "vue";

const props = withDefaults(
  defineProps<{
    label?: string;
    modelValue: boolean | null;
    disabled?: boolean;
    color?: string;
  }>(),
  {
    color: "#2f4fef"
  }
);

const emit = defineEmits<{
  (e: "update:modelValue", value: boolean | null): void;
}>();

const val = ref<boolean | null>(false);

const change = () => {
  if (val.value === false) val.value = null;
  else if (val.value === null) val.value = true;
  else val.value = false;
  emit("update:modelValue", val.value);
};

watch(
  () => props.modelValue,
  (value) => (val.value = value)
);
</script>

使组件可导出

在您的src文件夹中,我们将创建一个index.ts文件,该文件将用于从components文件夹导出组件。

import TriStateCheckbox from "./components/triStateCheckbox.vue";
export { TriStateCheckbox };

我们将需要一些新的依赖项,因此将这些软件包添加到您的开发依赖项中,这些软件包将很快解释:

yarn add vite-plugin-dts path -D

默认的vite.config.ts您在这一点上应该有类似于以下内容:

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()]
});

我们将增加几行,因此:

import vue from "@vitejs/plugin-vue";
import * as path from "path";
import { defineConfig } from "vite";
import dts from "vite-plugin-dts";

export default defineConfig({
  plugins: [vue(), dts()],
  build: {
    lib: {
      entry: path.resolve(__dirname, "src/index.ts"),
      name: "TriStateCheckbox",
      fileName: "vue-tri-state-checkbox"
    },
    rollupOptions: {
      external: ["vue"],
      output: {
        globals: {
          vue: "Vue"
        }
      }
    }
  },
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "src")
    }
  }
});

让我们介绍这里发生的事情:首先,在plugins属性中,我们添加了dts,这是vite-plugin-dts软件包的一部分。它的主要目的是从VUE文件中创建类型定义文件以自动以获得更好的开发体验,也就是说,它可以从.vue创建d.ts文件。

build属性中,我们定义了一些其他属性,这些属性将用于定义软件包本身的构建过程如何工作。

lib告诉构建过程,将整个东西像对待整个库一样对待,请阅读更多here。我们在此处定义的属性是:

  • build-包装导出的位置,也就是说用户在发布后从何处导入软件包,在这里我们使用path函数和__dirname变量指向先前定义的index.ts folde4 index.ts文件夹,该变量指向主要项目的文件夹
  • name-包装的唯一标识符,尝试将其与您的软件包名称保持一致
  • fileName-一种唯一标识符,将用于描述包装文件输出

rollupOptions中,我们将定义一些内容来告诉croulup如何配置模块bundler:

  • external-运行包装所需的任何外部依赖关系的定义,在这种情况下,vue本身,请阅读更多here
  • output.globals-需要为使用的外部依赖项提供上下文,请阅读更多here

最后,使用resolve属性将@定义为src文件夹路径的别名。

接下来,我们将编辑tsconfig.json文件:

{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "strict": true,
    "jsx": "preserve",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "esModuleInterop": true,
    "lib": ["ESNext", "DOM"],
    "skipLibCheck": true,
    "noEmit": true
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

明显的更改是target属性,通常是从ES2020的过渡,默认为ESNext

建立包裹

您都完成了上面提到的文件的编辑时,我们需要查看构建过程是否通过运行yarn build来工作。

您应该获得与此类似的输出:

$ vue-tsc && vite build
vite v4.3.9 building for production...
✓ 4 modules transformed.
dist/style.css              2.15 kB │ gzip: 0.65 kB
dist/vue-tri-state-checkbox.js  1.12 kB │ gzip: 0.58 kB
dist/vue-tri-state-checkbox.umd.cjs  1.09 kB │ gzip: 0.61 kB

[vite:dts] Start generate declaration files...
✓ built in 1.29s
[vite:dts] Declaration files built in 822ms.

Done in 3.49s.

有3个生成的文件,如果您添加了更多依赖项或将组件拆分为多个文件,则可能还有更多。这些是:

  • style.css-包装的CSS捆绑在一个单数入口点
  • vue-tri-state-checkbox.js-包含捆绑的JavaScript代码
  • 的主要软件包入口点
  • vue-tri-state-checkbox.umd.cjs-通用模块系统和常见的JS入口点

所有这些都位于dist文件夹中,该文件夹将用于使用NPM分配包装。

dist folder

不过,在我们这样做之前,我们必须编辑package.json

package.json

我们需要更改package.json才能分发新创建的组件(单词和软件包将从现在开始互换使用):

  • private需要设置为false
  • 添加files属性以指定哪些文件将在软件包函数中起作用,在使用yarn build构建组件后,所有分发文件都将在dist文件夹中
"files": ["dist", "src/components/"],

此外,我们将添加src/components文件夹,因为这些组件是从那里导出的。

  • repository属性中命名您的git存储库
"repository": {
  "type": "git",
  "url": "git+https://github.com/MatijaNovosel/tri-state-checkbox.git"
},
  • 指定一些关键字
"keywords": [
  "checkbox",
  "material",
  "material-ui",
  "tri-state-checkbox",
  "vue3",
  "vue",
  "vuejs"
],
  • 通过main属性设置包装的主要入口点
"main": "./dist/vue-tri-state-checkbox.umd.cjs",
  • 设置module属性,它被main属性掩盖为noted here,但仍然需要
"module": "./dist/vue-tri-state-checkbox.js",
  • 定义dts包装生成的软件包类型的types属性
"types": "./dist/index.d.ts",
  • 设置将用于分发软件包文件的exports属性
"exports": {
  ".": {
    "import": "./dist/vue-material-time-picker.js",
    "require": "./dist/vue-material-time-picker.umd.cjs"
  },
  "./dist/style.css": {
    "import": "./dist/style.css",
    "require": "./dist/style.css"
  }
},
  • 最后,添加仅包含vuepeerDependencies属性,该部分将用于定义该软件包所依赖的包装
"peerDependencies": {
  "vue": "^3.0.0"
},

完整的package.json文件如下:

{
  "name": "vue-tri-state-checkbox",
  "private": false,
  "version": "0.0.1",
  "type": "module",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/MatijaNovosel/tri-state-checkbox.git"
  },
  "keywords": [
    "checkbox",
    "vue-tri-state-checkbox",
    "material",
    "material-ui",
    "vue3",
    "vue",
    "vuejs"
  ],
  "files": ["dist", "src/components/"],
  "main": "./dist/vue-tri-state-checkbox.umd.cjs",
  "module": "./dist/vue-tri-state-checkbox.js",
  "exports": {
    ".": {
      "import": "./dist/vue-tri-state-checkbox.js",
      "require": "./dist/vue-tri-state-checkbox.umd.cjs"
    },
    "./dist/style.css": {
      "import": "./dist/style.css",
      "require": "./dist/style.css"
    }
  },
  "types": "./dist/index.d.ts",
  "scripts": {
    "dev": "vite",
    "build": "vue-tsc && vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "sass": "^1.62.1",
    "vue": "^3.2.47"
  },
  "peerDependencies": {
    "vue": "^3.0.0"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^4.1.0",
    "path": "^0.12.7",
    "typescript": "^5.0.2",
    "vite": "^4.3.9",
    "vite-plugin-dts": "^2.3.0",
    "vue-tsc": "^1.4.2"
  }
}

不要忘记将版本设置为0.0.1或您选择的其他选择。

分发包裹

首先,您需要使用npm login登录,完成该过程,然后运行npm publish

如果一切都进行了计划,您应该在输出中看到此支架:

npm notice Publishing to https://registry.npmjs.org/
+ vue-tri-state-checkbox@0.0.1

检查NPM页面本身应该可以立即安装:

NPM page

在新项目的内部,您应该能够使用选择的软件包管理器:yarn add vue-tri-state-checkbox

使用该组件,在全球定义它或仅在本地导入它,包括CSS文件:

<template>
  <tri-state-checkbox v-model="val" />
</template>

<script lang="ts" setup>
import { ref } from "vue";
import { TriStateCheckbox} from "vue-tri-state-checkbox";
import "vue-tri-state-checkbox/dist/style.css";
const val = ref(null);
</script>

更新软件包

如果您需要随时对项目进行更改,只需在package.json版本编号上,再次构建包装并运行npm publish

结论

即使有点乏味,使您的项目的可导出组件可以节省时间,而且非常实用。

可以找到该项目的源代码here