Vue3.0曾经公布了很长一段时间了,最近也在想着怎么去做工程化的货色,于是就想本人弄一个组件库捎带深刻学习Vue3.0,于是便有了明天的这篇文章。

Git地址:https://github.com/ZhQuella/AzUIFront

技术栈

包管理工具:

yarn

开发模块:

Vite
Vue 3.0

打包工具:

Gulp
Rollup

单元测试:

Jest

语法工具:

ESLint

语言:

TypeScript

为什么要应用Yarn

看到包管理工具应用的事yarn或者很多小伙伴不太能了解为什么要应用yarn,说到这里可能就须要理解一下前端的工程化的概念了,什么是前端的工程化?工程化别离为模块化组件化规范化自动化

模块化

模块化是指将一个文件拆分成多个相互依赖的文件,最初进行对立的打包和加载,这样可能很好的保障高效的多人合作。
JavaScript模块化:CommonJSAMDCMD以及ES6 Module
CSS模块化:SassLessStylusBEMCssModules等。其中预处理器和 BEM 都会有的一个问题就是款式笼罩。
资源模块化:任何资源都能以模块的模式进行加载,目前大部分我的项目中的文件、CSS、图片等都能间接通过 JS 做对立的依赖关系解决

组件化

不同于模块化,模块化是对文件、对代码和资源拆分,而组件化则是对UI层面的拆分。
组件化并不是前端所特有的,一些其余的语言或者桌面程序等,都具备组件化的先例。确切的说,只有有UI层的展现,就必然有能够组件化的中央。简略来说,组件就是将一段UI款式和其对应的性能作为独立的整体去对待,无论这个整体放在哪里去应用,它都具备一样的性能和款式,从而实现复用,这种整体化的细想就是组件化。不难看出,组件化设计就是为了减少复用性,灵活性,进步零碎设计,从而进步开发效率。
组件零碎是一个重要概念,因为它是一种形象,容许咱们应用小型、独立和通常可复用的组件构建大型利用。咱们会须要对页面进行拆分,将其拆分成一个一个的整机,而后别离去实现这一个个整机,最初再进行组装。
组件化的形象设计是很重要的,不仅减少了复用性进步了工作效率,从某种程度上来说也反馈了程序员对业务和产品设计的了解,一旦有问题或者须要性能扩大时,你就会发现之前的设计是如许的有意义。

规范化

规范化指的是咱们在工程开发初期以及开发期间制订的系列标准,其中又蕴含了:

  1. 我的项目目录构造
  2. 对于编码这块的束缚,个别咱们都会采纳一些强制措施,比方ESLintStyleLint等。
  3. 联调标准
  4. 文件命名标准
  5. 款式治理标准:目前风行的款式治理有BEMSassLessStylusCSS Modules等形式
  6. 工作流:其中蕴含分支命名标准、代码合并标准等
  7. 定期代码审查
自动化

从最早先的gruntgulp等,再到目前的webpackparcel。这些自动化工具在自动化合并、构建、打包都能为咱们节俭很多工作。而这些只是前端自动化其中的一部分,前端自动化还蕴含了继续集成、自动化测试等方方面面。


想必大家对与工程化也有了肯定的理解,那么会过头来持续说为什么要应用yarn,下面说到了模块化如果咱们想一下,组件的开发与组件文档的展现和组件库的自身是存在所有关联的,然而关联性并没有那么大,能够应用yarn的工作空间来分隔他们使他们本事作为一个独立的个体而存在,yarn工作流与npm相似都是应用package.json文件,yarn会重组node_modules文件,且不会与npm抵触。yarn的工作空间可能更好的帮忙咱们治理多个我的项目,能够在多个子项目中应用独立的package.json治理我的项目依赖。yarn会依据就依赖关系帮忙你剖析所有子项目的共用依赖,保障所有的我的项目专用的依赖只会被下载和装置一次。

初始化我的项目

初始化创立我的项目:

mkdir AzUiFontcd AzUiFontyarn init -y

创立.gitignore

node_modulescoveragedisteslibpackage-lock.json

批改package.json

{  "name": "az-ui-font",  "private": true,  "version": "0.0.1",  "main": "index.js",  "license": "MIT"}

搭建初始目录构造:

