Vue3.0 has been released for a long time, and recently I was thinking about how to do engineering things, so I wanted to get a component library to help me learn more about Vue3.0, hence this article.

Git address: github.com/ZhQuella/Az…

Technology stack

Package management tools:

yarn

Development module:

Vite

Vue 3.0

Packaging tools:

Gulp

Rollup

Unit tests:

Jest

Syntax tools:

ESLint

Language:

TypeScript

Why use Yarn

See the package management tool yarn, many people may not understand why to use yarn, so you need to understand the concept of front-end engineering. What is front-end engineering? Engineering is modularization, componentization, standardization and automation respectively.

modular

Modularity refers to the process of splitting a file into multiple interdependent files and then packaging and loading them uniformly. This ensures efficient collaboration between multiple people. JavaScript modularity: CommonJS, AMD, CMD, and ES6 Modules. Modular CSS: Sass, Less, Stylus, BEM, CssModules, etc. One of the problems that preprocessors and BEM have is style overwriting. Resource modularization: any resource can be loaded in the form of modules. At present, most of the files, CSS, pictures and so on in the project can be directly processed by JS in a unified dependency relationship

componentization

Unlike modularization, which involves splitting files, code, and resources, componentization is splitting the UI level. Componentization is not unique to the front end. There are precedents for componentization in other languages, desktop applications, etc. To be sure, as long as there is a UI layer presentation, there must be a place for componentization. To put it simply, a component is to treat a section of UI style and its corresponding functions as an independent whole. No matter where the whole is used, it has the same function and style, so as to realize reuse. This kind of integrated thinking is componentization. It is not difficult to see that componentized design is to increase the reuse, flexibility, improve system design, thus improving development efficiency. Component systems are an important concept because they are an abstraction that allows us to build large applications from small, independent, and often reusable components. We will need to take the page apart, break it into parts, implement each part separately, and then assemble it. Componentized abstract design is important, not only to increase reusability and productivity, but also to some extent to reflect the programmer’s understanding of business and product design. When there is a problem or need to extend functionality, you will find that the previous design makes sense.

The canonical

Standardization refers to a series of specifications developed by us in the initial stage and during the development of the project, including:

  1. Project directory structure
  2. For coding constraints, we generally adopt some enforcement measures, such asESLint,StyleLintAnd so on.
  3. Alignment specification
  4. File naming conventions
  5. Style management specifications: Currently popular style management areBEM,Sass,Less,Stylus,CSS ModulesMethods such as
  6. Workflow: includes branch naming conventions, code merging conventions, and so on
  7. Periodic code review

automation

From the earliest grunt, gulp, etc., to the current Webpack, parcel. These automation tools can save us a lot of work in automating merges, builds, and packaging. These are just part of front-end automation, which also includes continuous integration, automated testing and so on.


I think you have a little bit of knowledge about engineering, so I’ll go back and talk about why WE use YARN. It talks about modularity. If you think about it, the development of the component is related to the presentation of the component documentation and the component library itself, but it’s not that related. You can use yarn’s workspace to separate them so that they exist as separate entities. Yarn workflows are similar to NPM using package.json files. Yarn reorganizes node_modules files and does not conflict with NPM. The YARN workspace helps us better manage multiple projects by using separate package.json to manage project dependencies in multiple subprojects. Yarn helps you analyze the shared dependencies of all subprojects based on the dependencies, ensuring that all common dependencies are downloaded and installed only once for all projects.

Initialize the project

Initialize the create project:

mkdir AzUiFont
cd AzUiFont
yarn init -y
Copy the code

Create gitignore.

node_modules
coverage
dist
es
lib

package-lock.json
Copy the code

Modify the package. The json

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

Build the initial directory structure:

├─ ├─ exercises, ├─ exercises, exercises, exercises, exercises, exercises, exercises, exercises, exercises, exercises, exercises, exercises, exercises ├ ─ index. The HTML ├ ─ package. Json ├ ─ README. Md └ ─ tsconfig. JsonCopy the code
<! DOCTYPEhtml>
<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>
Copy the code

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"]}}Copy the code

Code specification constraints

Using ESLint to constrain the code specification, install the following tools:

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

Add 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": {}};Copy the code

Add eslintignore.

*.sh
*.md
*.ico
*.css
*.md
*.scss
*.woff
*.ttf
*/*/shims.d.ts 
*/*/index.html
*/*/yarn-error.log
packages/azui/rollup-plugin-vue/index.d.ts
node_modules
lib
coverage
dist
Copy the code

Add the following command to 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 - the 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"}}Copy the code

Now that the code constraint part is processed, work on the component part

Component library section

Execute the command

cd .\packages\azui\
yarn init -y
Copy the code

package.json

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

The directory structure is as follows

├ ─ a rollup plugin - vue └ ─ SRC ├ ─ packages │ └ ─ Button │ ├ ─ Button. The vue │ ├ ─ index. The ts │ └ ─ __tests__ └ ─ stylesCopy the code

To integrate Babel into your project, you need to install the following dependencies:

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

Add 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}}}}]]Copy the code

Integrated automated Testing (unit testing)

Yarn add jest-d -w yarn add [email protected] -d -w yarn add babel-jest-d -w yarn add @vue/[email protected] -d -W yarn add @vue/test-utils@next -D -W yarn add typescript -D -WCopy the code

Add a jest. Config. Js

module.exports = {
  testEnvironment: "jsdom"./ / the default JSdom
  roots: ["<rootDir>/src/packages"].//
  transform: {
    "^.+\\.vue$": "vue-jest".// vue single file
    "^.+\\js$": "babel-jest".// The latest esM syntax import
  },
  moduleFileExtensions: ["vue"."js"."json"."jsx"."ts"."tsx"."node"].testMatch: ["**/__tests__/**/*.spec.js"]./ / alias
  moduleNameMapper: {
    "^azui(.*)$": "<rootDir>$1"."^main(.*)$": "<rootDir>/src$1",}};Copy the code

