手摸手从零搭建vite+typescript+vue3项目(上)--eslint+prettier+husky+lint-staged

项目介绍

简介

  1. 架构一个Vite + typescript + vue3生态链项目。文档记录了作者搭建此项目架构的全过程,每个阶段的分支都留在了仓库中,可以一步一步跟着此文档的流程进入到相应的分支中查看对应代码,进而自己搭建出一个类似项目的开发环境。
  2. 此项目架构可作为一个通用架构便于开发相同技术栈的项目。
  3. 此项目可用于学习Vite + typescript + vue3生态链的相关技术

包含内容

  • Vite + typescript + vue3生态链 项目架构
  • Vite 分开发环境和生产环境进行配置
  • 新旧浏览器的兼容性处理
  • 配置eslint + stylelint + prettier 去统一代码风格
  • 配置 commitizen + commitlint 去规范代码提交,提交代码时不要执行 git commit ,而是执行封装好的命令 pnpm commit
  • 对vue-router 、 pinia、 本地mock、axios拦截器、表单验证进行封装
  • 支持自动注册组件和自动引入api
  • 集成icon-park库和animate.css以及gsap

关于类型声明

组件和apis的类型声明写在自身文件内

store里的类型声明单独创建一个types文件

版权声明

项目本身由作者一人开发完成,其中借鉴了许多网络和书籍的资料,如有侵犯您的权益,可联系作者删除相关内容。

项目地址

gitee: https://gitee.com/charleydeng/vue3-vite-ts-cli

初始化项目

使用 vite-cli 命令

法一:常规做法

 # pnpm
 pnpm create vite
 ​
 # npm
 npm init vite@latest
 ​
 # yarn
 yarn create vite

法二:快速初始化

 # pnpm
 pnpm create vite project-name -- --template vue-ts
 ​
 # npm 6.x
 npm init vite@latest project-name --template vue-ts
  
 # npm 7+, 需要额外的双横线:
 npm init vite@latest project-name -- --template vue-ts
  
 # yarn
 yarn create vite project-name --template vue-ts

环境配置

保证 node 的使用

 pnpm i @types/node --save-dev

修改 tsconfig.json

 {
   "compilerOptions": {
     "typeRoots": [//  要包含的类型声明文件路径列表
       "node_modules/@types"
       "src/types"
    ],
     "target""esnext",
     "useDefineForClassFields"true,
     "module""esnext",
     "moduleResolution""node",
     "strict"true,
     "jsx""preserve",
     "sourceMap"true,
     "resolveJsonModule"true,
     "esModuleInterop"true,
     "lib": ["esnext""dom"],
     "baseUrl""./",
     "paths":{ //模块名到基于 baseUrl的路径映射的列表(配置别名)
       "@": ["src"],
       "@/*": ["src/*"],
     }
   },
   "include": ["src/**/*.ts""src/**/*.d.ts""src/**/*.tsx""src/**/*.vue"]
 }

修改 vite.config.ts

 import { defineConfig } from 'vite';
 import vue from '@vitejs/plugin-vue';
 import * as path from 'path';
 ​
 // https://vitejs.dev/config/
 export default defineConfig({
     resolve: {
         //设置别名
         alias: {
             '@': path.resolve(__dirname, 'src')
         }
     },
     plugins: [vue()],
     server: {
         port: 8080, //启动端口
         hmr: {
             host: '127.0.0.1',
             port: 8080
         },
         // 设置 https 代理
         proxy: {
             '/api': {
                 target: 'your https address',
                 changeOrigin: true,
                 rewrite: (path: string) => path.replace(/^/api/, '')
             }
         }
     }
 });

给自定义的环境变量获得类型提示

默认情况下,Vite 在 vite/client.d.ts 中为 import.meta.env 提供了类型定义。 src 目录下创建一个 env.d.ts 文件,接着按下面这样增加 ImportMetaEnv 的定义:

 interface ImportMetaEnv {
   readonly VITE_APP_TITLE: string
   // 更多环境变量...
 }

按环境划分vite配置文件

新建config目录

目录结构:

. ├── productionPlugins │ ├── compress.ts │ └── visualizer.ts ├── utils │ └── index.ts //存放一些配置里用到的工具函数 ├── vite.config.base.ts ├── vite.config.dev.ts └── vite.config.prod.ts