├─packages          //  我的项目总目录│  ├─azui               //  组件库目录│  ├─docs               //  展现文档目录│  └─play               //  组件库开发展现目录├─script            //  运行脚本├─.gitignore       ├─index.html       ├─package.json     ├─README.md        └─tsconfig.json
<!DOCTYPE html><html lang="en">  <head>    <meta charset="UTF-8" />    <link rel="icon" href="/favicon.ico" />    <meta name="viewport" content="width=device-width, initial-scale=1.0" />    <title>AzUIFront</title>  </head>  <body>    <div id="app"></div>    <script type="module" src="/src/main.ts"></script>  </body></html>

tsconfig.json

{  "compilerOptions": {    "rootDir": ".",    "sourceMap": false,    "target": "esnext",    "module": "esnext",    "jsx": "preserve",    "moduleResolution": "node",    "strictNullChecks": true,    "noUnusedLocals": true,    "resolveJsonModule": true,    "esModuleInterop": true,    "experimentalDecorators": true,    "allowSyntheticDefaultImports": true,    "baseUrl": ".",    "lib": ["esnext", "dom"],    "types": ["jest", "node"]  }}

代码标准束缚

这里应用eslint对代码标准进行束缚,装置如下工具:

yarn add eslint -D -Wyarn add eslint-formatter-pretty -D -Wyarn add eslint-plugin-json -D -Wyarn add eslint-plugin-prettier -D -Wyarn add eslint-plugin-vue -D -Wyarn add @vue/eslint-config-prettier -D -Wyarn add babel-eslint -D -Wyarn add prettier -D -W

增加.eslintrc.js

module.exports = {    "root": true,    "env": {        "browser": true,        "es2020": true,        "node": true,        "jest": true    },    "globals": {        "ga": true,        "chrome": true,        "__DEV__": true    },    "extends": [        "eslint:recommended",        "plugin:@typescript-eslint/recommended",        'plugin:json/recommended',        'plugin:vue/vue3-essential',        '@vue/prettier'    ],    "parserOptions": {        "ecmaVersion": 12,        "parser": "@typescript-eslint/parser",        "sourceType": "module"    },    "plugins": [        "vue",        "@typescript-eslint"    ],    "rules": {    }};

增加.eslintignore

*.sh*.md*.ico*.css*.md*.scss*.woff*.ttf*/*/shims.d.ts */*/index.html*/*/yarn-error.logpackages/azui/rollup-plugin-vue/index.d.tsnode_moduleslibcoveragedist

package.json增加如下命令:

package.json

{  "scripts": {    "lint": "eslint --no-error-on-unmatched-pattern --ext .vue --ext .ts --ext .tsx packages/**/ --fix"  },  "devDependencies": {    "eslint": "^7.24.0",    "eslint-config-prettier": "^8.3.0",    "eslint-formatter-pretty": "^4.0.0",    "eslint-plugin-jest": "^24.3.5",    "eslint-plugin-json": "^2.1.2",    "eslint-plugin-prettier": "^3.4.0",    "prettier": "^2.2.1"  }}

代码束缚局部曾经解决实现,接下来解决组件局部

组件库局部

执行命令

cd .\packages\azui\yarn init -y

package.json

{  "name": "azui",  "version": "0.0.1",  "private": true,  "license": "MIT"}

目录构造如下

├─rollup-plugin-vue└─src    ├─packages    │  └─Button    │      ├─Button.vue    │      ├─index.ts    │      └─__tests__    └─styles

集成Babel到我的项目中,须要装置如下依赖:

yarn add babel -D -Wyarn add babel-plugin-syntax-dynamic-import -D -Wyarn add babel-plugin-syntax-jsx -D -Wyarn add babel-preset-env -D -Wyarn add @babel/plugin-proposal-optional-chaining -D -Wyarn add @babel/preset-env -D -Wyarn add @vue/babel-plugin-jsx -D -W

增加.babelrc

