Why?
- 提升开发效率
- 降低开发难度
- 提升产品质量
- 降低企业成本
简单划分
5个部分:开发、构建、部署、性能、规范化
图片来源:
开发
模块化发展
一、无模块化标准阶段
1. 文件划分
通过手动管理script标签顺序的方式,变量定义在全局调试困难
2. 命名空间
每个文件导出一个对象,该文件中变量和方法都定义在该对象中,解决全局命名冲突
3. IIFE(立即执行函数)
4. prototype时期
二、模块化标准阶段
1. CJS
node中使用,同步,导出的变量可修改
主要用于服务器端
也可以用在浏览器端,但是需要browserify等工具编译。
2. AMD
和CJS同一时期出现的,RequireJS , AMD是其模块化规范,其最大的优势就是支持各种插件。
它是异步加载的,主要用在浏览器端。
3. CMD UMD
4. ESM
ES6引入
在node端使用CJS和EJS:总结为一句话:.mjs文件总是以 ES6 模块加载,.cjs文件总是以 CommonJS 模块加载,.js文件的加载取决于package.json里面type字段的设置。
特点:双端支持、异步、可以静态分析、导出变量为引用无法修改(但是调用导出的修改方法可以修改)
CJS与ESM的区别
- 使用方式不同:CJS使用require和module.exports进行导入导出,ESM使用import 和export 导入导出。ESM在浏览器端要将script标签的type=”module”,且文件后缀名需要为mjs
- CJS是运行时加载,ESM是编译时输出接口,因此可以进行静态分析从而进行treeshaking等操作。
- CJS输出值拷贝,ESM输出值引用(该引用只读)
- 循环引用时表现不同
https://es6.ruanyifeng.com/#docs/module-loader#%E5%BE%AA%E7%8E%AF%E5%8A%A0%E8%BD%BD
CJS只能取得模块中已加载部分,执行过的脚本会缓存而不会重新执行.
ESM不会缓存,它会认为加载过的模块的接口已经正常输出,开发者要自己保证此时已经可以取得该接口,否则报错。
5. CJS是同步加载,而ESM可以异步加载,可以在顶层使用await命令
6. 相互加载:
CJS只能通过import()
方法加载EJS模块
EJS加载CJS模块只能整体加载,不能只加载某项
包管理方案
三大包管理器:npm yarn pnpm
https://liyucang-git.github.io/2021/02/12/%E5%89%8D%E7%AB%AF%E5%8C%85%E7%AE%A1%E7%90%86%E5%99%A8%E5%AF%B9%E6%AF%94-npm-yarn-%E5%92%8C-pnpm/
什么时候需要包管理器?
当我们要使用一些第三方库时,可以通过script标签引入手动管理,但是当依赖变多和需要升级时就会变得很麻烦,这时就可以将包管理的工作交给包管理器,让它帮我们进行包的安装、管理、发布、升级。
包管理器发展
npm1 / 2
npm install发生什么?
- 构建依赖树
- 解析包版本号
- 下载对应的tar包到本地镜像(unix或类unix系统下的压缩包文件,理解为一个打包了的文件就好,需要解压)
- 将tar包解压到本地缓存。
- 将包从缓存拷贝到项目的node_modules文件夹中。
npm 1 / 2中包的管理呈现嵌套结构
导致3个问题:
- 依赖过深,文件名过长
- 重复安装,占用空间(每个包的依赖都放在自己的node_modules中)
- 模块示例不共享(由第二个问题引出)
npm3 / yarn
扁平化管理,解决嵌套层级深、包重复安装(node中require会一直往上级的node_modules中找,找到就不再安装)问题
又有新问题:
- 幻影依赖Phantom :package.json中未声明的包(一些依赖自己依赖的包)可以直接使用
- 分身依赖Doppelgangers :node_modules安装的不稳定性,不同包依赖不同版本的同一包时产生,见下图
- 平铺算法耗时
npm5.x / yarn带有lock文件的平铺node_modules
lock文件用于解决node_modules安装的不稳定性,基本原理就是生成一个lockfile记录依赖版本号
pnpm - 基于符号链接的node_modules结构
https://pnpm.io/zh/blog/2020/05/27/flat-node-modules-is-not-the-only-way
安装的package都存储在一个任何文件夹都可以访问的目录里,并通过硬链接(指向inode,指向真实物理磁盘地址的指针)的方式连接到各个node_modules,以节省磁盘空间(高效)。
package.json指定的依赖解析使用软链接平铺在node_modules文件夹中(指向项目node_modules目录下.pnpm文件夹下依赖的对应绝对路径),只允许使用package.json中声明的包。
扁平化+网状结构
扁平:项目直接依赖,软链接
网状:真实的硬链接
对比pnpm 与 yarn / npm
yarn / npm 缺点:
- 幻影依赖
- 分身依赖
- 平铺算法耗时速度慢
pnpm优点:
概括为严格高效快速
- 严格: 解决幻影依赖,只允许使用package.json中声明过的包
- 高效:安装的packages放在一个任何文件夹都可以访问的文件夹里,通过硬链接的方式链接到各个node_modules中,节省了磁盘空间。
- 有了以上特点,安装更快。
pnpm install
跟 npm install 类似,安装项目下所有的依赖。但对于 monorepo 项目,会安装 workspace 下面所有 packages 的所有依赖。不过可以通过 –filter 参数来指定 package,只对满足条件的 package 进行依赖安装。
代码规范
这一块可以看看这个仓库https://github.com/haixiangyan/linter-tutorial
eslint
诞生于2013年,用nodejs写的一个js代码格式检查工具,可以在不运行代码的情况下发现代码格式错误。
官方文档https://eslint.org/docs/user-guide/command-line-interface
eslint会遵循两个隐式的忽略规则:忽略node_modules/ 忽略 **'.'**
开头的文件(除了**.eslintrc.js**
)
在vite项目中集成eslint
“lint”:”npx eslint . —ext .vue,.js,.ts,.jsx,.tsx —fix” 指定文件扩展名和自动修复
npx eslint --init // 如果未安装会提示安装
规则:https://eslint.bootcss.com/docs/rules/
插件可能有对应的规则集可以用于extends
eslint插件eslint-plugin-vuehttps://eslint.vuejs.org/user-guide/#usage
module.exports = {
"env": {
"browser": true,
"es2021": true,
"node": true
},
// 继承eslint推荐的规则集,vue基本的规则集,typescript的规则集
"extends": [
"eslint:recommended",
"plugin:vue/vue3-recommended",
"plugin:@typescript-eslint/recommended",
"./.eslintrc-auto-import.json"
],
// 新增,解析vue文件中的template
"parser": "vue-eslint-parser",
// 支持ts的最新语法
"parserOptions": {
"ecmaVersion": "latest",
// 解析vue文件中的script
"parser": "@typescript-eslint/parser",
"sourceType": "module"
},
// 添加vue和@typescript-eslint插件,增强eslint的能力
"plugins": [
"vue",
"@typescript-eslint"
],
"rules": {
"vue/multi-word-component-names": 0,
"@typescript-eslint/no-var-requires": 0
}
}
// .vite.config.js
// 配合自动导入使用
// 配置eslint解析规则,防止报错
eslintrc: {
enabled: true, // 设置为true自动生成
filepath: './.eslintrc-auto-import.json', // Default `./.eslintrc-auto-import.json`
globalsPropValue: true, // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable')
},
prettier
先看https://zhuanlan.zhihu.com/p/81764012
再看官方文档https://prettier.io/
使用eslint插件https://www.npmjs.com/package/eslint-plugin-prettier
一个代码格式化工具:
- An opinionated code formatter: opinionated 的意思是必须按照它的规定来执行,Vue和React就是unopinionated
- Supports many languages:支持html js css markdown等
- Integrates with most editors
- Has few options: 只给必要的配置项,其他的按我说的来!
配置
module.exports = {
printWidth: 100, // 超过最大值换行
tabWidth: 2, // 缩进数
useTabs: false, // 缩进不使用tab,使用空格
semi: false, // 句尾添加分号
singleQuote: true, // 使用单引号代替双引号
proseWrap: 'preserve', // 默认值。因为使用了一些折行敏感型的渲染器(如GitHub comment)而按照markdown文本样式进行折行
arrowParens: 'avoid', // (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid:省略括号
bracketSpacing: true, // 在对象,数组括号与文字之间加空格 "{ foo: bar }"
// disableLanguages: ['vue'],
// 不格式化vue文件,vue文件的格式化单独设置
// vueIndentScriptAndStyle: true,
//是否缩进 Vue 文件中的代码<script>和<style>标签
endOfLine: 'auto', // 结尾是 \n \r \n\r auto
htmlWhitespaceSensitivity: 'ignore',
trailingComma: 'es5', // 在对象或数组最后一个元素后面是否加逗号(在ES5中加尾逗号)
}
// prettierignore
/dist/*
.json
env.d.ts
.local
.output.js
/node_modules/**
**/*.svg
**/*.sh
/public/*
.md
package.json
.config.json
.config.js
.eslintrc.js
Stylelint
css样式代码的格式化工具
https://stylelint.io/user-guide/get-started
https://www.npmjs.com/package/eslint-plugin-prettier 修复样式顺序插件
样式顺序https://www.npmjs.com/package/stylelint-order
less支持https://www.npmjs.com/package/postcss-less
// .stylelintrc.json
{
"extends": [
"stylelint-config-standard",
"stylelint-config-prettier",
"stylelint-config-recommended-vue"
],
"customSyntax": "postcss-less",
"plugins": [
"stylelint-order"
],
"rules": {
"order/order": [
"custom-properties",
"declarations"
],
"order/properties-order": [
"position",
"top",
"right",
"bottom",
"left",
"z-index",
"display",
"justify-content",
"align-items",
"float",
"clear",
"overflow",
"overflow-x",
"overflow-y",
"margin",
"margin-top",
"margin-right",
"margin-bottom",
"margin-left",
"padding",
"padding-top",
"padding-right",
"padding-bottom",
"padding-left",
"width",
"min-width",
"max-width",
"height",
"min-height",
"max-height",
"font-size",
"font-family",
"font-weight",
"border",
"border-style",
"border-width",
"border-color",
"border-top",
"border-top-style",
"border-top-width",
"border-top-color",
"border-right",
"border-right-style",
"border-right-width",
"border-right-color",
"border-bottom",
"border-bottom-style",
"border-bottom-width",
"border-bottom-color",
"border-left",
"border-left-style",
"border-left-width",
"border-left-color",
"border-radius",
"text-align",
"text-justify",
"text-indent",
"text-overflow",
"text-decoration",
"white-space",
"color",
"background",
"background-position",
"background-repeat",
"background-size",
"background-color",
"background-clip",
"opacity",
"filter",
"list-style",
"outline",
"visibility",
"box-shadow",
"text-shadow",
"resize",
"transition"
]
}
}
lint_staged+husky
https://www.npmjs.com/package/lint-staged
https://typicode.github.io/husky/#/?id=install
lint-staged在commit之前运行配置的任务,只会对暂存区的文件运行任务(如linter等)
husky: git 客户端的hook工具,比如 pre-commit 钩子就会在你执行 git commit 的触发。
https://github.com/okonet/lint-stagednpx mrm lint-staged
根据package.json自动化生成husky配置
"lint-staged": {
"*.{ts,vue}": [
"npm run lint",
"npm run lint:prettier",
"npm run stylelint",
"git add"
],
"*.{vue,js,ts,jsx,tsx}": "eslint --cache --fix",
"*.css": "stylelint --fix"
},
commitlint
https://commitlint.js.org/#/guides-local-setup
用于规范化commit message
# For Windows:
pnpm install --save-dev @commitlint/config-conventional @commitlint/cli
# Configure commitlint to use conventional config
echo "module.exports = { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js
commitlint提交规范
commitizen
http://commitizen.github.io/cz-cli/
pnpm install -D commitizen // 安装Commitizen CLI工具
// 初始化
npx commitizen init cz-conventional-changelog --save-dev --save-exact
// 将git commit 换成 git cz 不行就 npx cz
commit信息规范
https://www.ruanyifeng.com/blog/2016/01/commit_message_change_log.html
代码规范完整引入配置
// 集成eslint
npx eslint --init
// 安装eslint的prettier插件,用eslint控制prettier
pnpm i prettier eslint-plugin-prettier eslint-config-prettier -D
//配置命令
"lint:prettier":"prettier src/**/*.{html,vue,css,sass,scss,ts,md} --write"
// .eslintrc.js
module.exports = {
"env": {
"browser": true,
"es2021": true
},
"extends": [
// 一些拓展预设配置,通常是最佳实践
'eslint:recommended',
// https://eslint.bootcss.com/docs/rules/
'plugin:vue/vue3-strongly-recommended',
// "plugin:vue/essential", vue2版本
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
'prettier', //放最后
],
parser: 'vue-eslint-parser', // 解析器 用于将代码变成ast
"parserOptions": {
//解析器的配置项
ecmaVersion: 'latest',
//版本 可以改为esXXXX
parser: '@typescript-eslint/parser',
sourceType: 'module',
},
"plugins": [
"vue",
"@typescript-eslint"
],
"rules": {
'no-irregular-whitespace': 'error',
'prettier/prettier': 'error',
'arrow-body-style': 'off',
'prefer-arrow-callback': 'off',
}
}
//.prettierrc.js
// prettier.config.js or .prettierrc.js
module.exports = {
printWidth: 100, // 超过最大值换行
tabWidth: 2, // 缩进数
useTabs: false, // 缩进不使用tab,使用空格
semi: true, // 句尾添加分号
singleQuote: true, // 使用单引号代替双引号
proseWrap: 'preserve', // 默认值。因为使用了一些折行敏感型的渲染器(如GitHub comment)而按照markdown文本样式进行折行
arrowParens: 'avoid', // (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid:省略括号
bracketSpacing: true, // 在对象,数组括号与文字之间加空格 "{ foo: bar }"
// disableLanguages: ['vue'],
// 不格式化vue文件,vue文件的格式化单独设置
vueIndentScriptAndStyle: false,
//是否缩进 Vue 文件中的代码<script>和<style>标签
endOfLine: 'auto', // 结尾是 \n \r \n\r auto
htmlWhitespaceSensitivity: 'ignore',
trailingComma: 'es5', // 在对象或数组最后一个元素后面是否加逗号(在ES5中加尾逗号)
};
//.prettierignore
/dist/*
.json
env.d.ts
.local
.output.js
/node_modules/**
**/*.svg
**/*.sh
/public/*
.md
package.json
.config.json
.config.js
// 引入stylelint
pnpm install --save-dev stylelint stylelint-config-standard
// 结合prettier使用stylelint
pnpm install --save-dev stylelint-config-prettier
// vue文件stylelint预设
pnpm i stylelint-config-recommended-vue
// 引入修复样式顺序插件
pnpm install stylelint-order --save-dev
// .stylelintrc.json
{
"extends": [
"stylelint-config-standard",
"stylelint-config-prettier",
"stylelint-config-recommended-vue"
],
"plugins": [
"stylelint-order"
],
"rules": {
"order/order": [
"custom-properties",
"declarations"
],
"order/properties-order": [
"position",
"top",
"right",
"bottom",
"left",
"z-index",
"display",
"justify-content",
"align-items",
"float",
"clear",
"overflow",
"overflow-x",
"overflow-y",
"margin",
"margin-top",
"margin-right",
"margin-bottom",
"margin-left",
"padding",
"padding-top",
"padding-right",
"padding-bottom",
"padding-left",
"width",
"min-width",
"max-width",
"height",
"min-height",
"max-height",
"font-size",
"font-family",
"font-weight",
"border",
"border-style",
"border-width",
"border-color",
"border-top",
"border-top-style",
"border-top-width",
"border-top-color",
"border-right",
"border-right-style",
"border-right-width",
"border-right-color",
"border-bottom",
"border-bottom-style",
"border-bottom-width",
"border-bottom-color",
"border-left",
"border-left-style",
"border-left-width",
"border-left-color",
"border-radius",
"text-align",
"text-justify",
"text-indent",
"text-overflow",
"text-decoration",
"white-space",
"color",
"background",
"background-position",
"background-repeat",
"background-size",
"background-color",
"background-clip",
"opacity",
"filter",
"list-style",
"outline",
"visibility",
"box-shadow",
"text-shadow",
"resize",
"transition"
]
}
}
// lint-stage + husky
pnpm install husky -D
npx husky install
// package.json
"scripts": {
"prepare": "husky install" // 在pnpm install 之后自动运行 pnpm husky install
},
git操作
命令
--grep
过滤提交历史git log <last release> HEAD --grep feat
commit信息
type:
- feat:新功能(feature)
- fix:修补bug
- docs:文档(documentation)
- style: 格式(不影响代码运行的变动)
- refactor:重构(即不是新增功能,也不是修改bug的代码变动)
- test:增加测试
- chore:构建过程或辅助工具的变动
scope用于说明 commit 影响的范围,比如数据层、控制层、视图层等等,视项目不同而不同。
subject是 commit 目的的简短描述,不超过50个字符。
<type>(<scope>): <subject>
// 空一行
<body>
// 空一行
<footer>