具体内容进目录的文件自己看

修改pachage.json文件
     "dev""vite --config ./config/vite.config.dev.ts",
     "build""vue-tsc --noEmit && vite build --config ./config/vite.config.prod.ts",
     "report""cross-env REPORT=true pnpm build", /*设置环境变量process.env.REPORT为'true'且执行pnpm build  !若系统没有cross-env 命令可以全局装一下*/
     "preview""vite preview",
vite.config.prod.ts
可视化

使用 rollup-plugin-visualizer (opens new window)可以对打包结果进行可视化的展示。

image-20220119155629040
image-20220119155629040

安装配置

 yarn add --dev rollup-plugin-visualizer
分块打包(可选)

使用分块打包可以将内容打包到不同的文件中,减少单个文件大小,提高加载速度。下面将node_modules的扩展单独进行打包。(具体我们这个项目怎么打包还需要了解)

 export default defineConfig({
   plugins: [vue()],
   build: {
     rollupOptions: {
       emptyOutDir: true,
       output: {
         manualChunks(id) {
           if (id.includes('node_modules')) {
             return id.toString().split('node_modules/')[1].split('/')[0].toString()
           }
         },
       },
     },
   },
 })

实际内容见文件里的

CDN加载

可以使用cdn加载的包,建议使用cdn完成,这样会减少打包后的文件大小。(前提是CDN得稳定)

下面是使用cdn加载 echarts、font-awesome、animate.css包。

 <script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.2.2/echarts.min.js"></script>
 <link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet" />
 <link href="https://cdn.bootcdn.net/ajax/libs/animate.css/4.1.1/animate.min.css" rel="stylesheet" />

兼容性处理

Vite

浏览器兼容性

用于生产环境的构建包会假设目标浏览器支持现代 JavaScript 语法。默认情况下,Vite 的目标浏览器是指能够 支持原生 ESM script 标签支持原生 ESM 动态导入 的。作为参考,Vite 使用这个 browserslist 作为查询标准:

 defaults and supports es6-module and supports es6-module-dynamic-import, not opera > 0, not samsung > 0, not and_qq > 0

你也可以通过 build.target 配置项 指定构建目标,最低支持 es2015

请注意,默认情况下 Vite 只处理语法转译,且 默认不包含任何 polyfill。你可以前往 Polyfill.io 查看,这是一个基于用户浏览器 User-Agent 字符串自动生成 polyfill 包的服务。

传统浏览器可以通过插件 @vitejs/plugin-legacy 来支持,它将自动生成传统版本的 chunk 及与其相对应 ES 语言特性方面的 polyfill。兼容版的 chunk 只会在不支持原生 ESM 的浏览器中进行按需加载。

@vitejs/plugin-legacy

参考资料

首先安装插件:pnpm add @vitejs/plugin-legacy -D ·然后在vite.config.js中配置

 import legacyPlugin from '@vitejs/plugin-legacy'
 export default defineConfig( {
     plugins: [
         legacyPlugin({
             targets:['chrome 52'],  // 需要兼容的目标列表,可以设置多个
             additionalLegacyPolyfills:['regenerator-runtime/runtime'] // 面向IE11时需要此插件
         })
     ]
 })
build.target
  • 类型: string | string[]

  • 默认: 'modules'

    设置最终构建的浏览器兼容目标。默认值是一个 Vite 特有的值——'modules',这是指 支持原生 ES 模块的浏览器

    另一个特殊值是 “esnext” —— 即假设有原生动态导入支持,并且将会转译得尽可能小:

    • 如果 build.minify 选项为 'terser''esnext' 将会强制降级为 'es2019'
    • 其他情况下将完全不会执行转译。

    转换过程将会由 esbuild 执行,并且此值应该是一个合法的 esbuild 目标选项。自定义目标也可以是一个 ES 版本(例如:es2015)、一个浏览器版本(例如:chrome58)或是多个目标组成的一个数组。

    注意:如果代码包含不能被 esbuild 安全地编译的特性,那么构建将会失败。查看 esbuild 文档 获取更多细节。