{  "presets": [["@babel/preset-env", { "targets": { "node": "current" } }]],  "plugins": [    "syntax-dynamic-import",    ["@vue/babel-plugin-jsx"],    "@babel/plugin-proposal-optional-chaining",    "@babel/plugin-proposal-nullish-coalescing-operator"  ],  "env": {    "utils": {      "presets": [        [          "env",          {            "loose": true,            "modules": "commonjs",            "targets": {              "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]            }          }        ]      ],      "plugins": [        [          "module-resolver",          {            "root": ["azui"],            "alias": {              "azui/src": "az-ui/lib"            }          }        ]      ]    },    "test": {      "plugins": ["istanbul"],      "presets": [["env", { "targets": { "node": "current" } }]]    },    "esm": {      "presets": [["@babel/preset-env", { "modules": false }]]    }  }}

集成自动化测试(单元测试)

yarn add jest -D -Wyarn add vue-jest@5.0.0-alpha.5 -D -Wyarn add babel-jest    -D -W                        yarn add @vue/compiler-sfc@3.0.2 -D -Wyarn add @vue/test-utils@next -D -Wyarn add typescript -D -W

增加jest.config.js

module.exports = {  testEnvironment: "jsdom", // 默认JSdom  roots: ["<rootDir>/src/packages"], //  transform: {    "^.+\\.vue$": "vue-jest", // vue单文件    "^.+\\js$": "babel-jest", // esm最新语法 import  },  moduleFileExtensions: ["vue", "js", "json", "jsx", "ts", "tsx", "node"],  testMatch: ["**/__tests__/**/*.spec.js"],  // 别名  moduleNameMapper: {    "^azui(.*)$": "<rootDir>$1",    "^main(.*)$": "<rootDir>/src$1",  },};

package.json

{  "scripts": {    "test": "jest --runInBand"  }}

款式打包,增加如下依赖:

yarn add gulp -D -Wyarn add gulp-autoprefixer -D -Wyarn add gulp-sass -D -Wyarn add gulp-cssmin -D -Wyarn add cp-cli -D -Wyarn add tslib -D -W

package.json

{  "scripts": {    "build:theme": "gulp build --gulpfile gulpfile.js"  }}

应用Rollup打包组件,装置如下依赖:

yarn add rollup -D -Wyarn add rollup-plugin-peer-deps-external -D -Wyarn add rollup-plugin-scss -D -Wyarn add rollup-plugin-terser -D -Wyarn add rollup-plugin-vue -D -Wyarn add @rollup/plugin-node-resolve -D -Wyarn add @rollup/plugin-commonjs -D -Wyarn add @rollup/plugin-json -D -Wyarn add @rollup/plugin-replace -D -Wyarn add @rollup/plugin-babel -D -Wyarn add rollup-plugin-vue -D -Wyarn add rollup-plugin-typescript2 -D -W

增加rollup.config.js

import path from "path";import scss from "rollup-plugin-scss";import peerDepsExternal from "rollup-plugin-peer-deps-external";import resolve from "@rollup/plugin-node-resolve";import commonjs from "@rollup/plugin-commonjs";import json from "@rollup/plugin-json";import replace from "@rollup/plugin-replace";import babel from "@rollup/plugin-babel";import { terser } from "rollup-plugin-terser";import ts from "rollup-plugin-typescript2";import pkg from "./package.json";const vuePlugin = require("./rollup-plugin-vue/index");const getPath = (_path) => path.resolve(__dirname, _path);const name = "AzUi";const createBanner = () => {  return `/*!  * ${pkg.name} v${pkg.version}  * (c) ${new Date().getFullYear()} Aaron  * @license MIT  */`;};const extensions = [".js", ".ts", ".tsx", ".scss"];const tsPlugin = ts({  tsconfig: getPath("./tsconfig.json"),  extensions,});const createBaseConfig = () => {  return {    input: "src/index.ts",    external: ["vue"],    plugins: [      peerDepsExternal(),      babel(),      resolve({        extensions,      }),      commonjs(),      json(),      tsPlugin,      vuePlugin({        css: true      }),      scss({        output: process.env.NODE_ENV === 'development'?                  './dist/lib/index.css':                  false,        watch: ["./src/styles"]      })    ],    output: {      sourcemap: false,      banner: createBanner(),      externalLiveBindings: false,      globals: {        vue: "Vue"      }    }  };};function mergeConfig(baseConfig, configB) {  const config = Object.assign({}, baseConfig);  // plugin  if (configB.plugins) {    baseConfig.plugins.push(...configB.plugins);  }  // output  config.output = Object.assign({}, baseConfig.output, configB.output);  return config;}function createFileName(formatName) {  return `dist/az-ui.${formatName}.js`;}// es-bundleconst esBundleConfig = {  plugins: [    replace({      __DEV__: `(process.env.NODE_ENV !== 'production')`,    }),  ],  output: {    file: createFileName("esm-bundler"),    format: "es",  },};// es-browserconst esBrowserConfig = {  plugins: [    replace({      __DEV__: true,    }),  ],  output: {    file: createFileName("esm-browser"),    format: "es",  },};// es-browser.prodconst esBrowserProdConfig = {  plugins: [    terser(),    replace({      __DEV__: false,    }),  ],  output: {    file: createFileName("esm-browser.prod"),    format: "es",  },};// cjsconst cjsConfig = {  plugins: [    replace({      __DEV__: true,    }),  ],  output: {    file: createFileName("cjs"),    format: "cjs",  },};// cjs.prodconst cjsProdConfig = {  plugins: [    terser(),    replace({      __DEV__: false,    }),  ],  output: {    file: createFileName("cjs.prod"),    format: "cjs",  },};// globalconst globalConfig = {  plugins: [    replace({      __DEV__: true,      "process.env.NODE_ENV": true,    }),  ],  output: {    file: createFileName("global"),    format: "iife",    name  },};// global.prodconst globalProdConfig = {  plugins: [    terser(),    replace({      __DEV__: false,    }),  ],  output: {    file: createFileName("global.prod"),    format: "iife",    name  },};const formatConfigs = [  esBundleConfig,  esBrowserProdConfig,  esBrowserConfig,  cjsConfig,  cjsProdConfig,  globalConfig,  globalProdConfig,];function createPackageConfigs() {  return formatConfigs.map((formatConfig) => {    return mergeConfig(createBaseConfig(), formatConfig);  });}export default createPackageConfigs();

package.json

{  "scripts": {    "build": "rollup -c"  }}

组件库局部曾经实现,接下来配置文档局部:

文档局部

执行命令

cd ../..cd .\packages\docs\

创立目录构造:

├─public├─scripts└─src    ├─assets    ├─components    └─__docs__

装置如下依赖:

yarn add @vitejs/plugin-vue -D -wyarn add markdown-it-containe -D -wyarn add node-sass -D -wyarn add sass -D -wyarn add sass-loader -D -wyarn add vite -D -wyarn add vite-plugin-vuedoc -D -wyarn add vue@next -S -Wyarn add vue-router@4 -S -W

package.json

{  "name": "@azui/docs",  "version": "0.0.1",  "private": true,  "scripts": {    "dev": "vite",    "build": "vite build",    "test": "tsrv test"  },  "dependencies": {    "azui": "0.0.1",    "vue": "^3.0.7",    "vue-router": "^4.0.4"  },  "devDependencies": {    "@vitejs/plugin-vue": "^1.1.5",    "markdown-it-container": "^3.0.0",    "node-sass": "^5.0.0",    "sass": "^1.32.11",    "sass-loader": "^11.0.1",    "vite": "^2.0.5",    "vite-plugin-vuedoc": "^3.1.2"  }}

增加vite.config.ts

import { defineConfig } from "vite";import { createPlugin, vueDocFiles } from "vite-plugin-vuedoc";import markdownItContainer from "markdown-it-container";import vue from "@vitejs/plugin-vue";import vitePluginSyncmd from "./scripts/vitePluginSyncmd";const containers = ["success", "warning", "info", "error"].map((type) => {  return [    markdownItContainer,    type,    {      validate: function (params: string) {        const str = params.trim();        if (str === type || str.startsWith(`${type} `)) {          return [str, str === type ? "" : str.substr(type.length + 1)];        }        return null;      },      render: function (tokens: any[], idx: number) {        const str = tokens[idx].info.trim();        const m = [str, str === type ? "" : str.substr(type.length + 1)];        if (tokens[idx].nesting === 1) {          // opening tag          return `<p>${type}--${m[1]}`;        } else {          // closing tag          return "</p>";        }      },    },  ];});export default defineConfig({  server: {    port: 3000,  },  assetsInclude: ["src/assets"],  optimizeDeps: {    exclude: ["azui"],  },  plugins: [    vitePluginSyncmd(),    createPlugin({      markdownIt: {        plugins: [...containers],      },      highlight: {        theme: "one-dark",      },    }),    vue({      include: [...vueDocFiles],    }),  ],});

tsconfig.json

{  "compilerOptions": {    "target": "esnext",    "module": "esnext",    "moduleResolution": "node",    "strict": true,    "jsx": "preserve",    "sourceMap": true,    "lib": ["esnext", "dom"],    "types": ["vite/client"],    "baseUrl": "."  },  "include": ["./shims.d.ts", "src/**/*"],  "exclude": ["node_modules", "dist"]}

shims.d.ts

declare module '*.vue' {  import type { DefineComponent } from 'vue'  const component: DefineComponent<{}, {}, any>  export default component}declare module '*.md' {  import { DefineComponent } from 'vue'  const component: DefineComponent<{}, {}, any>  export default component}

index.html

<!DOCTYPE html><html lang="en">  <head>    <meta charset="UTF-8" />    <link rel="icon" href="/src/assets/icon.png" />    <meta name="viewport" content="width=device-width, initial-scale=1.0" />    <title>Vite App</title>  </head>  <body>    <div id="app"></div>    <script type="module" src="/src/main.ts"></script>  </body></html>

scripts/vitePluginSyncmd.ts

import { Plugin } from "vite";import chokidar from "chokidar";import path from "path";import fs from "fs-extra";function docFileName(path: string) {  const ret = path.split("/__docs__/");  if (ret.length === 2) {    return ret;  }  return [null, null];}function syncdocServer({ root }) {  const componentsDir = path.join(root, "../elenext/src/components");  const docsPath = (file) => path.join(root, "src/__docs__", file);  const watcher = chokidar.watch(`${componentsDir}/**/__docs__/*.md`);  watcher    .on("add", async (path) => {      const [, file] = docFileName(path);      if (file) {        try {          await fs.copy(path, docsPath(file));        } catch (err) {          console.error(err);        }      }    })    .on("change", async (path) => {      const [, file] = docFileName(path);      if (file) {        try {          await fs.copy(path, docsPath(file));        } catch (err) {          console.error(err);        }      }    })    .on("unlink", async (path) => {      const [, file] = docFileName(path);      if (file) {        try {          await fs.remove(docsPath(file));        } catch (err) {          console.error(err);        }      }    });}function vitePluginSyncmd(): Plugin {  return {    name: "Syncmd",    configureServer(server) {      syncdocServer({ root: server.config.root });    },  };}export default vitePluginSyncmd;

src/__docs__/Button.zh-CN.md

---title: ButtonwrapperClass: md-button---# Button 按钮罕用的操作按钮## 按钮色彩应用`color`属性来定义 Button 的色彩`color`: 'primary' | 'success' | 'info' | 'warning' | 'danger'## Button Props| 参数        | 阐明           | 类型                                                             | 默认值 || ----------- | -------------- | ---------------------------------------------------------------- | ------ || color       | 类型           | 'primary' / 'success' / 'warning' / 'danger' / 'info' / 'string' | -      |

components/AppLayout.vue

<template>  <div class="demo-layout">    <div>      <div class="demo-header">        <div class="layout-center">          <div align="middle">            <div :flex="1">              <Logo />            </div>            <div>              <div mode="horizontal">                <div>                  <input v-model="data.primaryColor" />                </div>                <div>                  <a href="https://github.com/JasKang/elenext" target="__blank">GitHub</a>                </div>              </div>            </div>          </div>        </div>      </div>      <div>        <div class="layout-center">          <div align="top" :wrap="false">            <div :flex="'200px'">              <div style="padding-top: 40px">                <div mode="vertical" :current-path="route.path">                  <template v-for="menu in menus" :key="menu.title">                    <div :title="menu.title">                      <div v-for="item in menu.items" :key="item" :path="`/${item.name.toLowerCase()}`">                        {{ `${item.name}-Aaron` }}                      </div>                    </div>                  </template>                </div>              </div>            </div>            <div :flex="1">              <div class="site-content">                <router-view />              </div>            </div>          </div>        </div>      </div>    </div>  </div></template><script lang="ts">import { defineComponent, reactive } from 'vue'import { useRoute } from 'vue-router'import menus from '../menus'export default defineComponent({  name: 'AppLayout',  setup() {    const route = useRoute()    const data = reactive({      primaryColor: '#409eff',    })    return {      route,      menus,      data,    }  },})</script><style lang="scss">.demo-layout {  height: 100vh;}.layout-center {  max-width: 1200px;  width: 100vw;  margin: 0 auto;}.site-content {  width: 100%;  padding: 20px;  // max-width: 900px;  margin: 0 auto;}.demo-aside {  border-right: solid 1px #e6e6e6;}.demo-header {  border-bottom: solid 1px #e6e6e6;  // box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);}</style>

App.vue

<template>  <div class="box">111</div>  <router-view /></template><script lang="ts">import { defineComponent } from 'vue'export default defineComponent({  name: 'App',  components: {}})</script>

main.ts

import 'vite-plugin-vuedoc/style.css';import { createApp } from 'vue';import AzUI from 'azui';import 'azui/dist/lib/index.css';import { router } from './router';import App from './App.vue';const app = createApp(App);app.use(AzUI);app.use(router);app.mount('#app');

menus.ts

import { Component, defineAsyncComponent } from 'vue'import Button from './__docs__/Button.zh-CN.md'type MenuItemType = {  name: string  component: (() => Promise<Component>) | Component}type MenuType = {  title: string  items: MenuItemType[]}export default [  {    title: 'Basic',    items: [      { name: 'Button', component: Button },    ]  }] as MenuType[]

router.ts

import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'import AppLayout from './components/AppLayout.vue'import menus from './menus'export const router = createRouter({  history: createWebHistory(),  strict: true,  routes: [    { path: '/'},    {      path: '/component',      name: 'Layout',      component: AppLayout,      redirect: '/button',      children: menus.reduce((prev, item) => {        const _routes = item.items.map(i => {          console.log(i.component)          return {            path: `/${i.name.toLowerCase()}`,            name: i.name,            component: i.component,          }        })        prev.push(..._routes)        return prev      }, [] as RouteRecordRaw[]),    },  ],})

文档局部实现,接下来解决组件开发局部,其实组件开发局部能够和文档局部放在一起,应用不同的路由,然而两者的性能不雷同,所以独自配置了一个子项目。

开发局部

执行如下命令:

cd ../..cd .\packages\play\

目录构造:

├─public├─scripts├─index.html└─src    ├─App.vue    └─main.ts

package.json,相干依赖自行装置

{  "name": "@azui/play",  "version": "0.0.1",  "private": true,  "scripts": {    "dev": "vite",    "build": "vite build",    "test": "tsrv test"  },  "dependencies": {    "azui": "0.0.1",    "vue": "^3.0.7"  },  "devDependencies": {    "@vitejs/plugin-vue": "^1.1.5",    "node-sass": "^5.0.0",    "sass": "^1.32.11",    "sass-loader": "^11.0.1",    "vite": "^2.0.5"  }}

shims.d.ts

declare module '*.vue' {  import type { DefineComponent } from 'vue'  const component: DefineComponent<{}, {}, any>  export default component}declare module '*.md' {  import { DefineComponent } from 'vue'  const component: DefineComponent<{}, {}, any>  export default component}

tsconfig.json

{  "compilerOptions": {    "target": "esnext",    "module": "esnext",    "moduleResolution": "node",    "strict": true,    "jsx": "preserve",    "sourceMap": true,    "lib": ["esnext", "dom"],    "types": ["vite/client"],    "baseUrl": "."  },  "include": ["./shims.d.ts", "src/**/*"],  "exclude": ["node_modules", "dist"]}

vite.config.ts

import { defineConfig } from "vite";import vue from "@vitejs/plugin-vue";export default defineConfig({  server: {    port: 8080,  },  optimizeDeps: {    exclude: ["azui"],  },  plugins: [    vue()  ]});

这样的话组件开发局部也就配置好了,当初就是启动我的项目的时候,返回到根目录,在根目录的package.json中增加scripts:

我的项目启动

root package.json

{  "scripts": {    "dev": "yarn workspace azui run dev",    "start": "yarn workspace @azui/docs run dev",    "play": "yarn workspace @azui/play run dev",    "test": "yarn workspace azui run test",    "lint": "eslint --no-error-on-unmatched-pattern --ext .vue --ext .ts --ext .tsx packages/**/ --fix"  }}

须要留神的是,肯定要先运行yarn dev依据dev来运行打包出开发环境所须要的组件,之后再运行start或者play,记的有两个命令行窗口运行哦,如果间接运行startplay会抛出谬误:

[plugin:vite:import-analysis] Failed to resolve entry for package "azui". The package may have incorrect main/module/exports specified in its package.json.

这是因为在我的项目中无奈找到所依赖的组件库~这一点须要非凡留神。

结束语

要搭建一个绝对欠缺的组件库,都是须要通过一系列我的项目的积淀的。目前而言,组件库的开发流程上仍然会存在一些问题,比方版本治理、降级回退等。工夫是最好的老师,置信在前面的迭代中,咱们仍然可能放弃初心与激情,积极探索与发现,构建出更加欠缺的前端工程体系。