你在寻找Vue3移动端项目框架嘛?请看这里
现在web开发变得更加美妙高效,在于开发工具设计得更好了,丰富性与易用性,都有所提高。丰富性带来了一个幸福的烦恼,就是针对实际应用场景,如何选择工具 ?
1. Vue Cli和Vite之间的选择
Vite的开发环境体验好,基于浏览器原生ES6 Modules提供的功能,不对ES高版本语法进行转译,省略掉耗时的打包流程, 可是考虑到:
1) 项目要用到真机调试功能,开发环境下调试代码时不能使用ES高版本的语法,用着不顺畅。
2) Vite的一些痛点:
- Vite最新版2.7.x版本自带的less-loader, 将背景色的rgba属性转换成四位16进制在有些手机上存在兼容性问题。
- 与某些第三方工具库(比如说Cache-Router)不兼容,编译会报错。
- Vite的缓存机制,有时候让人有些困惑,代码修改了,重启之后都不生效,要手动删除node_modules下的.vite文件夹才生效。
- 给命令行动态添加自定义参数不太方便。
- Vite不支持装饰器语法,而有的第三方库用到了装饰器语法
3) Vite脚手架默认不集成TypeScript,Vue-Router,Vuex功能,使用起来不太方便
4) Vue Cli作为久经考验的成熟构建工具,稳定坑少,使用者众多,在生态环境和插件数量方面更好。
所以最终选择vue-cli最为Vue项目的脚手架。
安装最新版本vue脚手架
npm install -g @vue/cli@next
安装成功后通过查看版本命令,确认是否安装成功
vue -V
@vue/cli 5.0.0-rc.1
2 创建vue3项目
vue create vue3-demo
Vue CLI v5.0.0-rc.1
? Please pick a preset:
Default ([Vue 2] babel, eslint)
Default (Vue 3) ([Vue 3] babel, eslint) // 不选择默认的vue3配置,是因为没有vue-router+typescript功能,需要自己引入
> Manually select features // 手动选择特性
Vue CLI v5.0.0-rc.1
? Please pick a preset: Manually select features
? Check the features needed for your project: (Press <space> to select, <a> to toggle all, <i> to invert selection, and <enter> to proceed)
>(*) Choose Vue version
(*) Babel // 添加babel
(*) TypeScript // 添加类型约束功能
( ) Progressive Web App (PWA) Support
(*) Router // 添加路由功能
(*) Vuex // 添加状态管理功能
(*) CSS Pre-processors // 添加样式预编译功能
(*) Linter / Formatter // 添加代码质量校验提示和格式化功能
( ) Unit Testing
( ) E2E Testing
Vue CLI v5.0.0-rc.1
? Please pick a preset: Manually select features
? Check the features needed for your project: Choose Vue version, Babel, TS, Router, Vuex, CSS Pre-processors, Linter
? Choose a version of Vue.js that you want to start the project with
2.x
> 3.x // 选择vue3
Vue CLI v5.0.0-rc.1
? Please pick a preset: Manually select features
? Check the features needed for your project: Choose Vue version, Babel, TS, Router, Vuex, CSS Pre-processors, Linter
? Choose a version of Vue.js that you want to start the project with 3.x
? Use class-style component syntax? (y/N) N // 是否使用class组件语法, ,选N 项目中用Composition API
为了在Vue中使用TypeScript中,许多开发者选择了Class-Style Component 解决方案,时至今日,还有另外一个方案,Composition API 撰写的代码会完美享用类型推导,并且也不用做太多额外的类型标注。这也同样意味着你写出的 JavaScript 代码几乎就是 TypeScript 的代码。即使是非 TypeScript 开发者也会因此得到更好的 IDE 类型支持而获益。
常规风格
export default {
data(){
return {
selectOptions: ['A1', 'A2'],
results: [],
// ...
}
}
}
class 组件风格
import { Vue, Component } from 'vue-property-decorator'
@Component
export default class Game extends Vue {
// 定义data
private selectOptions = ['A1', 'A2']
private results: string[] = []
...
}
? Use class-style component syntax? Yes ? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes // 是否使用babel工具自动为转换后的 TypeScript 代码注入 polyfiills,此处选择 Y ? Use history mode for router? (Requires proper server setup for index fallback in production) Yes // 使用history网址路径风格,hash路径有点丑陋 ? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Less // sass在国内安装经常出错,所以选less ? Pick a linter / formatter config: Prettier // 校验配置选择 eslint+prettier组合,沿袭项目使用习惯 ? Pick additional lint features: Lint on save // 保存代码时校验代码质量, 提交代码时才去校验代码质量有些滞后 ? Where do you prefer placing config for Babel, ESLint, etc. In dedicated config files // 将Babel,ESlint等配置文件从package.json中独立出来,因为json文件不能写注释 ? Save this as a preset for future projects? Y // 将此配置保存起来,用于将来的项目 ,下次用vue-cli生成项目时,可以看到之前保存的配置项
启动服务
cd vue3-demo && yarn serve
在VSCode中打开app.vue发现文件中有许多红色的告警波浪线,安装Vetur扩展,绝大多数语法报错消失。
3 配置vue文件保存时自动格式化
代码美化功能,是一个重要的影响开发体验的指标。书写潦草的代码,按下Ctrl+S保存之后,瞬间变成整洁有序, 这种视觉感受,让人神清气爽。
在项目下新建.vscode/settings.json,内容如下:
{
// ...
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[vue]": {
"editor.defaultFormatter": "octref.vetur"
},
"[json]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
// ...
}
修改项目下的.prettierrc文件为.prettierrc.js, 内容如下:
module.exports = {
// 1.一行代码的最大字符数,默认是80(printWidth: <int>)
printWidth: 120,
// 2.tab宽度为2空格(tabWidth: <int>)
tabWidth: 2,
// 3.是否使用tab来缩进,我们使用空格(useTabs: <bool>)
useTabs: false,
// 4.结尾是否添加分号
semi: true,
// 5.使用单引号(singleQuote: <bool>)
singleQuote: true,
// 6.object对象中key值是否加引号(quoteProps: "<as-needed|consistent|preserve>")as-needed只有在需求要的情况下加引号,consistent是有一个需要引号就统一加,preserve是保留用户输入的引号
quoteProps: 'as-needed',
// 7.在jsx文件中的引号需要单独设置(jsxSingleQuote: <bool>)
jsxSingleQuote: false,
// 8.尾部逗号设置,es5是尾部逗号兼容es5,none就是没有尾部逗号,all是指所有可能的情况,需要node8和es2017以上的环境。(trailingComma: "<es5|none|all>")
trailingComma: 'all',
// 9.object对象里面的key和value值和括号间的空格(bracketSpacing: <bool>)
bracketSpacing: true,// 10.箭头函数单个参数的情况是否省略括号,默认always是总是带括号(arrowParens: "<always|avoid>")
arrowParens: 'always',
// 11.range是format执行的范围,可以选执行一个文件的一部分,默认的设置是整个文件(rangeStart: <int> rangeEnd: <int>)
rangeStart: 0,
rangeEnd: Infinity,
// 12. requirePragma: <bool>,格式化有特定开头编译指示的文件 比如下面两种
/**
* @prettier
*/
// or
/**
* @format
*/
requirePragma: false,
// 13.insertPragma: <bool> 自动插入pragma到已经完成的format的文件开头
insertPragma: false,
// 14. proseWrap: "<always|never|preserve>" 文章换行,默认情况下会对你的markdown文件换行 进行format会控制在printwidth以内
proseWrap: 'always',
// 15. htmlWhitespaceSensitivity: "<css|strict|ignore>" html中的空格敏感性
// html文档片段 1<b>2</b>3 原本显示为123, 不设置忽略空格的话格式化后会变成 1<b> 2 </b>3 显示为1 2 3
htmlWhitespaceSensitivity: 'ignore',
// 16. vue script和style标签中是否缩进,开启可能会破坏编辑器的代码折叠
vueIndentScriptAndStyle: false,
// 17. endOfLine: "<lf|crlf|cr|auto>" 行尾换行符,默认是lf,
endOfLine: 'lf',
// 18. 控制被引号包裹的代码是否进行格式化, 默认是auto,
embeddedLanguageFormatting: 'off'
}
4 配置移动端UI库
做移动端开发,虽然定制性比较强。绝大多数UI库组件都用不到,但像Toast,Modal,Picker,Form,PullRefresh等组件几乎是必用,所以需要引入移动端UI库。
vue3移动端UI库的选择:
antd-mobile-vue-next | 移入项目之后,编译报错 |
Vux | UI风格是绿色系,与现有项目使用的蓝色系风格UI不符, 所以没用 |
Vant | 是业界主流的移动端组件库之一,UI色系风格与历史项目相符,支持vue3,组件功能优于Vux,已Toast为例,Vant提供了网络加载的Toast, Vux未提供。Vant总共提供了69个(不含组合api)涵盖基础,表单,反馈,展示,导航,业务六大类组件。 |
yarn add vant@3
按需引入
按需加载需要借助babel-plugin-import
, 这样就可以只引入需要的组件,以减小项目体积
yarn add babel-plugin-import -D
对babel.config.js进行配置
module.exports = {
presets: ["@vue/cli-plugin-babel/preset"],
plugins: [
[
"import",
{
libraryName: "vant",
libraryDirectory: "es",
style: true,
},
"vant",
],
],
};
main.js中引入vant的样式
import { createApp } from "vue";
import App from "./App.vue";
import "vant/lib/index.css";
createApp(App).mount("#app");
在App.vue中引入组件
<template>
<div>
<Button type="primary">主要按钮</Button>
<img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld msg="Welcome to Your Vue.js App" />
</div>
</template> <script>
import HelloWorld from "./components/HelloWorld.vue";
import { Button } from "vant";
export default {
name: "App",
components: {
HelloWorld,
Button,
},
};
</script>
5 配置开发环境请求代理
请求代理是解决本地开发请求跨域的最佳方式之一,对前后端代码都没有侵入性。 在vue.config.js中添加代理转发配置:
const { defineConfig } = require("@vue/cli-service");
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
port: 9000,
host: "localhost",
https: false,
open: "/",
proxy: {
"/api": {
target: "http://192.168.xx.xx:50000",
secure: false,
changeOrigin: true,
logLevel: "debug",
},
},
},
// ....
});
6 配置路径别名
项目统一使用路径别名,好处是在代码中不用写../../../
之类让人看着有些云里雾里的文件引用路径,此外用短路径替代长路径,书写也更方便。而且编辑器对于别名路径也有提示,可以跳转。
需要注意的是,如果使用了TypeScript,除了要在vue.config.js中配置路径别名之外,还需要在tsconfig.json配置路径别名,否则虽然打包编译不报错,但是代码编辑器却会提示引用路径有错误。
vue.config.js路径别名配置
const path = require('path'); module.exports = {
configureWebpack: {
resolve: {
alias: {
'@': path.join(__dirname, 'src/')
}
}
}
}
tsconfig.json路径别名配置
{
"compilerOptions": {
// ...
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
}
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
// 包含自定义声明文件
"typings/**/*.d.ts",
],
// ...
}
7 设置自定义环境变量
开发调试的时候,需要动态在命令行添加动态参数,用以执行开发环境的调试逻辑,将自定义的命令行参数传到业务文件的方法是:
在package.json中传入自定义环境变量
{
// ...
"scripts": {
"start:wx": "ytt && vue-cli-service serve --mode local --wx true",
// ...
},
}
在vue.config.js中设置自定义环境变量
// ...
const webpack = require('webpack');
const { defineConfig } = require('@vue/cli-service');
const { wx, mode } = require('minimist')(process.argv.slice(2));
console.log({ wx, mode }); // console.log(process.env.VITE_API_HOST);
module.exports = defineConfig({
// ...
configureWebpack: {
plugins: [
// 定义环境变量
new webpack.DefinePlugin({
'process.env.WX_JS_SDK_ENABLED': wx, // 是否真机调试SDK模式
'process.env.CURRENT_ENV': JSON.stringify(mode),
}),
],
},
});
在业务文件中接收自定义环境变量
import { createApp } from 'vue';
import 'vant/lib/index.css';
import App from './App.vue';
import router from './router';
import store from './store'; console.log(process.env.WX_JS_SDK_ENABLED, process.env.CURRENT_ENV); createApp(App).use(store).use(router).mount('#app');
8 配置stylelint校验规则
stylelint的好处:
- 可以发现样式书写问题,如无效的十六进制值;重复的选择器;未命名的动画名称;错误的线性渐变语法;后面的属性覆盖前面的属性;前面的选择器优先级更高,覆盖后面的属性;选择器下未设置任何属性等。
- 能使所有人写的样式风格都一致,按照业内知名公司 (GitHub、Google、Airbnb)的样式规范要求写样式。
- 保存时自动对样式书写进行优化(如采用样式的简写形式,删除无意义小数点前面的0,调整样式顺序等),修复可以修复的样式错误。
1.安装依赖
yarn add -D stylelint stylelint-config-recess-order stylelint-order stylelint-config-standard stylelint-less stylelint-webpack-plugin postcss-html
2. 创建.stylelintrc.js 样式校验规则
module.exports = {
plugins: ['stylelint-less'],
extends: ['stylelint-order', 'stylelint-config-standard', 'stylelint-config-recess-order'],
rules: {
indentation: 2,
'at-rule-no-unknown': [true, { ignoreAtRules: ['mixin', 'extend', 'content', 'include'] }],
'no-empty-source': null, // null是关闭规则的意思--less文件内容可以为空
'no-descending-specificity': null, //禁止特异性较低的选择器在特异性较高的选择器之后重写
'font-family-no-missing-generic-family-keyword': null, // 关闭必须设置通用字体的规则
'property-no-unknown': [
true,
{
ignoreProperties: ['box-flex'], // 忽略某些未知属性的检测
},
],
'selector-pseudo-element-no-unknown': [
true,
{
ignorePseudoElements: ['ng-deep'], // 忽略ng-deep这种合法的伪元素选择器报警
},
],
'declaration-colon-newline-after': null, //一个属性过长的话可以写成多行
'media-feature-name-no-unknown': null, // 关闭禁止未知的媒体功能名
// 下面的排序规则是stylelint-config-recess-order的css排序规则,
// 要对某个属性排序进行调整,这个属性之前的样式排序都要配置在自定义属性排序中
'order/properties-order': [
{
// Must be first.
properties: ['all'],
},
{
// Position.
properties: ['position', 'top', 'right', 'bottom', 'left', 'z-index'],
},
{
// Display mode.
properties: ['box-sizing', 'display'],
},
{
// Flexible boxes.
properties: ['flex', 'flex-basis', 'flex-direction', 'flex-flow', 'flex-grow', 'flex-shrink', 'flex-wrap'],
},
{
// Grid layout.
properties: [
'grid',
'grid-area',
'grid-template',
'grid-template-areas',
'grid-template-rows',
'grid-template-columns',
'grid-row',
'grid-row-start',
'grid-row-end',
'grid-column',
'grid-column-start',
'grid-column-end',
'grid-auto-rows',
'grid-auto-columns',
'grid-auto-flow',
'grid-gap',
'grid-row-gap',
'grid-column-gap',
],
},
{
// Align.
properties: ['align-content', 'align-items', 'align-self'],
},
{
// Justify.
properties: ['justify-content', 'justify-items', 'justify-self'],
},
{
// Order.
properties: ['order'],
},
{
// Box model.
properties: [
'float',
'width',
'min-width',
'max-width',
'height',
'line-height',
'min-height',
'max-height',
'padding',
'padding-top',
'padding-right',
'padding-bottom',
'padding-left',
'margin',
'margin-top',
'margin-right',
'margin-bottom',
'margin-left',
'overflow',
'overflow-x',
'overflow-y',
'-webkit-overflow-scrolling',
'-ms-overflow-x',
'-ms-overflow-y',
'-ms-overflow-style',
'clip',
'clear',
],
},
{
// Typography.
properties: [
'font',
'font-family',
'font-size',
'font-style',
'font-weight',
'font-variant',
'font-size-adjust',
'font-stretch',
'font-effect',
'font-emphasize',
'font-emphasize-position',
'font-emphasize-style',
'-webkit-font-smoothing',
'-moz-osx-font-smoothing',
'font-smooth',
'hyphens',
'color',
'text-align',
'text-align-last',
'text-emphasis',
'text-emphasis-color',
'text-emphasis-style',
'text-emphasis-position',
'text-decoration',
'text-indent',
'text-justify',
'text-outline',
'-ms-text-overflow',
'text-overflow',
'text-overflow-ellipsis',
'text-overflow-mode',
'text-shadow',
'text-transform',
'text-wrap',
'-webkit-text-size-adjust',
'-ms-text-size-adjust',
'letter-spacing',
'word-break',
'word-spacing',
'word-wrap', // Legacy name for `overflow-wrap`
'overflow-wrap',
'tab-size',
'white-space',
'vertical-align',
'list-style',
'list-style-position',
'list-style-type',
'list-style-image',
],
},
{
// Accessibility & Interactions.
properties: [
'pointer-events',
'-ms-touch-action',
'touch-action',
'cursor',
'visibility',
'zoom',
'table-layout',
'empty-cells',
'caption-side',
'border-spacing',
'border-collapse',
'content',
'quotes',
'counter-reset',
'counter-increment',
'resize',
'user-select',
'nav-index',
'nav-up',
'nav-right',
'nav-down',
'nav-left',
],
},
{
// Background & Borders.
properties: [
'background',
'background-color',
'background-image',
"-ms-filter:\\'progid:DXImageTransform.Microsoft.gradient",
'filter:progid:DXImageTransform.Microsoft.gradient',
'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader',
'filter',
'background-repeat',
'background-attachment',
'background-position',
'background-position-x',
'background-position-y',
'background-clip',
'background-origin',
'background-size',
'background-blend-mode',
'isolation',
'border',
'border-color',
'border-style',
'border-width',
'border-top',
'border-top-color',
'border-top-style',
'border-top-width',
'border-right',
'border-right-color',
'border-right-style',
'border-right-width',
'border-bottom',
'border-bottom-color',
'border-bottom-style',
'border-bottom-width',
'border-left',
'border-left-color',
'border-left-style',
'border-left-width',
'border-radius',
'border-top-left-radius',
'border-top-right-radius',
'border-bottom-right-radius',
'border-bottom-left-radius',
'border-image',
'border-image-source',
'border-image-slice',
'border-image-width',
'border-image-outset',
'border-image-repeat',
'outline',
'outline-width',
'outline-style',
'outline-color',
'outline-offset',
'box-shadow',
'mix-blend-mode',
'filter:progid:DXImageTransform.Microsoft.Alpha(Opacity',
"-ms-filter:\\'progid:DXImageTransform.Microsoft.Alpha",
'opacity',
'-ms-interpolation-mode',
],
},
{
// SVG Presentation Attributes.
properties: [
'alignment-baseline',
'baseline-shift',
'dominant-baseline',
'text-anchor',
'word-spacing',
'writing-mode', 'fill',
'fill-opacity',
'fill-rule',
'stroke',
'stroke-dasharray',
'stroke-dashoffset',
'stroke-linecap',
'stroke-linejoin',
'stroke-miterlimit',
'stroke-opacity',
'stroke-width', 'color-interpolation',
'color-interpolation-filters',
'color-profile',
'color-rendering',
'flood-color',
'flood-opacity',
'image-rendering',
'lighting-color',
'marker-start',
'marker-mid',
'marker-end',
'mask',
'shape-rendering',
'stop-color',
'stop-opacity',
],
},
{
// Transitions & Animation.
properties: [
'transition',
'transition-delay',
'transition-timing-function',
'transition-duration',
'transition-property',
'transform',
'transform-origin',
'animation',
'animation-name',
'animation-duration',
'animation-play-state',
'animation-timing-function',
'animation-delay',
'animation-iteration-count',
'animation-direction',
],
},
],
},
};
编译时自动修复
// ...
const { defineConfig } = require('@vue/cli-service');
const StylelintPlugin = require('stylelint-webpack-plugin'); module.exports = defineConfig({
// ...
configureWebpack: {
plugins: [
// ...
new StylelintPlugin({
files: ['src/**/*.vue'],
// 编译时自动修复
fix: true,
// 这样配才能修复vue文件style片段中的less语法
customSyntax: 'postcss-html',
}),
],
},
});
安装VSCode stylelint扩展
在.vscode/settings.json中配置保存代码时自动修复样式错误
{
"editor.codeActionsOnSave": {
// ...
"source.fixAll.stylelint": true
},
// 关闭vscode自带的css,less,scss报错提示
"css.validate": false,
"less.validate": false,
"scss.validate": false,
"stylelint.validate": ["css", "less"]
}
9 配置yapi-to-typescript
typescript面世以来,经历了一个从厌烦到喜欢的过程,厌恶的是要在原来开发的基础上,多做一些繁杂数据类型定义的工作,喜欢的是确实帮助开发者发现了许多语法错误,享受到接口和传参的便利提示, 综合起来,还是利大于弊,所以 越来越多的开发者开始加入ts大家庭。yapi-to-typescript这个工具,可以帮我们省去接口数据类型定义的工作量。让我们更愉快的与ts玩耍。
安装依赖
yarn add -D yapi-to-typescript
创建ytt.config.ts配置文件
import { defineConfig } from 'yapi-to-typescript'; /**
* 生成Api接口名称 Interface和ChangeCase数据类型参见node_modules\yapi-to-typescript\lib\esm\index.d.ts定义
* @param interfaceInfo : Interface
* @param changeCase:ChangeCase
* @returns 请求响应接口名称--pascal命名
*/
function genApiInterfaceName(interfaceInfo, changeCase) {
// 取解析路径dir最尾部的路径作为前缀路径
const lastPath = interfaceInfo.parsedPath.dir.split('/').pop();
// 拼接前缀路径+文件名称
return `${changeCase.pascalCase(lastPath)}${changeCase.pascalCase(interfaceInfo.parsedPath.name)}`;
} export default defineConfig([
{
serverUrl: 'https://yapi.xxx.com',
typesOnly: true,
target: 'typescript',
reactHooks: {
enabled: false,
},
prodEnvName: '项目名称',
// 将生成文件路径转化成小驼峰命名方式
outputFilePath: (interfaceInfo, changeCase) => {
// 文件夹名称取api-url路径末尾2个
const filePathArr = interfaceInfo.path.split('/').slice(-2);
const filePath = filePathArr.map((item) => changeCase.camelCase(item)).join('/');
return `typings/httpTypes/${filePath}.ts`;
},
// 生成ts文件中请求参数interface名称,将下划线命名转换成pascal命名
getRequestDataTypeName: (interfaceInfo, changeCase) => {
return `${genApiInterfaceName(interfaceInfo, changeCase)}Request`;
},
// 生成ts文件中请求响应数据interface名称,将下划线命名转换成pascal命名
getResponseDataTypeName: (interfaceInfo, changeCase) => {
return `${genApiInterfaceName(interfaceInfo, changeCase)}Response`;
},
// 响应数据中要生成ts数据类型的键名
dataKey: 'retdata',
projects: [
{
// token获取方式: 在yapi-设置-token配置中查看
token: 'xxx',
// 分类id查找方式: 点击接口左侧的分类菜单,查看url地址栏最后面的数字获取
// 分类id配置特别重要,配置错了无法生成对应的ts数据类型定义文件
categories: [
{
id: [xxx], // 民生立减金API分类id
},
],
},
],
},
]);
3.在package.json中配置ytt指令
{
// ...
"scripts": {
"start": "ytt && vue-cli-service serve --mode local",
"build": "ytt && vue-cli-service build --mode local",
"ytt": "ytt",
},
}
4.在.gitignore中添加对httpTypes下文件的忽略
# ...
/typings/httpTypes/*
# ...
10 配置commitlint
commit message 是程序员开发的日常高频操作,自然状态下commit message 呈现五花八门的书写风格,不利于阅读和维护,规范的 commit message 有助于团队做 code review, 输出清晰明了的 CHANGELOG, 有利于项目的长期维护。
安装依赖包
yarn add -D husky conventional-changelog-cli @commitlint/{cli,config-conventional}
创建提交校验配置文件commitlint.config.js
/**
* git commit最佳实践
* 1.经常commit,One Thing,One Commit
* 2.commit之前测试,不要commit一半工作;
* 3.编写规范的commit message
*/ /**
* Commit message 包括三个部分:Header,Body 和 Footer
* <type>(<scope>): <subject>
* 空一行
* <body>
* 空一行
* <footer>
*/
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
// Header包括三个字段:type(必需)、scope(可选)和subject(必需)。最多200字
'header-max-length': [2, 'always', 200],
// 提交类型<type>枚举
'type-enum': [
2,
'always',
[
'init', // 项目初始化
'clean', // 清理过时无用文件
'merge', // 合并代码
'style', // 修改样式文件(包括css/less/sass,图片,字体文件)
'format', // 格式化,不影响代码含义的修改,比如空格、格式缩进、缺失的分号等
'build', // 改变构建流程、或者增加依赖库、工具等 如webpack.config.js,package.json yarn.lock
'chore', // 各种配置文件的修改, 如.gitignore,tsconfig.json,.vscode,.tenone, eslint/stylelint,envConfig
'ci', // 对CI配置文件或脚本进行了修改
'docs', // 修改项目说明文档
'feat', // 新增功能
'fix', // 修复bug
'perf', // 性能优化
'refactor', // 既不是修复bug也不是添加功能的代码重构
'revert', // 版本回退
'test', // 修改测试用例
],
],
// 格式-可选值
// 'lower-case' 小写 lowercase
// 'upper-case' 大写 UPPERCASE
// 'camel-case' 小驼峰 camelCase
// 'kebab-case' 短横线 kebab-case
// 'pascal-case' 大驼峰 PascalCase
// 'sentence-case' 首字母大写 Sentence case
// 'snake-case' 下划线 snake_case
// 'start-case' 所有首字母大写 start-case
// <type> 不能为空
'type-empty': [2, 'never'],
// <type> 格式 小写
'type-case': [2, 'always', 'lower-case'],
// <scope> 关闭改动范围不能为空规则
'scope-empty': [0, 'never'],
// <scope> 格式 小写
'scope-case': [2, 'always', 'lower-case'],
// <subject> 不能为空
'subject-empty': [2, 'never'],
// <subject> 关闭 以.为结束标志
'subject-full-stop': [0, 'never', '.'],
// <subject> 格式
'subject-case': [2, 'never', []],
// <body> 以空行开头
'body-leading-blank': [1, 'always'],
// <footer> 以空行开头
'footer-leading-blank': [1, 'always'],
},
};
3. 创建提交校验shell脚本 husky.sh和commit-msg
yarn husky install
在.husky文件夹下创建commit-msg文件
npx husky add .husky/commit-msg
在.husky/commit-msg文件中写入
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# 提交记录检查
yarn commitlint --edit $1
# 代码重复率检测
yarn jscpd
# 格式化检查
yarn format:check
# eslint检查
yarn lint:check
11 配置代码重复率检测工具jscpd
代码的简洁之道有一条铁律是 Don't Repeat Yourself,那么如何快速地检测出项目出是否存在着大段的重复代码,靠人工检查显然不可取,这种重复体力活应该交给工具。
检测前端代码重复率的工具有jsinspect、jscpd,PMD-CPD(PMD's Copy/Paste Detector)
- jsinspect工具支持js和jsx格式的文件,基于抽象语法树,可以检测出结构类似的代码块
- PMD-CPD工具支持js文件检测,也可以自己开发扩展包来解析指定的语言
- jscpd工具支持文件格式广泛,如js、jsx、vue、ts、less,java、oc等。其重复率判定依据为一定长度标识符的MD5值是否相同
每个工具各有其优缺点,若只需要检测js或jsx文件,且对检测结果要求较高,可以选择jsinspect或者PMD-CPD工具,若考虑检测工具的通用性,可以选择jscpd工具。
npm install -g jscpd
jscpd src/*
{
// 重复率阈值
"threshold": 0.1,
// 报告输出格式
"reporters": [
"html",
"console"
],
"ignore": [
"dist/**",
"node_modules/**"
],
// 文件路径使用相对路径
"absolute": false
}
--min-tokens | -k :代码的最小块大小。小于的代码块min-tokens将被跳过,默认为50; |
--min-lines | -l :最小代码行数,默认为5; |
--max-lines | -x : 最大代码行数,默认为1000; |
--max-size | -z :最大文件大小,单位为kb,默认100; |
--threshold | -t :重复级别的阈值,当项目重复级别大于该阈值时报错退出,默认为空; |
--ignore | -i :忽略的文件类型; |
--reporters | -r :输出类型 |
参考文献
你在寻找Vue3移动端项目框架嘛?请看这里的更多相关文章
- APP开发选择什么框架好? 请看这里!
背景 App的开发一般都需要满足Android和iOS两个系统环境,也就意味着一个App需要定制两套实现方案,造成开发成本和维护成本都很高.为了解决这个问题,最好的办法就是实现一套代码跨端运行,所以H ...
- 动端逐渐出了许多的移动端的框架,比如Sencha Touch、JQTouch、Jquery-moblie、jqMobi等等。这些框架都有优缺点,不同的框架应用在不同的项目中。现简单阐述一下各框架的优缺点:
移动前端工作的那些事---前端制作之微信小技巧篇 (2013-11-15 15:20) 转载▼ 标签: it css3/javascript html5 webapp 手机网站搭建 分类: 前端制 ...
- next.js、nuxt.js等服务端渲染框架构建的项目部署到服务器,并用PM2守护程序
前端渲染:vue.react等单页面项目应该这样子部署到服务器 貌似从前几年,前后端分离逐渐就开始流行起来,把一些渲染计算的工作抛向前端以便减轻服务端的压力,但为啥现在又开始流行在服务端渲染了呢?如v ...
- 从零开始搭建Electron+Vue+Webpack项目框架,一套代码,同时构建客户端、web端(一)
摘要:随着前端技术的飞速发展,越来越多的技术领域开始被前端工程师踏足.从NodeJs问世至今,各种前端工具脚手架.服务端框架层出不穷,“全栈工程师”对于前端开发者来说,再也不只是说说而已.在NodeJ ...
- 【原创】从零开始搭建Electron+Vue+Webpack项目框架(六)Electron打包,同时构建客户端和web端
导航: (一)Electron跑起来(二)从零搭建Vue全家桶+webpack项目框架(三)Electron+Vue+Webpack,联合调试整个项目(四)Electron配置润色(五)预加载及自动更 ...
- day97:MoFang:移动端APP开发准备&移动端项目搭建&APICloud前端框架
目录 1.移动端开发相关概念 1.APP类型 2.移动端屏幕介绍 3.移动端自适配方案 4.元信息(meta) 2.APP开发准备 1.注册APPCLoud账号 2.下载APP开发编辑器 3.下载AP ...
- 【原创】从零开始搭建Electron+Vue+Webpack项目框架,一套代码,同时构建客户端、web端(二)
摘要:上篇文章说到了如何新建工程,并启动一个最简单的Electron应用.“跑起来”了Electron,那就接着把Vue“跑起来”吧.有一点需要说明的是,webpack是贯穿这个系列始终的,我也是本着 ...
- 用 Vue 改造 Bootstrap,渐进提升项目框架[转]
GitChat 作者:Meathill 原文:用 Vue 改造 Bootstrap,渐进提升项目框架 关注微信公众号:「GitChat 技术杂谈」 一本正经的讲技术 [不要错过文末彩蛋] 前言 Vue ...
- 基于 vite 创建 vue3 全家桶项目(vite + vue3 + tsx + pinia)
vite 最近非常火,它是 vue 作者尤大神发布前端构建工具,底层基于 Rollup,无论是启动速度还是热加载速度都非常快.vite 随 vue3 正式版一起发布,刚开始的时候与 vue 绑定在一起 ...
随机推荐
- 解决git push报错error: failed to push some refs to 的问题
这个问题发生的背景一般是: 想把自己本地的某个项目关联到远程仓库并推送上去,接着他会做如下操作: 本地项目->远程创建仓库->本地关联远程->推送最新代码 最后一个步骤发生问题: 那 ...
- pipeline 共享库
目录 一.简介 二.共享库扩展 共享库使用 共享库结构 pipeline模板 一些小问题 三.共享库例子 使用公共变量 使用共享库的src方法 使用共享库的vars方法 四.插件实现pipeline ...
- 【论文笔记】Recommendations as Treatments: Debiasing Learning and Evaluation
Recommendations as Treatments: Debiasing Learning and Evaluation Authors: Tobias Schnabel, Adith Swa ...
- [BUUCTF]REVERSE——helloword
helloword 题目是安卓逆向.安卓逆向工具下载地址 用APKIDE打开附件,ctf+f调出检索版,检索main函数,能看到flag字符串 flag{7631a988259a00816deda84 ...
- PDF补丁丁将发布开放源代码的1.0版本
近况 一个月前的今天,母亲永远离开了我. 想起四个月前,我送她了去住院.入院后,做了检查.检查结果没出,我的生日就到了.母亲很关心我的生日.在电话里,她祝我身体健康,又问媳妇有没有给我做生日餐桌的菜肴 ...
- CF1265B Beautiful Numbers 题解
Content 给定一个 \(1\sim n\) 的排列,请求出对于 \(1\leqslant m\leqslant n\),是否存在一个区间满足这个区间是一个 \(1\sim m\) 的排列. 数据 ...
- CF1077A Frog Jumping 题解
Content 在一个数轴上有一个动点,初始时在 \(0\) 这个位置上,接下来有若干次操作,对于第 \(i\) 次操作: 如果 \(i\) 是奇数,那么动点往右移 \(a\) 个单位. 如果 \(i ...
- java 图形化小工具Abstract Window Toolit
老掉牙的历史 Java1.0在发布的时候,就为我们提供了GUI操作的库,这个库系统在所有的平台下都可以运行,这套基本的类库被称作抽象窗口工具集(Abstract Window Toolit),简称 ...
- Stun协议实现
在现实Internet网络环境中,大多数计算机主机都位于防火墙或NAT之后,只有少部分主机能够直接接入Internet.很多时候,我们希望网络中的两台主机能够直接进行通信(即所谓的P2P通信),而不需 ...
- 通过css实现表格的斜线
效果图 实现思路 编辑一个svg文件,可以自定义线条颜色和粗细. 将svg文件转为base64格式,作为背景图属性设置. svg转base64的网址:https://www.sojson.com/im ...