build.cssTarget
  • 类型: string | string[]

  • 默认值:build.target 一致

    此选项允许用户为 CSS 的压缩设置一个不同的浏览器 target,此处的 target 并非是用于 JavaScript 转写目标。

    应只在针对非主流浏览器时使用。 最直观的示例是当你要兼容的场景是安卓微信中的 webview 时,它支持大多数现代的 JavaScript 功能,但并不支持 CSS 中的 #RGBA 十六进制颜色符号。 这种情况下,你需要将 build.cssTarget 设置为 chrome61,以防止 vite 将 rgba() 颜色转化为 #RGBA 十六进制符号的形式。

postcss(可选)

也许vite不需要用这个插件(待研究)

vite默认已经集成了postcss 无需安装postcss

自动添加前缀

使用前:

原文地址(https://juejin.cn/post/7060351422885265415#heading-2)
原文地址(https://juejin.cn/post/7060351422885265415#heading-2)

使用后:

原文地址(https://juejin.cn/post/7060351422885265415#heading-2)
原文地址(https://juejin.cn/post/7060351422885265415#heading-2)
安装 postcss-preset-env 插件
 pnpm install postcss-preset-env -D
两种配置方法
  1. vite.config.prod.ts
 import postcssPresetEnv from 'postcss-preset-env'
 export default defineConfig({
   plugins: [vue()],
     css: {
       postcss: {
         plugins: [postcssPresetEnv],
       },
     },
 })
  1. 新建 postcss.config.js 并配置

     module.exports = {
       plugins: [
         require('postcss-preset-env')
       ]
     }
其他postcss插件

参考资料1 参考资料2 或者 用到时再继续查找

babel(可选)

vite-babel-plugin: A plugin for vite using babel plugin.

 $ pnpm i -D vite-babel-plugin

then in vite.config.js

 import babel from "vite-babel-plugin";
 ​
 export default {
   plugins: [
     babel(),
   ],
 };

then vite-babel-plugin will Will read .babelrc in the root directory of your project.

统一代码风格

集成 eslint

安装
 pnpm i eslint eslint-plugin-vue eslint-config-airbnb-base eslint-plugin-import eslint-import-resolver-typescript -D

由于 ESLint 默认使用 Espree 进行语法解析,无法识别 TypeScript 的一些语法,故我们需要安装 @typescript-eslint/parser 替代掉默认的解析器

 pnpm install @typescript-eslint/parser -D

安装对应的插件 @typescript-eslint/eslint-plugin 它作为 eslint 默认规则的补充,提供了一些额外的适用于 ts 语法的规则。

 pnpm install @typescript-eslint/eslint-plugin -D
创建配置文件

.eslintrc.js.eslintrc.json

 module.exports = {
   parser: 'vue-eslint-parser',
 ​
   parserOptions: {
     parser: '@typescript-eslint/parser',
     ecmaVersion: 2020,
     sourceType: 'module',
     ecmaFeatures: {
       jsx: true,
     },
   },
   env: {
     browser: true,
     node: true,
     'vue/setup-compiler-macros'true,
   },
   plugins: ['@typescript-eslint'],
   extends: [
     'airbnb-base',
         'plugin:vue/vue3-recommended',
         'plugin:import/recommended',
         'plugin:import/typescript',
     'plugin:@typescript-eslint/recommended',
     // 'prettier', //解决prettier和eslint的冲突
     'plugin:prettier/recommended', //解决prettier和eslint的冲突
   ],
 ​
   rules: {
     // override/add rules settings here, such as:
     'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
     'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
     'no-var''off',
     semi: ['error''never'], //强制不使用分号
     // 'quotes': [2, 'single'],//强制使用单引号
     'no-trailing-spaces': 2, //不允许行末空格
     'no-plusplus''off', // 允许使用++
     'no-await-in-loop''error', // 禁止在循环中使用await
     'no-unused-vars''error', //禁止出现未使用的变量
   },
 }
 ​
创建忽略文件

.eslintignore

 node_modules/
 dist/
 index.html
 /*.json
命令行式运行

修改 package.json

 {
     ...
     "scripts": {
         ...
         "eslint:comment""使用 ESLint 检查并自动修复 src 目录下所有扩展名为 .js 和 .vue 的文件",
         "eslint""eslint --ext .js,.vue,.ts,.jsx --ignore-path .gitignore --fix src",
     }
     ...
 }

集成 prettier

prettier 是一套代码格式规范,一般用作格式化工具。而在项目中,js交给eslint,css交给stylelint,这个主要就用于html或jsx或json部分的格式化。

安装
 pnpm i prettier eslint-config-prettier eslint-plugin-prettier -D  //解决prettier和eslint的冲突
创建配置文件

prettier.config.js.prettierrc.js

prettier的配置似乎是每次更改后都要重新打开vscode才能生效

 module.exports = {
   // 一行最多 80 字符
   printWidth: 120,
   // 使用 4 个空格缩进
   tabWidth: 4,
   // 使用 tab 缩进,而使用空格
   useTabs: true,
   // // 行尾需要有分号
   semi: false,
   // 使用单引号代替双引号
   singleQuote: true,
   // 对象的 key 仅在必要时用引号
   quoteProps: 'as-needed',
   // jsx 不使用单引号,而使用双引号
   jsxSingleQuote: false,
   // 末尾使用逗号
   trailingComma: 'all',
   // 大括号内的首尾需要空格 { foo: bar }
   bracketSpacing: true,
   // jsx 标签的反尖括号需要换行
   bracketSameLine: false,
   // 箭头函数,只有一个参数的时候,不需要括号
   arrowParens: 'avoid',
   // 每个文件格式化的范围是文件的全部内容
   rangeStart: 0,
   rangeEnd: Infinity,
   // 不需要写文件开头的 @prettier
   requirePragma: false,
   // 不需要自动在文件开头插入 @prettier
   insertPragma: false,
   // 使用默认的折行标准
   proseWrap: 'preserve',
   // 根据显示样式决定 html 要不要折行
   htmlWhitespaceSensitivity: 'css',
   // 换行符使用 lf
   endOfLine: 'auto',
 }
 ​
创建.prettierignore文件
 /dist/*
 .local
 .output.js
 /node_modules/**
 ​
 **/*.svg
 **/*.sh
 ​
 src/**/*.scss
 src/**/*.css
 /*不知为啥prettier自动修复完缩进后,stylelint插件会说不对,所以先让prettier不格式化scss和css问件忽略*/
修改 .eslintrc.js 配置
 module.exports = {
     ...
 ​
     extends: [
         'plugin:vue/vue3-recommended',
         'plugin:@typescript-eslint/recommended',
         'prettier',//解决prettier和eslint的冲突
         'plugin:prettier/recommended'//解决prettier和eslint的冲突
     ],
 ​
     ...
 };
命令行式运行
   "scripts": { 
     ……
     "prettier""prettier --write .",
   },

集成stylelint

下载依赖
 pnpm i -D stylelint stylelint-config-standard stylelint-config-rational-order  stylelint-config-prettier

stylelint-config-rational-order 处理css属性间的顺序(Stylelint 配置通过按顺序组合在一起对相关属性声明进行排序: 定位 盒子模型 排版 视觉的 动画片 杂项 ---npm介绍)

stylelint-config-prettier 禁用所有与格式相关的 Stylelint 规则,解决 prettier 与 stylelint 规则冲突,确保将其放在 extends 队列最后,这样它将覆盖其他配置。(Turns off all rules that are unnecessary or might conflict with Prettier. This lets you use your favorite shareable config without letting its stylistic choices get in the way when using Prettier---npm 介绍)

新建 .stylelintrc.js 文件
 module.exports = {
   extends: ['stylelint-config-standard''stylelint-config-rational-order''stylelint-config-prettier'],
   defaultSeverity: 'error',
   plugins: ['stylelint-order'],
   rules: {
     indentation: 4,
     'at-rule-no-unknown': [
       true,
       {
         ignoreAtRules: ['plugin'],
       },
     ],
     'rule-empty-line-before': [
       'always',
       {
         except: ['after-single-line-comment''first-nested'],
       },
     ],
     'selector-pseudo-class-no-unknown': [
       true,
       {
         ignorePseudoClasses: ['deep'],
       },
     ],
   },
 }
 ​

如果你想修改插件的默认规则,可以看官方文档,它提供了 170 项规则修改。例如我想要用 4 个空格作为缩进,可以这样配置:

 module.exports = {
     "extends""stylelint-config-standard",
     "rules": {
         "indentation": 4
     }
 }
命令行

在 package.json 配置检查与修复命令:

   "scripts": {
     "lint:style""stylelint "src/*.{css,scss}"",
     "fix:style""stylelint --fix "src/*.{css,scss}""
   }
scss

如果你想格式化 scss 文件,则需要下载 stylelint-scss stylelint-config-standard-scss 插件:

 npm i -D stylelint-scss stylelint-config-standard-scss

注意,要把 stylelint-config-standard 改成 stylelint-config-standard-scss,然后就可以格式化 scss 文件了。

 module.exports = {
   extends: ['stylelint-config-standard-scss', ……],
   ……  
 }

如果检测不到scss代码,可能是因为插件的设置这里没加上scss

image-20220525182759500
image-20220525182759500

自动检查并修复

安装Eslint插件

新版 vscode 需要手动启用 eslint 插件,在右下角查看 eslint 工作状态,可以点击开启。(如下图)

右下角查看 eslint 工作状态,点击会输出日志。(如下图)

根据输出日志,进行修复

安装prettier插件
安装stylelint 插件
在这里插入图片描述
在这里插入图片描述
保存自动格式化

settings.json中设置

   "editor.codeActionsOnSave": {
     "source.fixAll.eslint"true,
     "source.fixAll.stylelint"true,
     "source.fixAll.prettier"true
   },

editor设置保存自动格式化

editor设置保存自动格式化
editor设置保存自动格式化
bug

App.vue文件里的style保存时没有被格式化,不知为啥???

规范git提交

利用 commitizen + commitlint

  • @commitlint/cli + @commitlint/config-conventional

    • commit 信息校验工具

    • @commitlint/config-conventional

      这是一个规范配置,标识采用什么规范来执行消息校验, 这个默认是Angular的提交规范

      类型描述
      build编译相关的修改,例如发布版本、对项目构建或者依赖的改动
      chore其他修改, 比如改变构建流程、或者增加依赖库、工具等
      ci持续集成修改
      docs文档修改
      feat新特性、新功能
      fix修改bug
      perf优化相关,比如提升性能、体验
      refactor代码重构
      revert回滚到上一个版本
      style代码格式修改, 注意不是 css 修改
      test测试用例修改
  • commitizen + cz-conventional-changelog

    • 辅助 commit 信息 ,就像这样,通过选择输入,规范提交信息

      alt
安装
 pnpm install -D  @commitlint/config-conventional @commitlint/cli  commitizen  cz-conventional-changelog
自定义提交(可选)

commitlint-config-cz 自定义提交规范

cz-customizable 自定义提交提示信息

配置 package.json
 {
   ...
   "scripts": {
     "commit:comment""引导设置规范化的提交信息",
     "commit":"git-cz",
   },
 ​
   //如果没有自定义规范则用默认的
       "config": {
         "commitizen": {
             "path""./node_modules/cz-conventional-changelog"
         }
     },
   
   //如果有自定义提交规范的话
   "config": {
       "commitizen": {
         "path""node_modules/cz-customizable" //将原来commit配置,变更为自定义配置
       }
   },
   ...
 }
新增配置 commitlint.config.js

commitlint官网

 module.exports = {
     extends: ['@commitlint/config-conventional''cz'],
   
   //下面这些是自定义的,可以都不要
     rules: {
         'type-enum': [
             2,
             'always',
             [
                 'feature', // 新功能(feature)
                 'bug', // 此项特别针对bug号,用于向测试反馈bug列表的bug修改情况
                 'fix', // 修补bug
                 'ui', // 更新 ui
                 'docs', // 文档(documentation)
                 'style', // 格式(不影响代码运行的变动)
                 'perf', // 性能优化
                 'release', // 发布
                 'deploy', // 部署
                 'refactor', // 重构(即不是新增功能,也不是修改bug的代码变动)
                 'test', // 增加测试
                 'chore', // 构建过程或辅助工具的变动
                 'revert', // feat(pencil): add ‘graphiteWidth’ option (撤销之前的commit)
                 'merge', // 合并分支, 例如: merge(前端页面): feature-xxxx修改线程地址
                 'build', // 打包
             ],
         ],
         // <type> 格式 小写
         'type-case': [2, 'always''lower-case'],
         // <type> 不能为空
         'type-empty': [2, 'never'],
         // <scope> 范围不能为空
         'scope-empty': [2, 'never'],
         // <scope> 范围格式
         'scope-case': [0],
         // <subject> 主要 message 不能为空
         'subject-empty': [2, 'never'],
         // <subject> 以什么为结束标志,禁用
         'subject-full-stop': [0, 'never'],
         // <subject> 格式,禁用
         'subject-case': [0, 'never'],
         // <body> 以空行开头
         'body-leading-blank': [1, 'always'],
         'header-max-length': [0, 'always', 72],
     },
 };
自定义提示则添加 .cz-config.js(可选)
 module.exports = {
     types: [
         {value: 'feature',  name: 'feature:  增加新功能'},
         {value: 'bug',      name: 'bug:      测试反馈bug列表中的bug号'},
         {value: 'fix',      name: 'fix:      修复bug'},
         {value: 'ui',       name: 'ui:       更新UI'},
         {value: 'docs',     name: 'docs:     文档变更'},
         {value: 'style',    name: 'style:    代码格式(不影响代码运行的变动)'},
         {value: 'perf',     name: 'perf:     性能优化'},
         {value: 'refactor', name: 'refactor: 重构(既不是增加feature,也不是修复bug)'},
   {value: 'release',  name: 'release:  发布'},
   {value: 'deploy',   name: 'deploy:   部署'},
         {value: 'test',     name: 'test:     增加测试'},
         {value: 'chore',    name: 'chore:    构建过程或辅助工具的变动(更改配置文件)'},
         {value: 'revert',   name: 'revert:   回退'},
       {value: 'build',    name: 'build:    打包'}
     ],
     // override the messages, defaults are as follows
     messages: {
         type'请选择提交类型:',
         customScope: '请输入您修改的范围(可选):',
         subject: '请简要描述提交 message (必填):',
         body: '请输入详细描述(可选,待优化去除,跳过即可):',
         footer: '请输入要关闭的issue(待优化去除,跳过即可):',
         confirmCommit: '确认使用以上信息提交?(y/n/e/h)'
     },
     allowCustomScopes: true,
     skipQuestions: ['body''footer'],
     subjectLimit: 72
 };

husky +lint-staged

  • 前面只是规范了 git 的提交信息,我们对提交前代码的检查还没有做到位,例如 ESLint、Prettier,毕竟谁都会有疏忽的时候,
  • 那么现在我们的 husky 就闪亮登场了

lint-staged 是一个只检测git暂存区lint工具,husky是一个用来给我们的项目添加git hook的工具,git hook是进行git操作会触发的脚本,例如:提交的时候会触发pre-commit钩子,输入提交信息会触发commit-msg钩子。 我们用husky安装pre-commit钩子,我们就可以在进行git commit操作的时候,运行我们的脚本来检测待提交的代码是否规范,便可以只对暂存区的文件进行检查。

安装

 # 1.安装
 pnpm i husky lint-staged -D
 ​
 # 2.生成 .husky 的文件夹
 npx husky install
 ​
 # 3.添加 hooks,会在 .husky 目录下生成一个 pre-commit 脚本文件
 npx husky add .husky/pre-commit "npx --no-install lint-staged"
 ​
 # 4.添加 commit-msg
 npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'

添加配置 package.json

 {
   ...
     "scripts": {
     "lint-staged""npx lint-staged",
     "prepare""husky install"
   },
   "lint-staged": {
     "*.{js,ts,jsx,tsx,vue}": [
       "prettier --write",
       "eslint --fix"
     ],
     "*.{scss,less,css}": [
       "stylelint --fix"
     ],
     "*.{html,json,yaml,md}": [
       "prettier --write"
     ]
   },
   ...
 }

版本控制(可选)

  • [standard-version] https%3A%2F%2Fgithub.com%2Fconventional-changelog%2Fstandard-version 或者 [conventional-changelog]https%3A%2F%2Fgithub.com%2Fconventional-changelog%2Fconventional-changelog

集成各种插件

 pnpm i @vueuse/core
  
   # .scss and .sass
  pnpm i -D sass
 ​
  # .less
  pnpm i -D less
  
  pnpm i axios
  
  pnpm add echarts --save 
  pnpm add -D @types/echarts

本文由 mdnice 多平台发布

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值