其他章节请看:

vue 快速入门 系列

Vue CLI 4.x 上

vue loader 一文中我们已经学会从零搭建一个简单的,用于单文件组件开发的脚手架;本篇,我们将全面学习 vue-cli 这个官方的、成熟的脚手架。

分上下两篇进行,上篇主要是”基础“,下篇主要是“开发”

Tip:介绍顺序尽可能保持与官方文档一致

介绍

vue-cli 是一个基于 vue.js 进行快速开发的完整系统

让我们专注在撰写应用上,而不必花好几天去纠结配置的问题。

Vue CLI 有几个独立的部分:clicli 服务cli 插件

CLI

CLI (@vue/cli) 是一个全局安装的 npm 包,提供了终端里的 vue 命令。

可以通过 vue create(下文将会详细介绍) 快速搭建一个新项目。

CLI 服务

CLI 服务 (@vue/cli-service) 是一个开发环境依赖。它是一个 npm 包,局部安装在每个 @vue/cli 创建的项目中。

CLI 服务是构建于 webpackwebpack-dev-server 之上的。它包含了:

  • 加载其它 CLI 插件的核心服务;
  • 一个针对绝大部分应用优化过的内部的 webpack 配置;
  • 项目内部的 vue-cli-service 命令,提供 servebuildinspect 命令。

CLI 插件

CLI 插件是向你的 Vue 项目提供可选功能的 npm 包,例如 Babel/TypeScript 转译、ESLint 集成、单元测试和 end-to-end 测试等。Vue CLI 插件的名字以 @vue/cli-plugin- (内建插件) 或 vue-cli-plugin- (社区插件) 开头,非常容易使用。

当你在项目内部运行 vue-cli-service 命令时,它会自动解析并加载 package.json 中列出的所有 CLI 插件。

插件可以作为项目创建过程的一部分,或在后期加入到项目中,也可以被归成一组可复用的预设(preset)。

安装

全局安装 @vue/cli 这个包:

  1. > npm install -g @vue/cli

你可以通过简单运行 vue,看看是否展示出了一份所有可用命令的帮助信息,来验证它是否安装成功。你还可以用这个命令来检查其版本是否正确。请看示例:

  1. // 验证是否安装成功
  2. > vue
  3. Usage: vue <command> [options]
  4. Options:
  5. -h, --help output usage information
  6. ...
  1. // 查看版本
  2. > vue --version
  3. @vue/cli 4.5.13

升级

如需升级全局的 Vue CLI 包,请运行:

  1. npm update -g @vue/cli

若需升级项目中的 Vue CLI 相关模块(以 @vue/cli-plugin-vue-cli-plugin- 开头),请在项目目录下运行 vue upgrade

  1. 用法: upgrade [options] [plugin-name]
  2. (试用)升级 Vue CLI 服务及插件
  3. 选项:
  4. -t, --to <version> 升级 <plugin-name> 到指定的版本
  5. -f, --from <version> 跳过本地版本检测,默认插件是从此处指定的版本升级上来
  6. -r, --registry <url> 使用指定的 registry 地址安装依赖
  7. --all 升级所有的插件
  8. --next 检查插件新版本时,包括 alpha/beta/rc 版本在内
  9. -h, --help 输出帮助内容

基础

快速原型开发

你可以使用 vue servevue build 命令对单个 *.vue 文件进行快速原型开发,不过这需要先额外安装一个全局的扩展:

  1. > npm install -g @vue/cli-service-global

vue serve 的缺点就是它需要安装全局依赖,这使得它在不同机器上的一致性不能得到保证。因此这只适用于快速原型开发。

vue serve

你所需要的仅仅是一个 App.vue 文件。

请看示例:

创建目录 demo,新建 App.vue 文件:

  1. // demo/App.vue
  2. <template>
  3. <h1>Hello!</h1>
  4. </template>

然后在这个 App.vue 文件所在的目录下运行:

  1. demo> vue serve
  2. App running at:
  3. - Local: http://localhost:8080/
  4. - Network: http://192.168.0.103:8080/

访问 http://localhost:8080/,页面显示 Hello,并有热模块替换功能。

vue serve 使用了和 vue create 创建的项目相同的默认设置 (webpack、Babel、PostCSS 和 ESLint)。它会在当前目录自动推导入口文件——入口可以是 main.js、index.js、App.vue 或 app.vue 中的一个。

:在此项目中写 less 提示需要 css-loader,编写的 postcss 也未生效 color: lch(53 105 40);—— lch 是明天的 css 语法。

vue build

你也可以使用 vue build 将目标文件构建成一个生产环境的包并用来部署:

  1. demo> vue build
  2. / Building for production...
  3. File Size Gzipped
  4. dist\js\chunk-vendors.86166fc4.js 65.95 KiB 23.71 KiB
  5. dist\js\app.6d4e2596.js 1.79 KiB 0.89 KiB

dist 目录中会生成 index.html,笔者在 dist 目录下运行静态文件服务器,在打开的页面中能看到 Hello!

  1. demo> cd dist
  2. dist> anywhere
  3. Running at http://192.168.85.1:8000/
  4. Also running at https://192.168.85.1:8001/

vue build 也提供了将组件构建成为一个库或一个 Web Components 组件的能力

创建一个项目

运行以下命令来创建一个新项目:

  1. > vue create vue-hello-world

