1.介绍
CLI (@vue/cli) 是一个全局安装的 npm 包,提供了终端里的 vue 命令。它可以通过 vue create 快速创建一个新项目的脚手架,或者直接通过 vue serve 构建新想法的原型。你也可以通过 vue ui 通过一套图形化界面管理你的所有项目。
CLI 服务 (@vue/cli-service) 是一个开发环境依赖。它是一个 npm 包,局部安装在每个 @vue/cli 创建的项目中。
CLI 插件是向你的 Vue 项目提供可选功能的 npm 包
2.安装
关于旧版本
Vue CLI 的包名称由 vue-cli 改成了 @vue/cli。 如果你已经全局安装了旧版本的 vue-cli (1.x 或
2.x),你需要先通过 npm uninstall vue-cli -g 或 yarn global remove vue-cli 卸载它。
npm install -g @vue/cli
# OR
yarn global add @vue/cli
3.快速原型开发
你可以使用 vue serve 和 vue build 命令对单个 *.vue 文件进行快速原型开发,不过这需要先额外安装一个全局的扩展:
npm install -g @vue/cli-service-global
vue serve 使用了和 vue create 创建的项目相同的默认设置 (webpack、Babel、PostCSS 和 ESLint)。它会在当前目录自动推导入口文件——入口可以是 main.js、index.js、App.vue 或 app.vue 中的一个。你也可以显式地指定入口文件:
vue serve MyComponent.vue
//vue build 将目标文件构建成一个生产环境的包并用来部署:
vue build MyComponent.vue
4.创建一个项目
vue create hello-world
vue ui
拉取 2.x 模板 (旧版本)
Vue CLI >= 3 和旧版使用了相同的 vue 命令,所以 Vue CLI 2 (vue-cli) 被覆盖了。如果你仍然需要使用旧版本的 vue init 功能,你可以全局安装一个桥接工具:
npm install -g @vue/cli-init
vue init
的运行效果将会跟 vue-cli@2.x
相同
//webpack完整模板https://github.com/vuejs-templates
vue init webpack my-project
//,webpack-simple只有src目录
vue init webpack-simple my-project
5.插件和预设配置
如果一个插件名为 @foo/vue-cli-plugin-bar,你可以这样添加它:
vue add @foo/vue-cli-plugin-bar
vue add @foo/bar
vue add router
vue add vuex
如果出于一些原因你的插件列在了该项目之外的其它 package.json 文件里,你可以在自己项目的 package.json 里设置 vuePlugins.resolveFrom 选项指向包含其它 package.json 的文件夹。
例如,如果你有一个 .config/package.json 文件:
{
"vuePlugins": {
"resolveFrom": ".config"
}
}
预设配置
如果不是经常建项目这个不重要,如果需要查看->传送门
6.CLI 服务
@vue/cli-service 安装了一个名为 vue-cli-service 的命令。你可以在 npm scripts 中以 vue-cli-service、或者从终端中以 ./node_modules/.bin/vue-cli-service 访问这个命令。
{
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
}
}
如果你可以使用 npx (最新版的 npm 应该已经自带),也可以直接这样调用命令:
npx vue-cli-service serve
vue-cli-service serve
用法:vue-cli-service serve [options] [entry]
选项:
--open 在服务器启动时打开浏览器
--copy 在服务器启动时将 URL 复制到剪切版
--mode 指定环境模式 (默认值:development)
--host 指定 host (默认值:0.0.0.0)
--port 指定 port (默认值:8080)
--https 使用 https (默认值:false)
vue-cli-service build
用法:vue-cli-service build [options] [entry|pattern]
选项:
--mode 指定环境模式 (默认值:production)
--dest 指定输出目录 (默认值:dist)
--modern 面向现代浏览器带自动回退地构建应用
--target app | lib | wc | wc-async (默认值:app)
--name 库或 Web Components 模式下的名字 (默认值:package.json 中的 "name" 字段或入口文件名)
--no-clean 在构建项目之前不清除目标目录
--report 生成 report.html 以帮助分析包内容
--report-json 生成 report.json 以帮助分析包内容
--watch 监听文件变化
--modern 使用现代模式构建应用,为现代浏览器交付原生支持的 ES2015 代码,并生成一个兼容老浏览器的包用来自动回退。
https://cli.vuejs.org/zh/guide/browser-compatibility.html#现代模式
--target 允许你将项目中的任何组件以一个库或 Web Components 组件的方式进行构建。
https://cli.vuejs.org/zh/guide/build-targets.html
--report 和 --report-json 会根据构建统计生成报告,它会帮助你分析包中包含的模块们的大小
vue-cli-service inspect
用法:vue-cli-service inspect [options] [...paths]
选项:
--mode 指定环境模式 (默认值:development)
你可以使用 vue-cli-service inspect 来审查一个 Vue CLI 项目的 webpack config。
vue inspect > output.js//输出配置信息到当前目录下output.js中
缓存和并行处理
cache-loader 会默认为 Vue/Babel/TypeScript 编译开启。文件会缓存在 node_modules/.cache 中——如果你遇到了编译方面的问题,记得先删掉缓存目录之后再试试看。
thread-loader 会在多核 CPU 的机器上为 Babel/TypeScript 转译开启。
根据条件判断是否增加 thread-loader
条件如下:用户在 vue.config.js 中是否配置了 parallel 而且要是 production 环境
const useThreads = process.env.NODE_ENV === 'production'
&& options.parallel
7.浏览器兼容性
browserslist
你会发现有 package.json 文件里的 browserslist 字段 (或一个单独的 .browserslistrc 文件),指定了项目的目标浏览器的范围。这个值会被 @babel/preset-env 和 Autoprefixer 用来确定需要转译的 JavaScript 特性和需要添加的 CSS 浏览器前缀。
8.HTML 和静态资源
public/index.html 文件是一个会被 html-webpack-plugin 处理的模板,所以你可以使用 lodash template 语法插入内容:
<%= VALUE %> 用来做不转义插值;
<%- VALUE %> 用来做 HTML 转义插值;
<% expression %> 用来描述 JavaScript 流程控制。
除了被 html-webpack-plugin 暴露的默认值之外,所有客户端环境变量也可以直接使用。例如,BASE_URL 的用法:
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
Preload
<link rel="preload">
是一种 resource hint,用来指定页面加载后很快会被用到的资源,所以在页面加载的过程中,我们希望在浏览器开始主体渲染之前尽早 preload。
默认情况下,一个 Vue CLI 应用会为所有初始化渲染需要的文件自动生成 preload 提示。
这些提示会被 @vue/preload-webpack-plugin 注入,并且可以通过 chainWebpack 的 config.plugin(‘preload’) 进行修改和删除。
Prefetch
<link rel="prefetch">
是一种 resource hint,用来告诉浏览器在页面加载完成后,利用空闲时间提前获取用户未来可能会访问的内容。
默认情况下,一个 Vue CLI 应用会为所有作为 async chunk 生成的 JavaScript 文件 (通过动态 import() 按需 code splitting 的产物) 自动生成 prefetch 提示。
这些提示会被 @vue/preload-webpack-plugin 注入,并且可以通过 chainWebpack 的 config.plugin(‘prefetch’) 进行修改和删除。
当 prefetch 插件被禁用时,你可以通过 webpack 的内联注释手动选定要提前获取的代码区块:
import(/* webpackPrefetch: true */ './someAsyncComponent.vue')
提示
Prefetch 链接将会消耗带宽。如果你的应用很大且有很多 async
chunk,而用户主要使用的是对带宽较敏感的移动端,那么你可能需要关掉 prefetch 链接并手动选择要提前获取的代码区块。
不生成 index
当基于已有的后端使用 Vue CLI 时,你可能不需要生成 index.html,这样生成的资源可以用于一个服务端渲染的页面。这时可以向 vue.config.js 加入下列代码:
// vue.config.js
module.exports = {
// 去掉文件名中的 hash
filenameHashing: false,
// 删除 HTML 相关的 webpack 插件
chainWebpack: config => {
config.plugins.delete('html')
config.plugins.delete('preload')
config.plugins.delete('prefetch')
}
}
然而这样做并不是很推荐,因为:
硬编码的文件名不利于实现高效率的缓存控制。
硬编码的文件名也无法很好的进行 code-splitting (代码分段),因为无法用变化的文件名生成额外的 JavaScript 文件。
硬编码的文件名无法在现代模式下工作。
你应该考虑换用 indexPath 选项将生成的 HTML 用作一个服务端框架的视图模板。
URL 转换规则
如果 URL 是一个绝对路径 (例如 /images/foo.png),它将会被保留不变。
如果 URL 以 . 开头,它会作为一个相对模块请求被解释且基于你的文件系统中的目录结构进行解析。
如果 URL 以 ~ 开头,其后的任何内容都会作为一个模块请求被解析。这意味着你甚至可以引用 Node 模块中的资源:
<img src="~some-npm-package/foo.png">
如果 URL 以 @ 开头,它也会作为一个模块请求被解析。它的用处在于 Vue CLI 默认会设置一个指向 <projectRoot>/src 的别名 @。(仅作用于模版中)
public 文件夹
任何放置在 public 文件夹的静态资源都会被简单的复制,而不经过 webpack。你需要通过绝对路径来引用它们。
在模板中,你首先需要向你的组件传入基础 URL:
<img :src="`${publicPath}my-image.png`">
data () {
return {
publicPath: process.env.BASE_URL
}
}
9.CSS相关
CSS Modules
你可以通过 <style module> 以开箱即用的方式在 *.vue 文件中使用 CSS Modules。
阮一峰CSS Modules 用法教程
如果想在 JavaScript 中作为 CSS Modules 导入 CSS 或其它预处理文件,该文件应该以 .module.(css|less|sass|scss|styl) 结尾:
import styles from './foo.module.css'
// 所有支持的预处理器都一样工作
import sassStyles from './foo.module.scss'
如果你想去掉文件名中的 .module,可以设置 vue.config.js 中的 css.modules 为 true:
// vue.config.js
module.exports = {
css: {
modules: true
}
}
向预处理器 Loader 传递选项
有的时候你想要向 webpack 的预处理器 loader 传递选项。你可以使用 vue.config.js 中的 css.loaderOptions 选项。比如你可以这样向所有 Sass/Less 样式传入共享的全局变量:
// vue.config.js
module.exports = {
css: {
loaderOptions: {
// 给 sass-loader 传递选项
sass: {
// @/ 是 src/ 的别名
// 所以这里假设你有 `src/variables.sass` 这个文件
data: `@import "~@/variables.sass"`
},
// 默认情况下 `sass` 选项会同时对 `sass` 和 `scss` 语法同时生效
// 因为 `scss` 语法在内部也是由 sass-loader 处理的
// 但是在配置 `data` 选项的时候
// `scss` 语法会要求语句结尾必须有分号,`sass` 则要求必须没有分号
// 在这种情况下,我们可以使用 `scss` 选项,对 `scss` 语法进行单独配置
scss: {
data: `@import "~@/variables.scss";`
},
// 给 less-loader 传递 Less.js 相关选项
less:{
// http://lesscss.org/usage/#less-options-strict-units `Global Variables`
// `primary` is global variables fields name
globalVars: {
primary: '#fff'
}
}
}
}
}
Loader 可以通过 loaderOptions 配置,包括:
css-loader
postcss-loader
sass-loader
less-loader
stylus-loader
10.webpack 相关
调整 webpack 配置最简单的方式就是在 vue.config.js 中的 configureWebpack
链式操作 (高级)
Vue CLI 内部的 webpack 配置是通过 webpack-chain 维护的。
// vue.config.js
module.exports = {
configureWebpack: {
plugins: [
new MyAwesomeWebpackPlugin()
]
}
}
module.exports = {
configureWebpack: config => {
if (process.env.NODE_ENV === 'production') {
// 为生产环境修改配置...
} else {
// 为开发环境修改配置...
}
}
}
//添加一个新的 Loader
module.exports = {
chainWebpack: config => {
// GraphQL Loader
config.module
.rule('graphql')
.test(/\.graphql$/)
.use('graphql-tag/loader')
.loader('graphql-tag/loader')
.end()
}
}
//替换一个规则里的 Loader
module.exports = {
chainWebpack: config => {
const svgRule = config.module.rule('svg')
// 清除已有的所有 loader。
// 如果你不这样做,接下来的 loader 会附加在该规则现有的 loader 之后。
svgRule.uses.clear()
// 添加要替换的 loader
svgRule
.use('vue-svg-loader')
.loader('vue-svg-loader')
}
}
//修改 Loader 选项
module.exports = {
chainWebpack: config => {
config.module
.rule('vue')
.use('vue-loader')
.loader('vue-loader')
.tap(options => {
// 修改它的选项...
return options
})
}
}
//修改插件选项
module.exports = {
chainWebpack: config => {
config
.plugin('html')
.tap(args => {
return [/* 传递给 html-webpack-plugin's 构造函数的新参数 */]
})
}
}
比方说你想要将 index.html 默认的路径从 /Users/username/proj/public/index.html 改为 /Users/username/proj/app/templates/index.html。通过参考 html-webpack-plugin 你能看到一个可以传入的选项列表。我们可以在下列配置中传入一个新的模板路径来改变它:
// vue.config.js
module.exports = {
chainWebpack: config => {
config
.plugin('html')
.tap(args => {
args[0].template = '/Users/username/proj/app/templates/index.html'
return args
})
}
}
以一个文件的方式使用解析好的配置
//vue inspect
<projectRoot>/node_modules/@vue/cli-service/webpack.config.js
该文件会动态解析并输出 vue-cli-service 命令中使用的相同的 webpack 配置,包括那些来自插件甚至是你自定义的配置。
11.环境变量和模式
只有以 VUE_APP_ 开头的变量会被 webpack.DefinePlugin 静态嵌入到客户端侧的包中。你可以在应用的代码中这样访问它们:
console.log(process.env.VUE_APP_SECRET)
在构建过程中,process.env.VUE_APP_SECRET
将会被相应的值所取代。在 VUE_APP_SECRET=secret
的情况下,它会被替换为 “secret”。
除了 VUE_APP_*
变量之外,在你的应用代码中始终可用的还有两个特殊的变量:
NODE_ENV
- 会是 “development”、“production” 或 “test” 中的一个。具体的值取决于应用运行的模式。
BASE_URL
- 会和 vue.config.js 中的 publicPath 选项相符,即你的应用会部署到的基础路径。
所有解析出来的环境变量都可以在 public/index.html 中以 HTML 插值中介绍的方式使用。
12.构建目标
Web Components 组件
兼容性提示 Web Components 模式不支持 IE11 及更低版本。
你可以通过下面的命令将一个单独的入口构建为一个 Web Components 组件:
vue-cli-service build --target wc --name my-element [entry]
注意这里的入口应该是一个 *.vue 文件。Vue CLI 将会把这个组件自动包裹并注册为 Web Components 组件。
该构建将会产生一个单独的 JavaScript 文件 (及其压缩后的版本) 将所有的东西都内联起来。当这个脚本被引入网页时,会注册自定义组件 <my-element>,其使用 @vue/web-component-wrapper 包裹了目标的 Vue 组件。
这个模式允许你的组件的使用者以一个普通 DOM 元素的方式使用这个 Vue 组件:
<script src="https://unpkg.com/vue"></script>
<script src="path/to/my-element.js"></script>
<!-- 可在普通 HTML 中或者其它任何框架中使用 -->
<my-element></my-element>
注册多个 Web Components 组件的包
当你构建一个 Web Components 组件包的时候,你也可以使用一个 glob 表达式作为入口指定多个组件目标:
vue-cli-service build --target wc --name foo 'src/components/*.vue'
当你构建多个 web component 时,–name 将会用于设置前缀,同时自定义元素的名称会由组件的文件名推导得出。比如一个名为 HelloWorld.vue 的组件携带 --name foo 将会生成的自定义元素名为 <foo-hello-world>。
异步 Web Components 组件
当指定多个 Web Components 组件作为目标时,这个包可能会变得非常大,并且用户可能只想使用你的包中注册的一部分组件。这时异步 Web Components 模式会生成一个 code-split 的包,带一个只提供所有组件共享的运行时,并预先注册所有的自定义组件小入口文件。一个组件真正的实现只会在页面中用到自定义元素相应的一个实例时按需获取:
vue-cli-service build --target wc-async --name foo 'src/components/*.vue'
现在用户在该页面上只需要引入 Vue 和这个入口文件即可:
<script src="https://unpkg.com/vue"></script>
<script src="path/to/foo.min.js"></script>
<!-- foo-one 的实现的 chunk 会在用到的时候自动获取 -->
<foo-one></foo-one>