vue-cli3发布一个npm包(踩坑指南)

1,936 阅读5分钟

前奏

最近项目中做了一些工具组件,想着不如打成npm包,沉淀成基础能力,也方便后面其他的项目中使用,因着之前有过相关经验了,信心满满的开搞啦😀。结果dist包顺利的打出来一引用,emmm好像找不到export的组件【尴尬】。从头顺了一遍流程,没有问题,那么。。。偏差应当就在于“脚手架升级了!”,是了没错,现在都是用vue-cli3及以上的版本创建项目了,而上一次打npm好像还是在vue-cli2的时代【我没读书我有罪😭】,遇事不决查文档,于是跑去把官网文档重新看了一遍,终于踩坑成功辽!

库模式打包

在 vue cli 的官方文档中,找到了打包库模式的方法。详细文档可以参考vue-cli 构建目标库方法

#1 入口文件

入口文件可以是一个 .js 或一个 .vue 文件。如果没有指定入口,则会使用 src/App.vue。这里我们新建一个index.js用于直接export组件:

export { default as myLib } from '@/views/myLib'

当使用一个 .vue 文件作为入口时,你的库会直接暴露这个 Vue 组件本身,因为组件始终是默认导出的内容。当你使用一个 .js 或 .ts 文件作为入口时,它可能会包含具名导出,所以库会暴露为一个模块。也就是说你的库必须在 UMD 构建中通过 window.yourLib.default 访问,或在 CommonJS 构建中通过 const myLib = require('mylib').default 访问。如果你没有任何具名导出并希望直接暴露默认导出,你可以在 vue.config.js 中使用以下 webpack 配置:

module.exports = {
  configureWebpack: {
    output: {
      libraryExport: 'default'
    }
  }
}

#2 构建命令

你可以通过下面的命令将一个单独的入口构建为一个库。

vue-cli-service build --target lib --name myLib [entry]

#输出结果

File                     Size                     Gzipped

dist/myLib.umd.min.js    13.28 kb                 8.42 kb
dist/myLib.umd.js        20.95 kb                 10.22 kb
dist/myLib.common.js     20.57 kb                 10.09 kb  
dist/myLib.css           0.33 kb                  0.23 kb

构建一个库会输出:

  • dist/myLib.common.js:一个给打包器用的 CommonJS 包 (不幸的是,webpack 目前还并没有支持 ES modules 输出格式的包)
  • dist/myLib.umd.js:一个直接给浏览器或 AMD loader 使用的 UMD 包
  • dist/myLib.umd.min.js:压缩后的 UMD 构建版本
  • dist/myLib.css:提取出来的 CSS 文件 (可以通过在 vue.config.js 中设置 css: { extract: false } 强制内联)

新建一个index.js作为入口文件 执行构建命令:

vue-cli-service build --target lib --name myLib --dest lib src/index.js

查看过文件内容后,发现 myLib.umd.js 使用了umd 的统一模块定义方法,可以兼容所有的模块化方式,可以使用于任意环境,正是我们所需要的。 ​

#3 vue依赖

在库模式中,Vue 是外置的。这意味着包中不会有 Vue,即便你在代码中导入了 Vue。如果这个库会通过一个打包器使用,它将尝试通过打包器以依赖的方式加载 Vue;否则就会回退到一个全局的 Vue 变量。要避免此行为,可以在build命令中添加--inline-vue标志。

vue-cli-service build --target lib --name myLib --dest lib src/index.js --inline-vue

#4 测试结果

将构建后的lib文件夹复制到项目中进行测试:

<template>
  <div>
    <myLib />
  </div>
</template>
<script>
import { Vue, Component} from 'vue-property-decorator';
import { myLib } from './lib/myLib.umd.min.js';
@Component({
  components: {
    myLib: myLib,
  },
})
export default class extends Vue {

}
</script>
尴尬~布局失控了,疯狂报错了😥

#5 解决问题

问题一:丢失css样式

手动导入构建后的css文件,也可以构建时通过在 vue.config.js 中设置 css: { extract: false } 强制内联

如果你在开发一个库或多项目仓库 (monorepo),请注意导入 CSS 是具有副作用的。请确保在 package.json 中移除 "sideEffects": false,否则 CSS 代码块会在生产环境构建时被 webpack 丢掉。

import 'myLib/lib/myLib.css';
问题二:vuex数据初始化失败

排查后发现没有引入vuex依赖,导致所有store中存储的数据全部为undfined

在构建 Web Components 组件时,入口点不是 main.js ,而是 entry-wc.js 文件,因此,要在 Web Components 组件的目标中使用 vuex ,你需要在 App.vue 中初始化存储 (store):

import store from './store'

// ...

export default {
  store,
  name: 'App',
  // ...
}
开始解决问题

更新App.vue文件并手动挂载store:

<template>
  <div id="app">
    <myLib />
  </div>
</template>
<script>
import 'element-ui/lib/theme-chalk/index.css'
import '@/styles/index.scss'
import '@/styles/element-variables.scss'
import store from './store'
import myLib from './views/myLib'

export default {
  store,
  components: { myLib }
}
</script>

修改构建命令:

vue-cli-service build --target lib --name myLib --dest lib src/App.vue

重新引入测试:

<template>
  <div>
    <myLib />
  </div>
</template>
<script>
import { Vue, Component} from 'vue-property-decorator';
import { myLib } from './lib/myLib.umd.min.js';
import './lib/myLib.css';
@Component({
  components: {
    myLib: myLib,
  },
})
export default class extends Vue {

}
</script>
测试成功!✨

npm包发布

#1 更改入口文件

将 package.json 的 "main": "dist/index.js", 入口文件修改为 "main":"lib/myLib.umd.min.js"

#2 简化构建命令

在 package.json 中添加快捷语法,将 "vue-cli-service build --target lib --name myLib --dest lib src/App.vue" 命令简化为lib。

#npm run lib 构建

"scripts": {
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "dev": "vue-cli-service serve",
    "lib":"vue-cli-service build --target lib --name myLib --dest lib src/App.vue",
  },

#3 更改包权限

设置 package.json 的"private": false

#4 登陆npm账号

  • 如果没有账号先去官网注册npm
  • 在终端输入npm login,然后输入你创建的账号,密码和邮箱登陆

#5 发布

  • npm publish发布--注意每次发布更新要修改package.json中的版本号
  • 在项目中npm install 已发布的包名,导入使用

#6 删除

  • 删除指定版本:npm unpublish 包名@版本号
  • 删除整个包: npm unpublish 包名 --force

npm Organization

和同事一起给team新建了一个组织,现在我们要将这个包发布到组织下便于共同维护:

#1 注册组织

#2 初始化

  • npm init --scope=<org_name>
  • 修改package.json里面的name字段为@org_name/<pkg_name>
  • 公开包发布:npm publish --access public 

#3 验证

  • 登陆官网就可以在组织下看到发布的包的信息啦!

最后

欢迎纠错,看到会及时修改哒!❤

温故而知新,希望我们都可以保持本心,念念不忘,必有回响。