提示选取一个预设(preset)。

  1. Vue CLI v4.5.13
  2. ? Please pick a preset:
  3. Default ([Vue 2] babel, eslint) // 默认选项 vue2
  4. Default (Vue 3) ([Vue 3] babel, eslint) // 默认选项 vue3
  5. > Manually select features // 手动选择

Tip:笔者使用 powershell 终端,可以通过上下键来切换选项

默认的设置非常适合快速创建一个新项目的原型,而手动设置则提供了更多的选项,它们是面向生产的项目更加需要的。

如果选择 default 则会直接创建项目,创建项目包括 babel,eslin 这些工具,而 vue-router,vuex等其他依赖需要自己手动安装。

由于我们的项目需要 vue-router、vuex,所以就选择“手动选择”。

  1. Vue CLI v4.5.13
  2. ? Please pick a preset: Manually select features
  3. ? Check the features needed for your project:
  4. (*) Choose Vue version // vue 的版本
  5. (*) Babel // 代码编译
  6. (*) TypeScript // ts
  7. (*) Progressive Web App (PWA) Support // 渐进式网页应用程序
  8. (*) Router // 路由 - vue router
  9. (*) Vuex // 状态管理 - vuex
  10. (*) CSS Pre-processors // css预处理
  11. (*) Linter / Formatter // 代码风格、格式校验
  12. (*) Unit Testing // 单元测试
  13. >(*) E2E Testing // 端对端测试

Tip:这里为了演示,所以选择全部(笔者使用空格键来选中或取消)

全部选中后,回车,会依次询问我们对应特性的一些具体需求,比如 vue 的版本、是否使用class风格的组件语法、路由是否使用 history 模式等等:

  1. Vue CLI v4.5.13
  2. ? Please pick a preset: Manually select features
  3. ? Check the features needed for your project: Choose Vue version, Babel, TS, PWA, Router, Vuex, CSS Pre-processors, Linter, Unit, E2E
  4. ? Choose a version of Vue.js that you want to start the project with (Use arrow keys)
  5. > 2.x
  6. 3.x

选择 vue 2,回车:

  1. Vue CLI v4.5.13
  2. ? Please pick a preset: Manually select features
  3. ? Check the features needed for your project: Choose Vue version, Babel, TS, PWA, Router, Vuex, CSS Pre-processors, Linter, Unit, E2E
  4. ? Choose a version of Vue.js that you want to start the project with 2.x
  5. ? Use class-style component syntax? (Y/n)

这里询问的是是否使用class风格的组件语法,如果在项目中想要保持使用TypeScript的class风格的话,建议大家选择 y:

  1. ...
  2. ? Choose a version of Vue.js that you want to start the project with 2.x
  3. ? Use class-style component syntax? Yes
  4. ? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? (Y/n)

将 Babel 与 TypeScript 一起使用,选择 y:

  1. ...
  2. ? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes
  3. ? Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n)

路由是否使用 history 模式。因为 history 需要额外配置,所以这里选用 hash,输入n:

  1. // CSS Pre-processors
  2. ...
  3. ? Use history mode for router? (Requires proper server setup for index fallback in production) No
  4. ? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): (Use arrow keys)
  5. > Sass/SCSS (with dart-sass)
  6. Sass/SCSS (with node-sass)
  7. Less
  8. Stylus

选择一种CSS预处理类型,笔者选用 less:

  1. // Linter / Formatter
  2. ...
  3. ? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Less
  4. ? Pick a linter / formatter config: (Use arrow keys)
  5. > ESLint with error prevention only // 只进行报错提醒
  6. ESLint + Airbnb config // airbnb 模式
  7. ESLint + Standard config // 标准模式
  8. ESLint + Prettier // prettier 模式
  9. TSLint (deprecated) // 已弃用

选择 eslint 模式,笔者选标准模式:

  1. ...
  2. ? Pick a linter / formatter config: Standard
  3. ? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection)
  4. >(*) Lint on save
  5. ( ) Lint and fix on commit

选择校验时机,一般都会选择保存时校验,好及时做出调整,笔者选第一项:

  1. // Unit Testing
  2. ...
  3. ? Pick additional lint features: Lint on save
  4. ? Pick a unit testing solution: (Use arrow keys)
  5. > Mocha + Chai
  6. Jes

选择单元测试解决方案,普遍用到最多的时Mocha + chai,我们也选第一项。

  1. // E2E Testing E2E(End To End)
  2. ...
  3. ? Pick a unit testing solution: Mocha
  4. ? Pick an E2E testing solution: (Use arrow keys)
  5. > Cypress (Chrome only)
  6. Nightwatch (WebDriver-based)
  7. WebdriverIO (WebDriver/DevTools based)

选择端对端测试的类型,默认回车:

  1. // 额外选项
  2. ...
  3. ? Pick an E2E testing solution: Cypress
  4. ? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys)
  5. > In dedicated config files // 在专用配置文件中
  6. In package.json

选择 Babel, ESLint 等配置存放位置,建议使用第一个(专用配置文件)

Tip: 如果选用第一项,例如 eslint 的配置就会单独存放在一个文件(.eslintrc.js)中;如果选第二项,该配置就会存放在 package.josn 中,而 package.json 是不能写注释,而且太多配置都写入 package.json 也不好维护

  1. ? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
  2. ? Save this as a preset for future projects? (y/N)