package.json

{
  "scripts": {
    "test": "jest --runInBand"
  }
}
Copy the code

Style package and add the following dependencies:

yarn add gulp -D -W yarn add gulp-autoprefixer -D -W yarn add gulp-sass -D -W yarn add gulp-cssmin -D -W yarn add cp-cli  -D -W yarn add tslib -D -WCopy the code

package.json

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

Package the component using Rollup and install the following dependencies:

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

Add a 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) The ${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-bundle
const esBundleConfig = {
  plugins: [
    replace({
      __DEV__: `(process.env.NODE_ENV ! == 'production')`,})],output: {
    file: createFileName("esm-bundler"),
    format: "es",}};// es-browser
const esBrowserConfig = {
  plugins: [
    replace({
      __DEV__: true,})],output: {
    file: createFileName("esm-browser"),
    format: "es",}};// es-browser.prod
const esBrowserProdConfig = {
  plugins: [
    terser(),
    replace({
      __DEV__: false,})],output: {
    file: createFileName("esm-browser.prod"),
    format: "es",}};// cjs
const cjsConfig = {
  plugins: [
    replace({
      __DEV__: true,})],output: {
    file: createFileName("cjs"),
    format: "cjs",}};// cjs.prod
const cjsProdConfig = {
  plugins: [
    terser(),
    replace({
      __DEV__: false,})],output: {
    file: createFileName("cjs.prod"),
    format: "cjs",}};// global
const globalConfig = {
  plugins: [
    replace({
      __DEV__: true."process.env.NODE_ENV": true,})],output: {
    file: createFileName("global"),
    format: "iife",
    name
  },
};
// global.prod
const 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();
Copy the code

package.json

{
  "scripts": {
    "build": "rollup -c"
  }
}
Copy the code

Now that the component library section is complete, configure the documentation section:

Document parts

Execute the command

cd .. /.. cd .\packages\docs\Copy the code

Create a directory structure:

├─public ├─scripts ├─ SRC ├─assets ├─ exercisesCopy the code

Install the following dependencies:

yarn add @vitejs/plugin-vue -D -w
yarn add markdown-it-containe -D -w
yarn add node-sass -D -w
yarn add sass -D -w
yarn add sass-loader -D -w
yarn add vite -D -w
yarn add vite-plugin-vuedoc -D -w
yarn add vue@next -S -W
yarn add vue-router@4 -S -W
Copy the code

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": "^ at 2.0.5." "."vite-plugin-vuedoc": "^ 3.1.2." "}}Copy the code

Add 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],
    }),
  ],
});
Copy the code

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"]
}
Copy the code

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
}
Copy the code

index.html

<! DOCTYPEhtml>
<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>
Copy the code

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;
Copy the code

src/docs/Button.zh-CN.md

-- title: Button wrapperClass: mD-button -- # Button use the 'color' attribute to define the color of the Button: 'primary' | 'success' | 'info' | 'warning' | 'danger' # # Button Props | | parameters shows that default value type | | | | -- -- -- -- -- -- -- -- -- -- - | -- -- -- -- -- -- -- -- -- -- -- -- -- - | -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - | -- -- -- -- -- - | | | color | type 'primary' / 'success' / 'warning' / 'danger' / 'info' / 'string' | - |Copy the code

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>
Copy the code

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>
Copy the code

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');
Copy the code

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[]
Copy the code

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[]),
    },
  ],
})
Copy the code

The documentation section is complete, and then the component development section is processed. Actually, the component development section and the documentation section can be placed together, using different routes, but they have different functions, so a separate subproject is configured.

Development section

Run the following command:

cd .. /.. cd .\packages\play\Copy the code

Directory structure:

├─ Public ├─ Scripts ├─index.html ├─ SRC ├─ vue ├─ mainCopy the code

Package. json, dependent on self-installation

{
  "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": "^ at 2.0.5." "}}Copy the code

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
}
Copy the code

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"]}Copy the code

vite.config.ts

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


export default defineConfig({
  server: {
    port: 8080,
  },
  optimizeDeps: {
    exclude: ["azui"],
  },
  plugins: [
    vue()
  ]
});
Copy the code

Now that the component development section is configured, it’s time to start the project, go back to the root directory and add scripts to the package.json directory:

Project start

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"}}Copy the code

Make sure to run yarn dev to run the components needed to package the development environment. Then run start or play. There are two command Windows to run.

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

This is because the dependent component libraries cannot be found in the project ~ this needs special attention.

conclusion

To build a relatively perfect component library, is the need to go through a series of projects precipitation. At present, there are still some problems in the development process of component library, such as version management, upgrade rollback and so on. Time is the best teacher. We believe that in the following iterations, we can still maintain the original intention and enthusiasm, actively explore and discover, and build a more perfect front-end engineering system.

Reference: Vue3 Component Library Engineering — Overview of Element3 Front-end Engineering