共计 17361 个字符,预计需要花费 44 分钟才能阅读完成。
Vue3.0
曾经公布了很长一段时间了,最近也在想着怎么去做工程化的货色,于是就想本人弄一个组件库捎带深刻学习Vue3.0
, 于是便有了明天的这篇文章。
Git 地址:https://github.com/ZhQuella/AzUIFront
技术栈
包管理工具:
yarn
开发模块:
Vite
Vue 3.0
打包工具:
Gulp
Rollup
单元测试:
Jest
语法工具:
ESLint
语言:
TypeScript
为什么要应用 Yarn
看到包管理工具应用的事 yarn
或者很多小伙伴不太能了解为什么要应用 yarn
,说到这里可能就须要理解一下前端的工程化的概念了,什么是前端的工程化?工程化别离为 模块化
、 组件化
、 规范化
和自动化
。
模块化
模块化
是指将一个文件拆分成多个相互依赖的文件,最初进行对立的打包和加载,这样可能很好的保障高效的多人合作。JavaScript
模块化:CommonJS
、AMD
、CMD
以及 ES6 Module
。CSS
模块化:Sass
、Less
、Stylus
、BEM
、CssModules
等。其中预处理器和 BEM 都会有的一个问题就是款式笼罩。资源模块化
:任何资源都能以模块的模式进行加载,目前大部分我的项目中的文件、CSS、图片等都能间接通过 JS 做对立的依赖关系解决
组件化
不同于模块化,模块化是对文件、对代码和资源拆分,而组件化则是对 UI 层面
的拆分。
组件化并不是前端所特有的,一些其余的语言或者桌面程序等,都具备组件化的先例。确切的说,只有有 UI 层的展现,就必然有能够组件化的中央。简略来说,组件就是将一段 UI 款式和其对应的性能作为独立的整体去对待,无论这个整体放在哪里去应用,它都具备一样的性能和款式,从而实现复用,这种整体化的细想就是组件化。不难看出,组件化设计就是为了减少复用性,灵活性,进步零碎设计,从而进步开发效率。
组件零碎是一个重要概念,因为它是一种形象,容许咱们应用小型、独立和通常可复用的组件构建大型利用。咱们会须要对页面进行拆分,将其拆分成一个一个的整机,而后别离去实现这一个个整机,最初再进行组装。
组件化的形象设计是很重要的,不仅减少了复用性进步了工作效率,从某种程度上来说也反馈了程序员对业务和产品设计的了解,一旦有问题或者须要性能扩大时,你就会发现之前的设计是如许的有意义。
规范化
规范化指的是咱们在工程开发初期以及开发期间制订的系列标准,其中又蕴含了:
- 我的项目目录构造
- 对于编码这块的束缚,个别咱们都会采纳一些强制措施,比方
ESLint
、StyleLint
等。 - 联调标准
- 文件命名标准
- 款式治理标准:目前风行的款式治理有
BEM
、Sass
、Less
、Stylus
、CSS Modules
等形式 - 工作流:其中蕴含分支命名标准、代码合并标准等
- 定期代码审查
自动化
从最早先的 grunt
、gulp
等,再到目前的webpack
、parcel
。这些自动化工具在自动化合并、构建、打包都能为咱们节俭很多工作。而这些只是前端自动化其中的一部分,前端自动化还蕴含了继续集成、自动化测试等方方面面。
想必大家对与工程化也有了肯定的理解,那么会过头来持续说为什么要应用 yarn
,下面说到了 模块化
如果咱们想一下,组件的开发与组件文档的展现和组件库的自身是存在所有关联的,然而关联性并没有那么大,能够应用 yarn
的工作空间来分隔他们使他们本事作为一个独立的个体而存在,yarn
工作流与 npm
相似都是应用 package.json
文件,yarn
会重组 node_modules
文件,且不会与 npm
抵触。yarn
的工作空间可能更好的帮忙咱们治理多个我的项目,能够在多个子项目中应用独立的 package.json
治理我的项目依赖。yarn
会依据就依赖关系帮忙你剖析所有子项目的共用依赖,保障所有的我的项目专用的依赖只会被下载和装置一次。
初始化我的项目
初始化创立我的项目:
mkdir AzUiFont
cd AzUiFont
yarn init -y
创立.gitignore
node_modules
coverage
dist
es
lib
package-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 -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
增加.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.log
packages/azui/rollup-plugin-vue/index.d.ts
node_modules
lib
coverage
dist
在 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 -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
增加.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 -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
增加 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 -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"}
}
应用 Rollup 打包组件,装置如下依赖:
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
增加 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"}
}
组件库局部曾经实现,接下来配置文档局部:
文档局部
执行命令
cd ../..
cd .\packages\docs\
创立目录构造:
├─public
├─scripts
└─src
├─assets
├─components
└─__docs__
装置如下依赖:
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"
}
}
增加 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[]),
},
],
})
文档局部实现,接下来解决组件开发局部,其实组件开发局部能够和文档局部放在一起,应用不同的路由,然而两者的性能不雷同,所以独自配置了一个子项目。
开发局部
执行如下命令:
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
,记的有两个命令行窗口运行哦,如果间接运行start
和play
会抛出谬误:
[plugin:vite:import-analysis]
Failed to resolve entry for package "azui".
The package may have incorrect main/module/exports specified in its package.json.
这是因为在我的项目中无奈找到所依赖的组件库~ 这一点须要非凡留神。
结束语
要搭建一个绝对欠缺的组件库,都是须要通过一系列我的项目的积淀的。目前而言,组件库的开发流程上仍然会存在一些问题,比方版本治理、降级回退等。工夫是最好的老师,置信在前面的迭代中,咱们仍然可能放弃初心与激情,积极探索与发现,构建出更加欠缺的前端工程体系。