最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 从0到1,搭建一个VUE组件库维护的基本框架

    正文概述 掘金(食堂油条撬地球)   2021-03-26   1012

    一、基础框架的建立

    1、使用vue-cli脚手架创建一个基础的vue3.x+ts项目

    从0到1,搭建一个VUE组件库维护的基本框架

    2、项目目录结构整理

    2.1、修改src目录为examples

    examples目录作为所有示例页面的文件入口目录,同时清理文件夹中由vue-cli默认添加的一些无用的示例文件,

    由于修改了原有的src目录,所以同时需要对vue.config.js进行修改,使得脚手架能够正确的启动项目:

    module.exports = {
      pages: {
        examples: {
          // page 的入口
          entry: 'examples/main.ts',
          // 模板来源
          template: 'public/index.html',
          // 在 dist/index.html 的输出
          filename: 'index.html',
          // 当使用 title 选项时,
          // template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
          title: 'Examples'
        }
      }
    }
    

    2.2、创建packages目录

    packages目录包含组件库中所有的组件以及入口等

    2.3、创建typings目录

    在项目根路径下创建typing目录,并且将examples目录下的shims-vue.d.ts文件移动到当前目录下。

    2.4、修改tsconfig.json文件

    修改tsconfig.json文件中的include字段,将修改后的examples目录和packages目录包含在其中。同时typings目录也需要被添加到该配置中。

    {
        "include": [
            "examples/**/*.ts",
            "examples/**/*.tsx",
            "examples/**/*.vue",
            "packages/**/*.ts",
            "packages/**/*.tsx",
            "packages/**/*.vue",
            "typings/**/*.ts"
        ]
    }
    

    2.5、添加一些风格规范和样式规范的配置文件

    这个地方根据团队编码风格或个人编码风格设置,不作过多的赘述。

    小结:

    修改后整个项目目录结构大致如下:

    .
    ├── examples
    │   ├── App.vue
    │   └── main.ts
    ├── packages
    │   ├── index.ts
    ├── public
    │   ├── favicon.ico
    │   └── index.html
    ├── typings
    │   └── shims-vue.d.ts
    ├── README.md 
    ├── babel.config.js
    ├── tsconfig.json
    ├── package.json
    └── vue.config.js
    

    二、组件的创建

    1、组件A

    在packages目录下创建目录comp-a并且在该文件夹下创建src/comp-a.vue文件和index.ts文件

    comp-a.vue文件代码如下

    <template>
      <div style="width: 200px; background-color: red">comp-a</div>
    </template>
    
    <script lang="ts">
    import { defineComponent } from 'vue'
    
    export default defineComponent({
      name: 'CompA'
    })
    </script>
    
    

    index.ts作为组件的入口,目的是为了导出组件并且添加install方法

    import { App } from 'vue'
    
    import CompA from './src/comp-a.vue'
    
    // 为组件添加注册方法
    CompA.install = (app: App): void => {
      app.component(CompA.name, CompA)
    }
    
    export default CompA
    
    

    2、组件B

    组件B的创建与组件A同理,不做过多赘述,只展示代码

    comp-b.vue

    <template>
      <div style="width: 200px; background-color: green">comp-b</div>
    </template>
    
    <script lang="ts">
    import { defineComponent } from 'vue'
    
    export default defineComponent({
      name: 'CompB'
    })
    </script>
    
    

    index.ts

    import { App } from 'vue'
    
    import CompB from './src/comp-b.vue'
    
    // 为组件添加注册方法
    CompB.install = (app: App): void => {
      app.component(CompB.name, CompB)
    }
    
    export default CompB
    
    

    3、组件入口

    在packages/index.ts文件中编写代码,作为整个组件库的导出统一导出目录

    import { App } from 'vue'
    
    import CompA from './comp-a'
    import CompB from './comp-b'
    
    const components = [CompA, CompB]
    
    // 注册所有的组件
    const install = function (app: App): void {
      components.forEach((component) => {
        app.component(component.name, component)
      })
    }
    
    // 导出注册方法
    export default {
      install
    }
    
    // 导出 单个组件
    export { CompA, CompB }
    
    

    三、组件的使用

    1、全局使用

    1.1、在examples/main.ts中导入组件,通过app.use注册所有组件

    import { createApp } from 'vue'
    import App from './App.vue'
    
    import Components from '../packages'
    
    const examples = createApp(App)
    examples.use(Components)
    examples.mount('#app')
    
    export default examples
    
    

    1.2、在页面中使用:

    <template>
      <div id="#app">
        <comp-a />
        <comp-b />
      </div>
    </template>
    
    <script lang="ts">
    import { defineComponent } from 'vue'
    export default defineComponent({
      name: 'App'
    })
    </script>
    
    

    1.3、效果:

    从0到1,搭建一个VUE组件库维护的基本框架

    2、在局部组件中引用

    2.1、删除main.ts中对全局的引用

    2.2、在页面中导入组件并且注册

    <template>
      <div id="#app">
        <comp-a />
        <comp-b />
      </div>
    </template>
    
    <script lang="ts">
    import { defineComponent } from 'vue'
    
    import { CompA, CompB } from '../packages'
    
    export default defineComponent({
      name: 'App',
      components: { CompA, CompB }
    })
    </script>
    
    

    2.3、效果:

    从0到1,搭建一个VUE组件库维护的基本框架

    四、组件库打包

    1、vue-cli打包

    vue-cli工具提供了将vue打包为lib库的命令详细信息:cli.vuejs.org/zh/guide/bu…

    在package.json的script字段下增加一条命令:

    {
      "scripts": {
        "build:lib": "vue-cli-service build --target lib ./packages/index.ts"
      }
    }
    

    通过命令行执行

    yarn build:lib
    

    npm run build:lib
    

    即可打包为库文件

    从0到1,搭建一个VUE组件库维护的基本框架

    从0到1,搭建一个VUE组件库维护的基本框架

    打包之后会生成cjs、umd格式的库,demo.html文件描述了该如何在html界面中使用这个库。

    2、rollup打包

    vue-cli打包之后仅仅生成了cjs和umd格式的库,对于一个组件库而言,可能还需要使用esm格式的库,如果在typescript项目中使用,或许还需要.d.ts类型声明文件。vue-cli打包并没有为我们提供这些支持,所以需要使用到rollup,使得我们的库能够得到更好的支持

    2.1、安装rollup依赖

    • rollup 打包工具
    • rollup-plugin-terser 代码压缩工具
    • plugin-node-resolve 第三方工具模块定位插件
    • rollup-plugin-typescript 处理typescript文件
    • rollup-plugin-vue vue处理插件
    • rollup-plugin-css-only 处理样式(本文中未用到)
    npm install -D rollup rollup-plugin-terser @rollup/plugin-node-resolve rollup-plugin-typescript2 rollup-plugin-vue rollup-plugin-css-only
    

    yarn add -D rollup rollup-plugin-terser @rollup/plugin-node-resolve rollup-plugin-typescript2 rollup-plugin-vue rollup-plugin-css-only
    

    2.2、ESM-bundle

    • 在项目跟目录下创建build文件夹,用于存放打包需要的脚本文件
    • 在build文件夹下创建rollup.config.bundle.js,使用rollup打包出具有所有组件的esm模块,以及各个组件的类型声明文件

    rollup.config.bundle.js配置文件:

    /* eslint-disable */
    import path from 'path'
    import pkg from '../package.json'
    import { terser } from 'rollup-plugin-terser'
    import { nodeResolve } from '@rollup/plugin-node-resolve'
    import vue from 'rollup-plugin-vue'
    import typescript from 'rollup-plugin-typescript2'
    
    const deps = Object.keys(pkg.dependencies || {})
    
    export default [
      {
        input: path.resolve(__dirname, '../packages/index.ts'), //入口
        output: {
          format: 'es',
          file: 'lib/index.esm.js'
        },
        plugins: [
          terser(),
          nodeResolve(),
          vue({
            target: 'browser', // 服务端渲染使用 'node'
            css: false,
            exposeFilename: false
          }),
          typescript({
            tsconfigOverride: {
              compilerOptions: {
                declaration: true
              },
              include: ['packages/**/*', 'typings/vue-shim.d.ts'],
              exclude: ['node_modules']
            },
            abortOnError: false
          })
        ], // 插件
        external(id) {
          return /^vue/.test(id) || deps.some((k) => new RegExp('^' + k).test(id))
        }
      }
    ]
    
    
    • 在package.json文件中添加脚本,用于打包项目
    {
      "scripts": {
        "build:esm-bundle": "rollup --config ./build/rollup.config.bundle.js"
      }
    }
    

    2.3、UMD

    • UMD格式脚本与esm格式基本相同,只不过需要指定output.name属性
    /* eslint-disable */
    import path from 'path'
    import pkg from '../package.json'
    import { terser } from 'rollup-plugin-terser'
    import { nodeResolve } from '@rollup/plugin-node-resolve'
    import vue from 'rollup-plugin-vue'
    import typescript from 'rollup-plugin-typescript2'
    
    const deps = Object.keys(pkg.dependencies || {})
    
    export default [
      {
        input: path.resolve(__dirname, '../packages/index.ts'), //入口
        output: {
          format: 'umd', // umd格式
          file: 'lib/index.umd.js', // 输出文件
          name: pkg.name // 指定name
        },
        plugins: [
          terser(),
          nodeResolve(),
          vue({
            target: 'browser', // 服务端渲染使用 'node'
            css: false,
            exposeFilename: false
          }),
          typescript({
            tsconfigOverride: {
              compilerOptions: {
                declaration: true
              },
              include: ['packages/**/*', 'typings/vue-shim.d.ts'],
              exclude: ['node_modules']
            },
            abortOnError: false
          })
        ], // 插件
        external(id) {
          return /^vue/.test(id) || deps.some((k) => new RegExp('^' + k).test(id))
        }
      }
    ]
    
    

    五、发布

    1、npm账号

    1.1、注册账号,注册地址: www.npmjs.com/signup (已有账号)请忽略这一步

    1.2、登录,通过命令行执行登录

    npm login
    

    登录成功检查:

    npm whoami
    

    2、修改package.json

    2.1、设置private字段为false, 为true时 npm拒绝发布

    {
        "private": false
    }
    

    2.2、设置入口以及类型声明

    {
        "main": "lib/index.umd.js",
        "module": "lib/index.esm.js",
        "typings": "lib/index.d.ts"
    }
    

    3、发布

    3.1、设置版本号

    修改package.json中的version字段,保证该字段与已经发布的字段不重复

    3.2、发布

    执行命令:(发布前确保当前分支已经时一个干净的分支,即不含有未提交的文件)

    npm publish
    

    总结

    至此,从0到1搭建一个组件库的基本框架便已经完成,其中还有诸多细节需要处理,如:

    • css、scss等样式文件的处理
    • 单个组件的分离
    • ...

    这一片文章谨献给想要维护一个自己的组件库,但是无从下手的初学者,同时更多深层次的内容仍需要继续探索。处于工作中的各位,将来势必会走到维护公司内部的业务组件库的地步,看过这篇文章,不至于真正需要用到的时候手足无措。更多细节敬请批评指正。

    最后附上整个过程中所涉及到的代码:

    GitHub: gitee.com/AloneH/vue-…

    Gitee: gitee.com/AloneH/vue-…


    起源地下载网 » 从0到1,搭建一个VUE组件库维护的基本框架

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元