Vite创建npm包并发布到私有仓库

1,472 阅读3分钟

[Talk is cheap. Show me the code]

使用背景:
当公司出现多个系统,多个系统之间需要进行跳转组件时,因此需要一个跳转的导航组件,而在各个业务系统中都维护一个业务组件耗时耗力,因此将这种公共业务组件做成一个npm包的形式,发布到公司私有的gitlab上,公司内部代码切记不要发布到公网,其他业务系统只需要按需下载即可。

1.使用vite创建一个vue3项目并做相关配置

在工具上你可以选择其他工具,当然也会遇到一些其他可能会出现的问题,如果你不愿意重复的去造轮子,完全可以跟我选择一样的工具,你需要保证自己了解这些工具的基本使用,你需要用到的工具(‘/’为或的意思)有:

nvm/n
yarn/npm/pnpm
vite
vue3
element-plus
ts

1.1 创建一个vue3项目并进行相关配置

    yarn create @vitejs/app  //选择自己的framework&variant  内容参考见下图
    cd bc   //这里根据自己的项目名称进行切换
    yarn
    

image.png

1.2 进行相关的代码配置

这里请根据自己的需要进行相关的修改,相关参数请翻阅对应的文档,我们需要做的配置有:
1:eslint配置 ESLint相关配置实现
2:vite.config.ts


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

// import path from 'path';
// import { resolve } from 'path'

const path = require('path')
function _resolve(dir: string) {
  return path.resolve(__dirname, dir);
}
export default env => {
  return defineConfig({
    plugins: [
      vue(),
    ],
    css: {
      preprocessorOptions: {
        scss: {
          prependData: '@use "@/assets/style/element/index.scss" as *;'
        }
      }
    },
    resolve: {
      alias: {
      '@': _resolve('src'),
      '@assets': _resolve('src/assets'),
      '@comps': _resolve('src/components'),

      },
      extensions: ['', '.ts', '.tsx', '.js', '.scss'],
    },
    server: {
      open: true, // 自开启浏览器
      host: '0.0.0.0', // fix use `--host` to expose
      // disableHostCheck: true,
      https: true,
      proxy: {
      
      }
    },
    esbuild: false,
    build: {
      lib: {
        entry: _resolve('src/index.ts'),
        name: 'app',
        fileName: (format) => `app.${format}.js`
      },
      terserOptions: {
        compress: {
          keep_infinity: true,
          // 删除console
          drop_console: true
        }
      },
      // 禁用该功能可能会提高大型项目的构建性能
      brotliSize: false,
      rollupOptions: {
        // 确保外部化处理那些你不想打包进库的依赖
        external: ['vue'],
        output: {
          // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
          globals: {
            vue: 'Vue'
          }
        }
      }
    }
  });
};

3:tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "useDefineForClassFields": true,
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "lib": ["esnext", "dom"],
    "types": ["element-plus/global"],
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    },

  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  "references": [{ "path": "./tsconfig.node.json" }],
  // "extends": "./tsconfig.node.json"
}

4:package.json

