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 by myself to learn more about Vue3.0
, so I have today’s article.
Git address: https://github.com/ZhQuella/AzUIFront
Technology stack
Package management tools:
Development module:
Packaging tools:
unit test:
Grammar tools:
Language:
Why use Yarn
Seeing the use of package management tools yarn
perhaps many friends do not understand why yarn
, you may need to understand the concept of front-end engineering. What is front-end engineering? The engineering is modularization,
componentization,
standardization and
automation.
Modular
Modularization refers to splitting a file into multiple interdependent files, and finally performing unified packaging and loading, which can ensure efficient multi-person collaboration.
JavaScript
modular: CommonJS
, AMD
, CMD
and ES6 Module
.CSS
modularity: Sass
, Less
, Stylus
, BEM
, CssModules
etc. One of the problems that both the preprocessor and BEM have is style coverage. Resource Modularization: Any resource can be loaded in the form of a module. At present, most of the files, CSS, pictures, etc. in the project can be directly processed through JS for unified dependency processing
Componentization
Different from modularization, modularization is the separation of files, codes and resources, while componentization is the UI level.
Componentization is not unique to the front end. Some other languages or desktop programs have precedents for componentization. To be precise, as long as there is a display of the UI layer, there must be a place for componentization. Simply put, a component is to treat a piece of UI style and its corresponding function as an independent whole. No matter where the whole is used, it has the same function and style, so as to achieve reuse. This integrated Thinking about it is componentization. It is not difficult to see that component design is to increase reusability, flexibility, and improve system design, thereby improving development efficiency.
The component system is an important concept because it is an abstraction that allows us to build large applications using small, independent, and usually reusable components. We will need to split the page, split it into parts one by one, and then realize the parts one by one, and finally assemble it.
Component-based abstract design is very important. It not only increases reusability and improves work efficiency, but also reflects the programmer’s understanding of business and product design to a certain extent. Once there is a problem or need to expand the function, you You will discover how meaningful the previous design is.
Normalization
Standardization refers to the series of specifications that we formulated in the early stage and during the development of the project, which also includes:
- Project directory structure
- Regarding the constraints of coding, generally we will adopt some mandatory measures, such as
ESLint
,StyleLint
etc. - Joint Commissioning Specifications
- File naming convention
- Style management standard: currently popular style management has
BEM
,Sass
,Less
,Stylus
,CSS Modules
etc. - Workflow: It includes branch naming specifications, code merging specifications, etc.
- Regular code review
automation
From the earliest grunt
, gulp
etc., to the current webpack
, parcel
. These automated tools can save us a lot of work in automating merging, building, and packaging. And these are only part of front-end automation, front-end automation also includes continuous integration, automated testing and other aspects.
I think everyone has a certain understanding of engineering, so I will go yarn
and continue to talk about why 06089787a8e6af should be used. The above mentioned modularization. If we think about it, there is everything in the development of components, the display of component documents and the component library itself. Related, but the relationship is not so big, you can use the
yarn
to separate them so that they can exist as an independent individual. The yarn
workflow is npm
using the package.json
file, and yarn
will reorganize the node_modules
file, and Will not conflict npm
yarn
can better help us manage multiple projects. Independent package.json
can be used in multiple sub-projects to manage project dependencies. yarn
will help you analyze the common dependencies of all sub-projects based on the dependencies, and ensure that all common dependencies of the projects will only be downloaded and installed once.
Initialize the project
Initially create the project:
mkdir AzUiFont
cd AzUiFont
yarn init -y
Create .gitignore
node_modules
coverage
dist
es
lib
package-lock.json
Modify package.json
{
"name": "az-ui-font",
"private": true,
"version": "0.0.1",
"main": "index.js",
"license": "MIT"
}
Build the initial directory structure:
├─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"]
}
}
Code specification constraints
Here, eslint
is used to constrain the code specification, and the following tools are installed:
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
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": {
}
};
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
Add the following command in 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"
}
}
The code constraint part has been processed, and the component part will be processed next
Component library section
Excuting an order
cd .\packages\azui\
yarn init -y
package.json
{
"name": "azui",
"version": "0.0.1",
"private": true,
"license": "MIT"
}
The directory structure is as follows
├─rollup-plugin-vue
└─src
├─packages
│ └─Button
│ ├─Button.vue
│ ├─index.ts
│ └─__tests__
└─styles
To integrate Babel
into the project, the following dependencies need to be installed:
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 -W
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 }]]
}
}
}
Integrated automated testing (unit testing)
yarn add jest -D -W
yarn add vue-jest@5.0.0-alpha.5 -D -W
yarn add babel-jest -D -W
yarn add @vue/compiler-sfc@3.0.2 -D -W
yarn add @vue/test-utils@next -D -W
yarn add typescript -D -W
Add 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"
}
}
Style packaging, 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 -W
package.json
{
"scripts": {
"build:theme": "gulp build --gulpfile gulpfile.js"
}
}
Use Rollup to package components 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
Add 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-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();
package.json
{
"scripts": {
"build": "rollup -c"
}
}
The component library part has been completed, and then configure the document part:
Documentation section
Excuting an order
cd ../..
cd .\packages\docs\
Create the directory structure:
├─public
├─scripts
└─src
├─assets
├─components
└─__docs__
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
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"
}
}
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],
}),
],
});
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: Button
wrapperClass: 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[]),
},
],
})
The document part is completed, and then the component development part is processed. In fact, the component development part can be put together with the document part and use different routes, but the functions of the two are different, so a sub-project is configured separately.
Development part
Execute the following commands:
cd ../..
cd .\packages\play\
Directory Structure:
├─public
├─scripts
├─index.html
└─src
├─App.vue
└─main.ts
package.json, related dependencies are installed by themselves
{
"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()
]
});
In this case part of the component development also configured, now is the time to start the project returns to the root directory in the root directory package.json
added in scripts
:
Project begining
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"
}
}
It should be noted that you must first run yarn dev
according to dev
to run the components required for the development environment, and then run start
or play
, remember that there are two command line windows to run, if you run start
and play
directly, it will throw error:
[plugin:vite:import-analysis]
Failed to resolve entry for package "azui".
The package may have incorrect main/module/exports specified in its package.json.
This is because the dependent component library cannot be found in the project~ this requires special attention.
Concluding remarks
To build a relatively complete component library, it needs to go through a series of projects. At present, there are still some problems in the development process of the component library, such as version management, upgrade rollback, etc. Time is the best teacher. I believe that in the subsequent iterations, we can still maintain our original intention and enthusiasm, actively explore and discover, and build a more complete front-end engineering system.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。