一、概念
命令行界面(英语:command-line interface,缩写:CLI),俗称脚手架。
1、基本工作流程
- 通过命令行交互询问用户问题
- 根据用户回答的结果生成文件
2、热门工具
| 名称 | 简介 | | —- | —- | | commander | 命令行自定义指令 | | inquirer | 命令行询问用户问题,记录回答结果 | | chalk | 控制台输出内容样式美化 | | ora | 控制台 loading 样式 | | figlet | 控制台打印 logo | | easy-table | 控制台输出表格 | | download-git-repo | 下载远程模版 | | fs-extra | 系统fs模块的扩展,提供了更多便利的 API,并继承了fs模块的 API | | cross-spawn | 支持跨平台调用系统上的命令 |
二、vue/cli 配置
1、初始化
- 通过npx
- 执行:
npx @vue/cli create my-project
- 执行:
2、配置选择
- default 配置
- Babel:即ESNext,可使用下一代 JavaScript 语法。作为 webpack loader加载
- Eslint:即代码格式检测
手动选择特性:可以选择将已选项保存为一个将来可复用的 preset。
CLI 服务 (
@vue/cli-service
) 是一个开发环境依赖。局部安装在每个@vue/cli
创建的项目中的一个 npm 包- 构建于 webpack 和 webpack-dev-server 之上
- CLI 插件是提供可选功能的 npm 包,例如 Babel/TypeScript 转译、ESLint 集成、单元测试和 end-to-end 测试等。Vue CLI 插件的名字以
@vue/cli-plugin-
(内建插件) 或vue-cli-plugin-
(社区插件) 开头 - 项目内部运行
vue-cli-service
命令时,它会自动解析并加载package.json
中列出的所有 CLI 插件
4、插件
插件可以修改 webpack 的内部配置,也可以向 vue-cli-service
注入命令。每个 CLI 插件包含一个 (用来创建文件的) 生成器和一个 (用来调整 webpack 核心配置和注入命令的) 运行时插件
- 已有项目中安装一个插件:使用
vue add
命令,如vue add eslint
- 建议先提交项目最新状态,该命令可能调用插件的文件生成器并很有可能更改你现有的文件
- 不带
@vue
前缀,该命令会换作解析一个 unscoped 的包,会安装第三方插件 - 插件已经被安装:使用
vue invoke
命令跳过安装过程,只调用它的生成器
本地插件:需要每个文件暴露一个函数,接受插件 API 作为第一个参数
{
"vuePlugins": {
"service": ["my-commands.js"]
}
}
5、cli服务
vue-cli-service serve
:启动一个开发服务器 (基于 webpack-dev-server) 并附带开箱即用的模块热重载 (Hot-Module-Replacement)。也可使用vue.config.js
里的 devServer 字段配置开发服务器vue-cli-service build [options]
:在dist/
目录产生一个可用于生产环境的包,带有 JS/CSS/HTML 的压缩,和为更好的缓存自动的 vendor chunk splitting。它的 chunk manifest 会内联在 HTML 里- vue-cli-service build —modern:产生两个应用的版本,一个现代版的包,面向支持 ES modules 的现代浏览器,另一个旧版的包,面向不支持的旧浏览器。 ``` 用法:vue-cli-service build [options] [entry|pattern]
选项: —modern 面向现代浏览器带自动回退地构建应用 —target app | lib | wc | wc-async (默认值:app) 允许你将项目中的任何组件以一个库或 Web Components 组件的方式进行构建 —report 生成 report.html 以帮助分析包内容 —report-json 生成 report.json 以帮助分析包内容
- `vue-cli-service inspect`:审查一个 Vue CLI 项目的 webpack config
<a name="irOLy"></a>
### 6、浏览器兼容性
<a name="lwT8l"></a>
#### 6.1 browserslist
`package.json` 文件里的 `browserslist` 字段指定项目的目标浏览器的范围。值会被 @babel/preset-env 和 Autoprefixer 用来确定需转译的 JS 特性和需添加的 CSS 浏览器前缀。如何指定见[browserslist](https://github.com/browserslist/browserslist)
<a name="dBP5Y"></a>
#### 6.2 polyfill
一个默认的 Vue CLI 项目会使用 @vue/babel-preset-app,它通过 `@babel/preset-env` 和 `browserslist` 配置来决定项目需要的 polyfill。
- 默认把 `useBuiltIns: 'usage'` 传递给 `@babel/preset-env`,根据源代码中出现的语言特性自动检测需要的 polyfill。确保最终包里 polyfill 数量的最小化。但**如果其中一个依赖需要特殊的 polyfill,默认情况下 Babel 无法将其检测出来**
- 如果有依赖需要 polyfill:
- **如果该依赖基于一个目标环境不支持的 ES 版本撰写:** 将其添加到 `vue.config.js` 中的 `transpileDependencies` 选项。这会为该依赖同时开启语法转换和根据使用情况检测 polyfill
- **如果该依赖交付了 ES5 代码并显式地列出了需要的 polyfill:** 使用 `@vue/babel-preset-app` 的 polyfills 选项预包含所需要的 polyfill。**注意 **`**es.promise**`** 将被默认包含,因为现在的库依赖 Promise很普遍。**
```javascript
// babel.config.js
module.exports = {
presets: [
['@vue/app', {
polyfills: [
'es.promise',
'es.symbol'
]
}]
]
}
- 如果该依赖交付 ES5 代码,但使用 ES6+ 特性且没有显式地列出需要的 polyfill (例如 Vuetify):请使用
**useBuiltIns: 'entry'**
然后在入口文件添加**import 'core-js/stable'; import 'regenerator-runtime/runtime';**
。这会根据**browserslist**
目标导入所有 polyfill,但是因为包含了一些没有用到的 polyfill 所以最终的包大小可能会增加。- 构建库或是 Web Component 时的 Polyfills:推荐给
@vue/babel-preset-app
传入useBuiltIns: false
选项。确保库或是组件不包含不必要的 polyfills。通常来说,打包 polyfills 应当是最终使用你的库的应用的责任
- 构建库或是 Web Component 时的 Polyfills:推荐给
7、webpack 相关
7.1 简单的配置方式
configureWebpack 作为对象:将会被 webpack-merge 合并入最终的 webpack 配置
// vue.config.js
module.exports = {
configureWebpack: {
plugins: [
new MyAwesomeWebpackPlugin()
]
}
}
configureWebpack 作为函数:基于环境有条件地配置行为或直接修改配置,在环境变量被设置后懒执行
- 函数第一个参数会收到已经解析好的配置config。在函数内可直接修改配置,或返回一个将会被合并的对象
// vue.config.js
module.exports = {
configureWebpack: config => {
if (process.env.NODE_ENV === 'production') {
// 为生产环境修改配置...
} else {
// 为开发环境修改配置...
}
}
}
- 函数第一个参数会收到已经解析好的配置config。在函数内可直接修改配置,或返回一个将会被合并的对象
7.2 链式操作
webpack-chain 库提供一个 webpack 原始配置的上层抽象,使其可以定义具名的 loader 规则和具名插件,并有机会在后期进入这些规则并对它们的选项进行修改。允许更细粒度的控制其内部配置
// vue.config.js
module.exports = {
chainWebpack: config => {
config.module
.rule('vue')
.use('vue-loader')
.loader('vue-loader')
.tap(options => {
// 修改它的选项...
return options
})
config.module
.rule('graphql')
.test(/\.graphql$/)
.use('graphql-tag/loader')
.loader('graphql-tag/loader')
.end()
// 你还可以再添加一个 loader
.use('other-loader')
.loader('other-loader')
.end()
const svgRule = config.module.rule('svg')
svgRule.uses.clear()//清除已有的所有 loader。否则接下来 loader 会附加在该规则现有 loader 后
// 添加要替换的 loader
svgRule
.use('vue-svg-loader')
.loader('vue-svg-loader')
config.plugin('html')
.tap(args => {
//传递给 html-webpack-plugin's 构造函数的新参数
args[0].template = '/Users/username/proj/app/templates/index.html'
return args
})
}
}
8、多页面打包
多页面:指一个项目多个入口,打包会生成多个html文件,实际开发过程混合在一个项目中开发
在 multi-page 模式下构建应用。每个“page”应该有一个对应的 JavaScript 入口文件。其值应该是一个对象,对象的 key 是入口的名字,value 是:
- 一个指定了
entry
,template
,filename
,title
和chunks
的对象 (除了entry
之外都是可选的); - 或一个指定其
entry
的字符串。module.exports = {
pages: {
index: {
// page 的入口
entry: 'src/index/main.js',
// 模板来源
template: 'public/index.html',
// 在 dist/index.html 的输出
filename: 'index.html',
// 当使用 title 选项时,
// template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
title: 'Index Page',
// 在这个页面中包含的块,默认情况下会包含
// 提取出来的通用 chunk 和 vendor chunk。
chunks: ['chunk-vendors', 'chunk-common', 'index']
},
// 当使用只有入口的字符串格式时,
// 模板会被推导为 `public/subpage.html`
// 并且如果找不到的话,就回退到 `public/index.html`。
// 输出文件名会被推导为 `subpage.html`。
subpage: 'src/subpage/main.js'
}
}
三、create-react-app 配置
1、初始化
创建一个名为 ts-react 的 typescript 项目
- npx:
npx create-react-app ts-react --template typescript
2、tsconfig.json解读
通常 tsconfig.json 文件主要包含两部分内容:指定待编译文件和定义编译选项。compilerOptions 属性作用是配置编译选项。
{
"compilerOptions": {
"target": "es5", // 目标语言的版本
"lib": [
"dom",
"dom.iterable",
"esnext"
], // TS需要引用的库,即声明文件
"allowJs": true, // 允许编译器编译JS,JSX文件
"skipLibCheck": true, // 忽略所有的声明文件(*.d.ts)的类型检查
"esModuleInterop": true, // 允许export=导出,由import from 导入
"allowSyntheticDefaultImports": true, // 允许从没有设置默认导出的模块中默认导入
"strict": true,
"forceConsistentCasingInFileNames": true, // 禁止对同一个文件的不一致的引用
"noFallthroughCasesInSwitch": true, // 防止switch语句贯穿(即无break语句后面不会执行)
"module": "esnext", // 指定生成代码的模板标准
"moduleResolution": "node", // 使用哪种模块解析策略
"resolveJsonModule": true, // 是否可以导入 JSON 模块
"isolatedModules": true, // 将每个文件作为单独的模块
"noEmit": true, // 不生成输出文件
"jsx": "react-jsx" // 在 .tsx文件里支持JSX: "React"或 "Preserve"
},
"include": [
"src"
]
}
3、自定义配置
弹出cra配置,仅能弹出一次:npm run eject
4、react-scripts
- cra项目中的开发依赖项。可运行内置命令行
5、代码规范、Git工作流/提交规范
- 代码格式化工具:prettier
- 安装prettier:
yarn add prettier -D
- 配置.prettierrc ```json { “trailingComma”: “es5”, // 在任何可能的多行中,添加es5中被支持的尾逗号,默认none “tabWidth”: 4, // 水平缩进的空格数,默认为 2 “singleQuote”: true, // 是否使用单引号 “jsxBracketSameLine”: false, // 是否多属性html标签的‘>’折行放置 “printWidth”: 100, // 指定代码换行的行长度,超过最大值换行 }
- 安装prettier:
- 代码规范校验工具:**eslint**
- Git工作流规范:
- **husky**:git hooks工具
- 安装:`yarn add husky -D`
- 配置:在package.json 文件的scripts配置项添加命令
```json
"scripts": {
"prepare": "husky install"
}
- 执行:`yarn prepare`,创建.husky/目录并指定该目录为git hooks所在的目录
lint-staged : pre-commit Hook 脚本,允许我们在 git 中的暂存文件上运行脚本
- 安装:
yarn add lint-staged -D
- 配置:
"lint-staged": {
"src/**/*.{js,jsx,ts,tsx,json}": [
"prettier --write",
"eslint",
"git add"
]
}
- 安装:
pretty-quick
- 安装:
yarn add pretty-quick -D
- 安装:
commitlint : commit-msg Hook脚本,帮助我们在多人开发时,遵守 git 提交约定
- 安装:
yarn add @commitlint/cli @commitlint/config-conventional -D
- 配置:在根目录src目录下创建 commitlint.config.js 文件
module.exports = {
extends: [
"@commitlint/config-conventional"
],
// 自定义规则,可不填写
rules: {
'type-enum': [
2,
'always',
[
'bug', // 此项特别针对bug号,用于向测试反馈bug列表的bug修改情况
'feat', // 新功能(feature)
'fix', // 修补bug
'docs', // 文档(documentation)
'style', // 格式(不影响代码运行的变动)
'refactor', // 重构(即不是新增功能,也不是修改bug的代码变动)
'test', // 增加测试
'chore', // 构建过程或辅助工具的变动
'revert', // 撤销之前的commit
'merge' // 合并分支
]
]
}
};
- 安装:
添加钩子: 首先,运行
yarn prepare
- commit-msg :
npx husky add .husky/commit-msg "yarn commitlint --edit '$1'"
- pre-commit: 二选一
npx husky add .husky/pre-commit "yarn lint-staged --allow-empty '$1'"
npx husky add .husky/pre-commit "yarn pretty-quick --staged"
- commit-msg :
- 添加钩子到git中去:
- 添加 commit-msg 到git中去:
git add .husky/commit-msg
- 添加 pre-commit 到git中去:
git add .husky/pre-commit
- Git提交规范:commitizen
- 添加 commit-msg 到git中去:
- 安装:
yarn add commitizen cz-conventional-changelog -D
- 配置:在package.json中加入以下代码。其中,需要增加一个script,使得我们可以通过执行npm run cm来代替git commit,而path为cz-conventional-changelog包相对于项目根目录的路径
{
"scripts": {
"commit": "git-cz",
},
"config": {
"commitizen": {
"path": "node_modules/cz-conventional-changelog"
}
}
}
自动化版本控制:standard-version 升级版本号、生成 changelog 及 tag
要告知开发服务器在开发中,将任何未知请求代理到您的 API 服务器,在 package.json 中添加一个代理字段:"proxy": "http://localhost:4000"
7、source-map-explorer 分析包大小
- 安装:
yarn add source-map-explorer
- package.json配置加上脚本: ```json “scripts”: {
“analyze”: “source-map-explorer ‘build/static/js/*.js’”, “start”: “react-scripts start”, “build”: “react-scripts build”, “test”: “react-scripts test” }
- 执行:
```powershell
npm run build
npm run analyze
- 不安装:
npx source-map-explorer build/static/js/*.js