是否保存成一个预设给以后项目使用。这里选 y,然后输入存储当前配置项的名称,例如 presetNameA

  1. ? Save this as a preset for future projects? Yes
  2. ? Save preset as:

随后就会创建完毕,并提示通过 npm run serve 启动服务:

  1. ...
  2. Generating README.md...
  3. Successfully created project vue-hello-world.
  4. Get started with the following commands:
  5. $ cd vue-hello-world
  6. $ npm run serve
  1. > npm run serve
  2. ...
  3. Time: 3055ms
  4. App running at:
  5. - Local: http://localhost:8080/
  6. - Network: http://192.168.0.103:8080/

通过浏览器访问 http://localhost:8080/ 即可访问项目。

Tip:下次创建项目的时候就会看到刚保存的预设(presetNameA):

  1. > vue create demo
  2. Vue CLI v4.5.13
  3. ? Please pick a preset: (Use arrow keys)
  4. > presetNameA ([Vue 2] less, babel, typescript, pwa, router, vuex, eslint, unit-mocha, e2e-cypress)
  5. Default ([Vue 2] babel, eslint)
  6. Default (Vue 3) ([Vue 3] babel, eslint)
  7. Manually select features

插件

Vue CLI 使用了一套基于插件的架构。如果你查阅一个新创建项目的 package.json,就会发现依赖都是以 @vue/cli-plugin- 开头的:

  1. // vue-hello-world/package.json
  2. {
  3. "name": "vue-hello-world",
  4. "version": "0.1.0",
  5. "private": true,
  6. "scripts": {
  7. "serve": "vue-cli-service serve",
  8. "build": "vue-cli-service build",
  9. "test:unit": "vue-cli-service test:unit",
  10. "test:e2e": "vue-cli-service test:e2e",
  11. "lint": "vue-cli-service lint"
  12. },
  13. "dependencies": {
  14. "core-js": "^3.6.5",
  15. "register-service-worker": "^1.7.1",
  16. "vue": "^2.6.11",
  17. "vue-class-component": "^7.2.3",
  18. "vue-property-decorator": "^9.1.2",
  19. "vue-router": "^3.2.0",
  20. "vuex": "^3.4.0"
  21. },
  22. "devDependencies": {
  23. "@types/chai": "^4.2.11",
  24. "@types/mocha": "^5.2.4",
  25. "@typescript-eslint/eslint-plugin": "^4.18.0",
  26. "@typescript-eslint/parser": "^4.18.0",
  27. "@vue/cli-plugin-babel": "~4.5.0",
  28. "@vue/cli-plugin-e2e-cypress": "~4.5.0",
  29. "@vue/cli-plugin-eslint": "~4.5.0",
  30. "@vue/cli-plugin-pwa": "~4.5.0",
  31. "@vue/cli-plugin-router": "~4.5.0",
  32. "@vue/cli-plugin-typescript": "~4.5.0",
  33. "@vue/cli-plugin-unit-mocha": "~4.5.0",
  34. "@vue/cli-plugin-vuex": "~4.5.0",
  35. "@vue/cli-service": "~4.5.0",
  36. "@vue/eslint-config-standard": "^5.1.2",
  37. "@vue/eslint-config-typescript": "^7.0.0",
  38. "@vue/test-utils": "^1.0.3",
  39. "chai": "^4.1.2",
  40. "eslint": "^6.7.2",
  41. "eslint-plugin-import": "^2.20.2",
  42. "eslint-plugin-node": "^11.1.0",
  43. "eslint-plugin-promise": "^4.2.1",
  44. "eslint-plugin-standard": "^4.0.0",
  45. "eslint-plugin-vue": "^6.2.2",
  46. "less": "^3.0.4",
  47. "less-loader": "^5.0.0",
  48. "typescript": "~4.1.5",
  49. "vue-template-compiler": "^2.6.11"
  50. }
  51. }

插件可以修改 webpack 的内部配置,也可以向 vue-cli-service 注入命令。在项目创建的过程中,绝大部分列出的特性都是通过插件来实现的。

基于插件的架构使得 Vue CLI 灵活且可扩展。

下面我们将通过一个示例来讲解插件,首先新建项目 demo2(选择 Default):

  1. // 选则`Default ([Vue 2] babel, eslint)`默认创建
  2. > vue create demo2

Tip: 前面创建的项目(vue-hello-world)是基于 typescript,演示起来不是很方便

vue add

每个 CLI 插件都会包含一个 (用来创建文件的) 生成器和一个 (用来调整 webpack 核心配置和注入命令的) 运行时插件。当你使用 vue create 来创建一个新项目的时候,有些插件会根据你选择的特性被预安装好。如果你想在一个已经被创建好的项目中安装一个插件,可以使用 vue add 命令,例如 vue add axios

Tipvue add 的设计意图是为了安装和调用 Vue CLI 插件。这不意味着替换掉普通的 npm 包。对于这些普通的 npm 包,你仍然需要选用包管理器。

下面我们通过安装 axios 来详细了解一下vue add 插件npm install 包之间的区别:

  1. > npm i axios

安装完成,项目中只有 package.json 会增加相应的依赖:

  1. "dependencies": {
  2. + "axios": "^0.21.1",
  3. "core-js": "^3.6.5",
  4. "vue": "^2.6.11"
  5. },