{
  "name": "**自行决定",
  "private": true,
  "version": "0.0.1",
  "author": {
    "name": "st77"
  },
  "files": [
    "dist"
  ],
  "scripts": {
    "dev": "vite",
    "build": "vue-tsc --noEmit --skipLibCheck && vite build",
    "preview": "vite preview"
  },
  "module": "./dist/app.es.js",
  "main": "./dist/app.umd.js",
  "exports": {
    ".": {
      "import": "./dist/app.es.js",
      "require": "./dist/app.umd.js"
    },
    "./dist/style.css": {
      "import": "./dist/style.css",
      "require": "./dist/style.css"
    }
  },
  "keywords": [
    "mtbc"
  ],
  "dependencies": {
    "element-plus": "^2.0.1",
    "path": "^0.12.7",
    "vue": "^3.2.25",
    "@wefly/vue-virtual-scroller": "^1.0.5",
    "axios": "^0.21.1",
    "lodash": "^4.17.21",
    "vue-clipboard3": "^1.0.1",
    "vue-router": "^4.0.5",
    "vuex": "^4.0.0"
  },
  "devDependencies": {
    "@types/node": "^17.0.17",
    "@vitejs/plugin-vue": "^2.2.0",
    "typescript": "^4.5.4",
    "vite": "^2.8.0",
    "vue-tsc": "^0.29.8",
    "@ehutch79/vite-eslint": "0.0.1",
    "@vue/compiler-sfc": "^3.0.5",
    "@vue/eslint-config-prettier": "^6.0.0",
    "autoprefixer": "^10.2.5",
    "babel-eslint": "^10.1.0",
    "crypto-js": "^4.0.0",
    "element-plus": "^1.3.0-beta.5",
    "eslint": "^6.7.2",
    "eslint-config-standard": "^10.2.1",
    "eslint-friendly-formatter": "^3.0.0",
    "eslint-loader": "^1.7.1",
    "eslint-plugin-import": "^2.7.0",
    "eslint-plugin-node": "^5.2.0",
    "eslint-plugin-prettier": "^3.1.3",
    "eslint-plugin-promise": "^3.4.0",
    "eslint-plugin-standard": "^3.0.1",
    "eslint-plugin-vue": "^7.0.0-0",
    "extract-text-webpack-plugin": "^3.0.0",
    "husky": "^1.3.1",
    "lint-staged": "^9.5.0",
    "mockjs": "^1.1.0",
    "prettier": "^1.19.1",
    "sass": "^1.41.1",
    "vite-plugin-mock": "^2.3.0",
    "vite-plugin-svg-icons": "^0.4.0"
  }
}

2、编写代码并在本地进行调试

2.1 编写你需要的组件并导出

我这里编写了一个app-nav组件,请保证你的文件路径正确,示例如下:

image.png app-nav.vue

<template>
  <el-dropdown trigger="click">
    <span class="el-dropdown-link">
      {{ activeApp ? activeApp : apps[0] }}
      <el-icon class="el-icon--right">
        <arrow-down />
      </el-icon>
    </span>
    <template #dropdown>
      <el-dropdown-menu>
        <el-dropdown-item v-for="app in apps " :key="app" @click="pinkApp(app)">{{ app }}</el-dropdown-item>
      </el-dropdown-menu>
    </template>
  </el-dropdown>
</template>
<script lang="ts">
import { defineComponent, reactive, toRefs, ref, watch, onMounted } from 'vue';
import { ArrowDown } from '@element-plus/icons-vue'
interface Test {
  apps: string[],
  pinkApp: any,
  activeApp: string,
}
export default defineComponent({
  components: {
    ArrowDown
  },
  props: {
  },
  setup(props, context) {
    const state = reactive<Test>({
      apps: ['Action', 'Action2', 'Action3', 'Action4', 'Action5'],
      activeApp: '',
      pinkApp(app: any) {
        state.activeApp = app
      }
    })
    return {
      ...toRefs(state)
    };
  }
})
</script>

<style scoped>
.example-showcase .el-dropdown-link {
  cursor: pointer;
  color: var(--el-color-primary);
  display: flex;
  align-items: center;
}
</style>

这里index.ts路径需要跟vite.config.ts中的路径保持一致

image.png
index.ts

export { default as AppNav } from './app-nav/index.vue';

本地调试正常之后,推上到你的私有gitlab仓库,推送到npm库请参考发布npm到公共仓库

3、在其他项目中使用

在你要使用的项目package.json中添加你的包名称:git+对应的仓库地址。你可以定义任何符合需要的名称

 "mtbc": "git+https://gitlab.***.com/**/MtBc.git",

npm i / yarn 在页面中使用即可

image.png

3、代码编写过程中可能出现的问题

1:element-plus Cannot find name 'Language'. 报错 解决方案修改build命令

    # --skipLibCheck  忽略所有的声明文件( `*.d.ts`)的类型检查。
    # --noEmit 不生成输出文件。
   "build": "vue-tsc --noEmit --skipLibCheck && vite build",

2:An import path cannot end with a '.ts' extension. Consider importing '@/index.js' instead. 解决方案:

目前排查是ts/node版本导致的,所以我将node版本选择在v14.17.0,重新构建了一遍项目,解决了问题。

如果有任何关于本文的意见,欢迎在文章下方留言,我会在看到的第一时间回复。