将 axios 这个包删除,再次用 vue add 安装 axios 插件:

  1. // 删除
  2. > npm r axios
  1. > vue add axios
  2. WARN There are uncommitted changes in the current repository, it's recommended to commit or stash them first.
  3. ? Still proceed?

Tip: 由于会更改文件,所以会让你先提交代码

  1. > vue add axios
  2. Installing vue-cli-plugin-axios...
  3. ...
  4. Run `npm audit` for details.
  5. Successfully installed plugin: vue-cli-plugin-axios

告诉我们正在安装的包是:vue-cli-plugin-axios

安装完成,通过 git status 就能知道此命令修改的文件和内容:

  1. demo2> git status
  2. On branch master
  3. Changes not staged for commit:
  4. (use "git add <file>..." to update what will be committed)
  5. (use "git restore <file>..." to discard changes in working directory)
  6. modified: package-lock.json
  7. modified: package.json
  8. modified: src/main.js
  9. Untracked files:
  10. (use "git add <file>..." to include in what will be committed)
  11. src/plugins/
  1. // package.json
  2. "devDependencies": {
  3. "axios": "^0.18.0",
  4. "vue-cli-plugin-axios": "~0.0.4",
  5. },
  1. // main.js
  2. import './plugins/axios'
  1. // src/plugins/axios.js
  2. "use strict";
  3. import Vue from 'vue';
  4. import axios from "axios";
  5. // Full config: https://github.com/axios/axios#request-config
  6. // axios.defaults.baseURL = process.env.baseURL || process.env.apiUrl || '';
  7. // axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
  8. // axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
  9. let config = {
  10. // baseURL: process.env.baseURL || process.env.apiUrl || ""
  11. // timeout: 60 * 1000, // Timeout
  12. // withCredentials: true, // Check cross-site Access-Control
  13. };
  14. const _axios = axios.create(config);
  15. _axios.interceptors.request.use(
  16. function(config) {
  17. // Do something before request is sent
  18. return config;
  19. },
  20. function(error) {
  21. // Do something with request error
  22. return Promise.reject(error);
  23. }
  24. );
  25. // Add a response interceptor
  26. _axios.interceptors.response.use(
  27. function(response) {
  28. // Do something with response data
  29. return response;
  30. },
  31. function(error) {
  32. // Do something with response error
  33. return Promise.reject(error);
  34. }
  35. );
  36. Plugin.install = function(Vue, options) {
  37. Vue.axios = _axios;
  38. window.axios = _axios;
  39. Object.defineProperties(Vue.prototype, {
  40. axios: {
  41. get() {
  42. return _axios;
  43. }
  44. },
  45. $axios: {
  46. get() {
  47. return _axios;
  48. }
  49. },
  50. });
  51. };
  52. Vue.use(Plugin)
  53. export default Plugin;

接着启动服务,eslint 报错,于是修改 eslint 配置绕过代码校验,再次重启服务。

  1. // package.json
  2. "extends": [
  3. "plugin:vue/essential",
  4. - "eslint:recommended"
  5. ],

在任意组件中即可使用 axios,例如在 App.vue 中使用:

  1. <script>
  2. export default {}
  3. console.log(window.axios);
  4. </script>

浏览器控制台会输出:

  1. ƒ wrap() {
  2. var args = new Array(arguments.length);
  3. for (var i = 0; i < args.length; i++) {
  4. args[i] = arguments[i];
  5. }
  6. return fn.apply(thisArg, args);
  7. }

至此,axios 已经成功引入我们的项目,而且范文也已经就绪。

通过这个示例我们也就明白,vue 提供的这个插件比 npm 这种方式更友好,比如有范文

vue add vuex
  1. > vue add vuex
  2. Installing @vue/cli-plugin-vuex...
  3. ...

安装 axios 对应的包是 vue-cli-plugin-axios,以 vue-cli-plugin- 开头,属于第三方插件

而 vuex 对应的包是 @vue/cli-plugin-vuex,以 @vue/cli-plugin- 开头。

使用 GUI 安装和管理插件

我们通过 vue ui 命令使用 GUI 安装和管理插件。由于前面我们已经全局安装,所以在任意目录下运行即可:

  1. > vue ui
  2. Starting GUI...
  3. Ready on http://localhost:8001

浏览器自动打开页面,并来到Vue 项目管理器系统,导入项目(例如 vue-hello-world),你会可以看见如下几个菜单:

  • 插件,会显示已安装的插件,以及通过添加插件就可以查找插件,在查找插件的页面,我们知道:

    • 没有 jquery 对应的插件
    • axios 对应的插件,将鼠标移到添加插件的图标上会显示:这个插件带有一个生成器,可以在项目中修改或增加文件
  • 依赖,能清晰的知道运行依赖有哪些(例如 vue),开发依赖有哪些(例如 eslint
  • 配置,里面有配置 Vue 项目代码质量和纠错
  • 任务,包括项目中 package.json 中 scripts 对应的任务(servebuildlint等)。还有 inspect,能检查 webpack 配置,比如查看项目对应开发环境和生成环境的 webpack 配置。

Preset

一个 Vue CLI preset 是一个包含创建新项目所需预定义选项和插件的 JSON 对象,让用户无需在命令提示中选择它们。

vue create 过程中保存的 preset 会被放在你的 home 目录下的一个配置文件中 (~/.vuerc)。你可以通过直接编辑这个文件来调整、添加、删除保存好的 preset。

笔者预设如下:

  1. > cat ~/.vuerc
  2. {
  3. "useTaobaoRegistry": false,
  4. "latestVersion": "4.5.13",
  5. "lastChecked": 1622962273301,
  6. "presets": {
  7. "presetNameA": {
  8. "useConfigFiles": true,
  9. "plugins": {
  10. "@vue/cli-plugin-babel": {},
  11. "@vue/cli-plugin-typescript": {
  12. "classComponent": true,
  13. "useTsWithBabel": true
  14. },
  15. "@vue/cli-plugin-pwa": {},
  16. "@vue/cli-plugin-router": {
  17. "historyMode": false
  18. },
  19. "@vue/cli-plugin-vuex": {},
  20. "@vue/cli-plugin-eslint": {
  21. "config": "standard",
  22. "lintOn": [
  23. "save"
  24. ]
  25. },
  26. "@vue/cli-plugin-unit-mocha": {},
  27. "@vue/cli-plugin-e2e-cypress": {}
  28. },
  29. "vueVersion": "2",
  30. "cssPreprocessor": "less"
  31. }
  32. }
  33. }

Preset 的数据会被插件生成器用来生成相应的项目文件。除了上述这些字段,你也可以为集成工具添加配置:

  1. {
  2. "useConfigFiles": true,
  3. "plugins": {...},
  4. "configs": {
  5. "vue": {...},
  6. "postcss": {...},
  7. "eslintConfig": {...},
  8. "jest": {...}
  9. }
  10. }

这些额外的配置将会根据 useConfigFiles 的值被合并到 package.json 或相应的配置文件中。例如,当 "useConfigFiles": true 的时候,configs 的值将会被合并到 vue.config.js 中。

你可以显式地指定用到的插件的版本:

  1. {
  2. "plugins": {
  3. "@vue/cli-plugin-eslint": {
  4. "version": "^3.0.0",
  5. // ... 该插件的其它选项
  6. }
  7. }
  8. }

注意对于官方插件来说这不是必须的——当被忽略时,CLI 会自动使用 registry 中最新的版本。不过推荐为 preset 列出的所有第三方插件提供显式的版本范围。

CLI 服务

使用命令

在一个 Vue CLI 项目中,@vue/cli-service 安装了一个名为 vue-cli-service 的命令。你可以在 npm scripts 中以 vue-cli-service、或者从终端中以 ./node_modules/.bin/vue-cli-service 访问这个命令。

上文我们创建的项目 demo2 的 package.json 中的命令有:

  1. {
  2. "scripts": {
  3. "serve": "vue-cli-service serve",
  4. "build": "vue-cli-service build",
  5. "lint": "vue-cli-service lint"
  6. }
  7. }

可以通过 npmnpx(最新版的 npm 应该已经自带) 执行命令:

  1. > npm run serve
  1. > npx vue-cli-service serve

Tip: 可以通过 vue ui 命令使用 GUI 运行更多的特性脚本

vue-cli-service serve
  1. 用法:vue-cli-service serve [options] [entry]
  2. 选项:
  3. --open 在服务器启动时打开浏览器
  4. --copy 在服务器启动时将 URL 复制到剪切版
  5. --mode 指定环境模式 (默认值:development)
  6. --host 指定 host (默认值:0.0.0.0)
  7. --port 指定 port (默认值:8080)
  8. --https 使用 https (默认值:false)

vue-cli-service serve 命令会启动一个开发服务器 (基于 webpack-dev-server) 并附带开箱即用的模块热重载 (Hot-Module-Replacement)。

除了通过命令行参数,你也可以使用 vue.config.js 里的 devServer 字段配置开发服务器

命令行参数 [entry] 将被指定为唯一入口,而非额外的追加入口。尝试使用 [entry] 覆盖 config.pages 中的 entry 将可能引发错误。

  1. // 在服务器启动时打开浏览器
  2. demo2> npx vue-cli-service serve --open
  3. // 或者指定 entry
  4. demo2> npx vue-cli-service serve --open ./src/main.js

Tip:终端可能因为 eslint 报错而终止编译,可以更改 eslint 配置。在项目根目录下新建 vue.config.js,重启服务即可。

  1. // vue.config.js
  2. module.exports = {
  3. lintOnSave: true
  4. }
vue-cli-service build
  1. 用法:vue-cli-service build [options] [entry|pattern]
  2. 选项:
  3. --mode 指定环境模式 (默认值:production)
  4. --dest 指定输出目录 (默认值:dist)
  5. --modern 面向现代浏览器带自动回退地构建应用
  6. --target app | lib | wc | wc-async (默认值:app)
  7. --name 库或 Web Components 模式下的名字 (默认值:package.json 中的 "name" 字段或入口文件名)
  8. --no-clean 在构建项目之前不清除目标目录
  9. --report 生成 report.html 以帮助分析包内容
  10. --report-json 生成 report.json 以帮助分析包内容
  11. --watch 监听文件变化

vue-cli-service build 会在 dist/ 目录产生一个可用于生产环境的包,带有 JS/CSS/HTML 的压缩,和为更好的缓存而做的自动的 vendor chunk splitting。它的 chunk manifest 会内联在 HTML 里。

这里还有一些有用的命令参数:

  • --modern 使用现代模式构建应用,为现代浏览器交付原生支持的 ES2015 代码,并生成一个兼容老浏览器的包用来自动回退。
  1. // 打包生成了两份:现代包和遗留包
  2. demo2> npx vue-cli-service build --modern
  3. // 为生产构建遗留包...
  4. / Building legacy bundle for production...
  5. File Size Gzipped
  6. dist\js\chunk-vendors-legacy.7b12297e.js 117.56 KiB 40.92 KiB
  7. dist\js\app-legacy.853ea99d.js 5.15 KiB 1.84 KiB
  8. dist\css\app.fb0c6e1c.css 0.33 KiB 0.23 KiB
  9. // 省略了图像和其他类型的资产
  10. Images and other types of assets omitted.
  11. // 为生产构建现代捆绑...
  12. - Building modern bundle for production...
  13. File Size Gzipped
  14. dist\js\chunk-vendors.1e2bb21b.js 92.78 KiB 32.14 KiB
  15. dist\js\app.d739a095.js 5.07 KiB 1.81 KiB
  16. dist\css\app.fb0c6e1c.css 0.33 KiB 0.23 KiB
  17. // 省略了图像和其他类型的资产
  18. Images and other types of assets omitted.
  • --target 允许你将项目中的任何组件以一个库或 Web Components 组件的方式进行构建。

  • --report--report-json 会根据构建统计生成报告,它会帮助你分析包中包含的模块们的大小。

  1. demo2> npx vue-cli-service build --report
  2. | Building for production...
  3. File Size Gzipped
  4. dist\js\chunk-vendors.7b12297e.js 117.55 KiB 40.92 KiB
  5. dist\js\app.853ea99d.js 5.14 KiB 1.83 KiB
  6. dist\css\app.fb0c6e1c.css 0.33 KiB 0.23 KiB
  7. Images and other types of assets omitted.

会在 dist 目录中生成 report.html

Tip: 如果你使用的是 vscode,只需要安装 Live Server 插件,即可右键通过 live server 查看 report.html,非常方便。

如果是 --report,则不会生成 report.html,而会生成 report.json

vue-cli-service inspect
  1. 用法:vue-cli-service inspect [options] [...paths]
  2. 选项:
  3. --mode 指定环境模式 (默认值:development)

审查一个 Vue CLI 项目的 webpack config。请看示例:

  1. // 提取出webpack开发配置,导出到 webpack.config.development.js 中
  2. demo2> npx vue-cli-service inspect --mode development >> webpack.config.development.js
  3. // 提取出webpack生成配置
  4. demo2> npx vue-cli-service inspect --mode production >> webpack.config.production.js

:接下来我们学习过程中会参考这两个配置文件

查看所有的可用命令

有些 CLI 插件会向 vue-cli-service 注入额外的命令。例如 @vue/cli-plugin-eslint 会注入 vue-cli-service lint 命令。你可以运行以下命令查看所有注入的命令:

  1. demo2> npx vue-cli-service help
  2. Usage: vue-cli-service <command> [options]
  3. Commands:
  4. serve start development server
  5. build build for production
  6. inspect inspect internal webpack config
  7. lint lint and fix source files
  8. run vue-cli-service help [command] for usage of a specific command.

也可以这样学习每个命令可用的选项:

  1. npx vue-cli-service help [command]
缓存和并行处理
  • cache-loader 会默认为 Vue/Babel/TypeScript 编译开启。文件会缓存在 node_modules/.cache 中——如果你遇到了编译方面的问题,记得先删掉缓存目录之后再试试看。
  1. // demo2 中的缓存文件:
  2. demo2> dir .\node_modules\.cache\
  3. Mode LastWriteTime Length Name
  4. ---- ------------- ------ ----
  5. d----- 2021/8/11 11:30 babel-loader
  6. d----- 2021/8/11 11:30 eslint-loader
  7. d----- 2021/7/19 19:31 terser-webpack-plugin
  8. d----- 2021/8/11 11:30 vue-loader
  • thread-loader 会在多核 CPU 的机器上为 Babel/TypeScript 转译开启。

Tip:虽然 package.json 中没有 cache-loaderthread-loader,但 demo2/node_modules 中有。

Git Hook

在安装之后,@vue/cli-service 也会安装 yorkie,它会让你在 package.json 的 gitHooks 字段中方便地指定 Git hook:

  1. {
  2. "gitHooks": {
  3. "pre-commit": "lint-staged"
  4. },
  5. "lint-staged": {
  6. "*.{js,vue}": [
  7. "vue-cli-service lint",
  8. "git add"
  9. ]
  10. }
  11. }

Tip:yorkie,fork 项目 husky,并做了一些改变,比如更改了从 package.json 中读取钩子的位置:

  1. // before
  2. {
  3. "scripts": {
  4. "precommit": "foo"
  5. }
  6. }
  1. // after
  2. {
  3. "gitHooks": {
  4. "pre-commit": "foo"
  5. }
  6. }

具体用法,请看示例(在demo2基础上进行):

  1. // package.json
  2. {
  3. ...
  4. "gitHooks": {
  5. "pre-commit": "lint-staged"
  6. },
  7. "lint-staged": {
  8. "*.{js,vue}": [
  9. "vue-cli-service lint",
  10. "git add"
  11. ]
  12. }
  13. }

执行 git commit 命令报错:

  1. demo2> git commit -m 'xx'
  2. On branch master
  3. (use "git add <file>..." to include in what will be committed)
  4. src/a.js
  5. 'lint-staged' 不是内部或外部命令,也不是可运行的程序
  6. 或批处理文件。
  7. pre-commit hook failed (add --no-verify to bypass)

安装依赖包:

  1. // lint-staged - 对暂存的 git 文件运行 linter,不要让不好的代码溜进你的代码库!
  2. demo2> npm i -D lint-staged

接下来给 eslint 增加一个规则,然后在 a.js 中故意不遵守该规则:

  1. // package.json
  2. {
  3. "eslintConfig": {
  4. "rules": {
  5. "no-console": "error"
  6. }
  7. },
  8. }
  1. // src/a.js
  2. let i = 1
  3. console.log(i);

执行git commit命令,验证不通过,终止提交:

  1. // 需要先 git add
  2. demo2> git add src/a.js
  3. demo2> git commit -m 'xx'
  4. > running pre-commit hook: lint-staged
  5. Some of your tasks use `git add` command. Please remove it from the config since all modifications made by tasks will be
  6. automatically added to the git commit index.
  7. [STARTED] Preparing...
  8. [SUCCESS] Preparing...
  9. [STARTED] Running tasks...
  10. [STARTED] Running tasks for *.{js,vue}
  11. [STARTED] vue-cli-service lint
  12. [FAILED] vue-cli-service lint [FAILED]
  13. [FAILED] vue-cli-service lint [FAILED]
  14. [SUCCESS] Running tasks...
  15. [STARTED] Applying modifications...
  16. [SKIPPED] Skipped because of errors from tasks.
  17. [STARTED] Reverting to original state because of errors...
  18. [SUCCESS] Reverting to original state because of errors...
  19. [STARTED] Cleaning up...
  20. [SUCCESS] Cleaning up...
  21. vue-cli-service lint:
  22. error: Unexpected console statement (no-console) at src\a.js:2:1:
  23. 1 | let i = 1
  24. > 2 | console.log(i);
  25. | ^
  26. 3 |
  27. 1 error found.
  28. pre-commit hook failed (add --no-verify to bypass)

Tip:Git 钩子,和其它版本控制系统一样,Git 能在特定的重要动作发生时触发自定义脚本。有两组这样的钩子:客户端的和服务器端的。客户端钩子由诸如提交和合并这样的操作所调用,而服务器端钩子作用于诸如接收被推送的提交这样的联网操作。你可以随心所欲地运用这些钩子。

  1. // 项目 demo2 的 git hooks
  2. demo2> dir .\.git\hooks\
  3. 目录: demo2\.git\hooks
  4. Mode LastWriteTime Length Name
  5. ---- ------------- ------ ----
  6. -a---- 2021/7/19 9:11 870 applypatch-msg
  7. -a---- 2021/7/19 9:07 478 applypatch-msg.sample
  8. -a---- 2021/7/19 9:11 854 commit-msg
  9. -a---- 2021/7/19 9:07 896 commit-msg.sample
  10. -a---- 2021/7/19 9:07 4655 fsmonitor-watchman.sample
  11. -a---- 2021/7/19 9:11 874 post-applypatch
  12. -a---- 2021/7/19 9:11 866 post-checkout
  13. -a---- 2021/7/19 9:11 858 post-commit
  14. -a---- 2021/7/19 9:11 854 post-merge
  15. -a---- 2021/7/19 9:11 862 post-receive
  16. -a---- 2021/7/19 9:11 862 post-rewrite
  17. -a---- 2021/7/19 9:11 858 post-update
  18. -a---- 2021/7/19 9:07 189 post-update.sample
  19. -a---- 2021/7/19 9:11 870 pre-applypatch
  20. -a---- 2021/7/19 9:07 424 pre-applypatch.sample
  21. -a---- 2021/7/19 9:11 858 pre-auto-gc
  22. -a---- 2021/7/19 9:11 854 pre-commit
  23. -a---- 2021/7/19 9:07 1643 pre-commit.sample
  24. -a---- 2021/7/19 9:07 416 pre-merge-commit.sample
  25. -a---- 2021/7/19 9:11 846 pre-push
  26. -a---- 2021/7/19 9:07 1348 pre-push.sample
  27. -a---- 2021/7/19 9:11 854 pre-rebase
  28. -a---- 2021/7/19 9:07 4898 pre-rebase.sample
  29. -a---- 2021/7/19 9:11 858 pre-receive
  30. -a---- 2021/7/19 9:07 544 pre-receive.sample
  31. -a---- 2021/7/19 9:11 913 prepare-commit-msg
  32. -a---- 2021/7/19 9:07 1492 prepare-commit-msg.sample
  33. -a---- 2021/7/19 9:11 878 push-to-checkout
  34. -a---- 2021/7/19 9:11 886 sendemail-validate
  35. -a---- 2021/7/19 9:11 838 update
  36. -a---- 2021/7/19 9:07 3635 update.sample
配置时无需 Eject

通过 vue create 创建的项目无需额外的配置就已经可以跑起来了。插件的设计也是可以相互共存的,所以绝大多数情况下,你只需要在交互式命令提示中选取需要的功能即可。

不过我们也知道满足每一个需求是不太可能的,而且一个项目的需求也会不断改变。通过 Vue CLI 创建的项目让你无需 eject 就能够配置工具的几乎每个角落。

其他章节请看:

vue 快速入门 系列

vue 快速入门 系列 —— vue-cli 上的更多相关文章

  1. vue 快速入门 系列 —— vue 的基础应用(上)

    其他章节请看: vue 快速入门 系列 vue 的基础应用(上) Tip: vue 的基础应用分上下两篇,上篇是基础,下篇是应用. 在初步认识 vue一文中,我们已经写了一个 vue 的 hello- ...

  2. vue 快速入门 系列 —— vue loader 上

    其他章节请看: vue 快速入门 系列 vue loader 上 通过前面"webpack 系列"的学习,我们知道如何用 webpack 实现一个不成熟的脚手架,比如提供开发环境和 ...

  3. vue 快速入门 系列 —— vue 的基础应用(下)

    其他章节请看: vue 快速入门 系列 vue 的基础应用(下) 上篇聚焦于基础知识的介绍:本篇聚焦于基础知识的应用. 递归组件 组件是可以在它们自己的模板中调用自身的.不过它们只能通过 name 选 ...

  4. vue 快速入门 系列 —— vue loader 下

    其他章节请看: vue 快速入门 系列 vue loader 下 CSS Modules CSS Modules 是一个流行的,用于模块化和组合 CSS 的系统.vue-loader 提供了与 CSS ...

  5. vue 快速入门 系列 —— vue loader 扩展

    其他章节请看: vue 快速入门 系列 vue loader 扩展 在vue loader一文中,我们学会了从零搭建一个简单的,用于单文件组件开发的脚手架.本篇将在此基础上继续引入一些常用的库:vue ...

  6. vue 快速入门 系列 —— Vue 实例的初始化过程

    其他章节请看: vue 快速入门 系列 Vue 实例的初始化过程 书接上文,每次调用 new Vue() 都会执行 Vue.prototype._init() 方法.倘若你看过 jQuery 的源码, ...

  7. vue 快速入门 系列 —— Vue(自身) 项目结构

    其他章节请看: vue 快速入门 系列 Vue(自身) 项目结构 前面我们已经陆续研究了 vue 的核心原理:数据侦测.模板和虚拟 DOM,都是偏底层的.本篇将和大家一起来看一下 vue 自身这个项目 ...

  8. vue 快速入门 系列 —— vue-cli 下

    其他章节请看: vue 快速入门 系列 Vue CLI 4.x 下 在 vue loader 一文中我们已经学会从零搭建一个简单的,用于单文件组件开发的脚手架:本篇,我们将全面学习 vue-cli 这 ...

  9. vue 快速入门 系列 —— vue-router

    其他章节请看: vue 快速入门 系列 Vue Router Vue Router 是 Vue.js 官方的路由管理器.它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌. 什么是路由 ...

随机推荐

  1. .Net RabbitMQ实战指南——服务日志

    RabbitMQ的日出输入方式有很多种:file.console .syslog .exchange. 在RabbitMQ中,日志级别有none(0).critical(4).error(8).war ...

  2. 29、Tomcat只允许指定域名访问,禁用IP地址访问,防止恶意解析

    1.1.测试环境说明: Linux版本:7.6 IP地址:10.11.220.123/24 Tomcat版本:tomcat-8.5.37(端口号为8080) Jdk版本:1.8.0_202 1.2.配 ...

  3. 27、myslq更改为不自动提交

    27.1.说明: 默认情况下, MySQL启用自动提交模式(变量autocommit为ON).这意味着, 只要你执行DML操作的语句, MySQL会立即隐式提交事务(Implicit Commit). ...

  4. Spring官方发布新成员:Spring GraphQL

    近日,在GraphQL Java诞生6周年的时候,Spring社区通过博客宣布正式创建全新项目:Spring GraphQL,同时还发布了这个新项目的里程碑1.0版本. 博客原文:https://sp ...

  5. CRM系统对企业管理的作用有多大?

    随着市场经济的发展,对任何行业的企业来说,客户都是非常重要的一个部分.CRM系统帮助企业做到以客户为中心,它可以根据客户的具体要求进行跟进和反馈,在很大程度上提高公司的客户服务水平和客户满意度,进而提 ...

  6. 用java实现斐波那契数列

    斐波那契数列源于数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入的计算问题.假设某种兔子兔子,出生第一个月变成大兔子,大兔子再过一个月能生下一对小兔子,且一年 ...

  7. 解决数据库连接池连接mysql时,每隔8小时mysql自动断开所有连接的问题

    解决数据库连接池连接mysql时,每隔8小时mysql自动断开所有连接的问题 最近有个问题非常讨厌,我们的工程中使用自己的连接池连接mysql数据库,可mysql数据库每隔8小时就会自动断开所有链接, ...

  8. robotframework安装robotframework-requests库遇到的几种问题

    robotframework-requests库依赖于requests库,所以如果安装robotframework-requests库后,在RF中的RequestsLibrary不能使用或者使用pyt ...

  9. linux学习之路第四天

    用户和用户组的配置文件

  10. echarts堆叠柱状图在最上面的柱子显示总和

    需求 柱子需设置barMinHeight 在堆叠柱状图的最上面显示当前堆叠的总和 直接上代码吧 需要注意:设置barMinHeight时为了让0不显示,只能将0设置为null; 设置为null的柱子l ...