Vue项目工程@vue_cli简介

853 阅读9分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第38天,点击查看活动详情


Vue CLI脚手架简介

Vue CLI 是Vue官方提供的基于 Webpack 的 Vue 工具链,用于快速搭建Vue项目的开发框架。@vue/cli 为Vue项目开发提供完整的、全方位的支持,致力于将Vue生态中的工具基础标准化,配备了Vue项目开发所需的各种工具,并提供了最优化的平衡配置。大大简化了Webpack那一堆复杂的配置,无需去纠结各种配置。

  • Vue CLI 5.* 中文文档 和vue2配套使用,也支持vue3。
  • 新一代的Vue CLI是 Vite,和Vue3 搭配。

🪧CLI:Command-Line Interface,命令行界面, 俗称脚手架,搬砖必备。

✅Vue-cli主要作用:

  • 项目脚手架,快速搭建vue项目框架。
  • 开箱即用的开发/构建环境,vue-cli 基于webpack,集成了大量常用组件,抽象了webpack的配置(vue.config.js)。所以webpack中那些代码编译、打包、热更新等功能都开箱即用。
  • 图形化的项目管理功能vue uivue可视化项目管理工具,在这个工具中安装插件,创建、管理项目,这个好评!

✅Vue-cli 三个核心组成部分:

  • CLI:全局安装的npm包@vue/cli,提供vue指令功能。
  • CLI服务@vue/cli-service提供开发环境的编译、热更新功能,安装在每个vue项目中。构建于webpack + webpack-dev-server之上,包含了:
    • 加载其他CLI插件的核心服务。
    • 优化过的webpack配置vue.config.js
    • 提供的vue-cli-service命令:servebuildinspect
  • CLI插件:提供了大量可选的vue项目所需的npm包,
    • @vue/cli-<plugin-name>:为内建插件。
    • vue-cli-<plugin-name> :为社区插件。
    • 运行cli服务时会自动更新package.json中的包。

安装@vue/cli

依赖环境:node.js + npm,安装好node.js环境就可以了,vue/cli 内置了webpack。

  • 全局安装@vue/cli插件:npm install -g @vue/cli
  • 安装可视化管理插件:vue ui
  • 创建vue项目:vue create vue-name
#安装插件
npm install -g @vue/cli
#查看版本
vue --version  						
@vue/cli 5.0.8

#安装vue-cli的可视化管理工具
vue ui

#创建项目,在工程目录下执行指令,项目会创建在该目录下
vue create vuep3

安装完@vue/cli后可用的vue指令:

vue指令描述
vue -Vvue-cli的版本
vue -h查看帮助,在命令后面加-h可以获得对应命令的帮助说明
vue create <项目名称>创建一个项目,
vue ui创建/启动 一个 vue-cli 的图形化管理工具,就可以可视化管理项目了,基本涵盖大部分指令功能
🪧项目目录下运行
vue upgrade升级项目中cli插件的版本,vue upgrade --all 升级所有插件
vue add <plugin>在vue-cli中新增一个vue插件,也可以用npm,vue会提供更好(五星级)的安装服务。
vue add eslint实际过程:包名解析为完整的@vue/cli-plugin-eslint然后npm安装

image.png

vue ui 安装vue项目管理工具,所有的插件管理、依赖管理、配置、开发服务等都可以在线可视化操作了!

image.png

命令行运行指令:vue ui 启动可视化工具

image.png


CLI服务@vue/cli-service

@vue/cli-service提供开发环境的编译、热更新功能,安装在每个vue项目中,通过vue-cli脚手架创建的项目就默认安装了。提供了一个名为 vue-cli-service 的命令,包括servebuildinspect等命令。

运行npm run serve启动开发服务器,实时更新。注意如果修改了配置文件(如vue.config.js),则需要重启serve才生效。

vue-cli-service指令npm指令vue指令描述
vue-cli-service servenpm run servevue serve启动开发服务,开发模式热更新,代码修改自动编译更新,可实时调试
vue-cli-service buildnpm run buildvue build编译代码,默认模式是production(生产环境),在dist目下输出
vue-cli-service test:unitnpm run test:unit运行单元测试
vue-cli-service lintnpm run lint代码检查
vue-cli-service inspectnpm run inspectvue inspect检查被所有 cli 插件解析后的 webpack配置,可以输出到文件查看
<指令> -help查看帮助

image.png

注意:指令在项目目录下运行。

package.json中自动配置了npm指令:

"scripts": {
  "serve": "vue-cli-service serve",
  "build": "vue-cli-service build",
  "test:unit": "vue-cli-service test:unit",
  "lint": "vue-cli-service lint"
},

编译缓存(cache-loader):Vue/Babel/TypeScript 编译缓存到目录 node_modules/.cache 下,如果有编译问题,可清空缓存试试。


vue项目结构

基于@vue/cli 5.0.8 版本创建项目:vue create vuep3,选择vue2版本,设置babel、router、vuex、less、eslint、test,完成后的项目工程目录结构如下:

项目目录/文件描述
📁dist编译输出目录,默认每次编译会清空。(distributable /dɪˈstrɪbjuːtəbl/ 可分配的)
📁node_modules项目的所有依赖包资源,有点多,第一层目录级就700+
📁public不需要编译打包的静态文件,直接拷贝目录下内容到dist
📁img/css/js资源目录
index.html入口html文件,构建时会注入资源(js、css、图标等),可以插值
manifest.json离线缓存配置,用于创建桌面app的快捷入口
favicon.ico网页图标logo
robots.txt爬虫配置
📁src开发目录,搬砖写Bug的地方
📁assets图片、CSS、字体文件等静态资源( /ˈæset/资产),与public区别是会被webpack编译
📁components项目公共组件
📁router/router.jsvue-router路由文件
📁store/store.jsvuex公共库文件
📁views页面视图,用router路由
App.vue应用程序根组件
main.js应用程序入口文件,引入其他组件;创建根Vue实例,渲染App.vue,mount到index.html
registerServiceWorker.jsweb workers文件
📁test单元测试
.browserslistrc浏览器兼容性配置,在构建中使用
.eslintrc.jseslint 的配置文件
.gitignoregit的忽略配置
babel.config.jsbabel配置,用于转换ES6语法
jsconfig.json单元测试配置
package-lock.json用于锁定模块依赖树的版本,避免多人开发的版本差异
package.json项目npm依赖包配置
vue.config.jsvue配置文件
readme.md项目自我介绍文档

image.png

运行npm run serve启动项目,项目入口文件的引用关系如下图。

$ npm run serve
> vuep5@0.1.0 serve
> vue-cli-service serve

App running at:
- Local:   http://localhost:3000/ 
- Network: http://localhost:3000/

image.png

vue.config.js

vue.config.js 是vue的全局配置,这个文件导出一个配置对象,module.exports = defineConfig({ })。是vue-cli 抽象出来的配置,会被自动合并(应用)到webpack.config.js等插件中,所以尽量不要重复修改webpack中的配置。

选项属性说明
publicPath基本url,多用于指定子路径,如/app/则应用url 为www.baidu.cn/app/
outputDir默认'dist',编译输出的目录,注意编译时目录会被清空
assetsDir默认空,放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录
indexPath默认'index.html',生成的 index.html 的输出路径 (相对于 outputDir)
filenameHashing默认true,静态资源 (js、css、img、fonts) 文件名是否包含哈希值,作用是控制浏览器缓存
pages : Object构建多页应用
lintOnSave针对@vue/cli-plugin-eslint的配置项,是否在编译保存代码时执行lint检查代码
runtimeCompiler默认false,是否运行时编译Vue的模板,参考
transpileDependencies默认false,是否需要转译的第三方依赖。默认babel-loader 会忽略所有 node_modules 文件
productionSourceMap默认true,构建时输出source map文件,便于调试JS
crossoriginhtml-webpack-plugin配置,设置 <link rel="stylesheet"> 标签的 crossorigin 属性
integrity (默认falsehtml-webpack-plugin配置,增强CDN部署的安全性,(integrity /ɪnˈteɡrəti/ 完整、安全)
configureWebpackwebpack配置,Object | Function,最终会合并到最终的配置中
chainWebpack链式webpack配置,是一个函数,可链式调用的方式配置webpack
css.requireModuleExtension默认true,只有 *.module.[ext] 结尾才会被视作 CSS Modules 模块,参考
css.extract默认生产环境ture,开发false,打包时是否提取css到一个独立css文件
css.sourceMap默认false,是否为 CSS 开启 source map
css.loaderOptions向 CSS 相关的 loader 传递选项,参考
devServer开发服务器设置,devServer.proxy设置一个访问代理
parallel是否为 Babel 或 TypeScript 使用 thread-loader,默认在cpu核心数大于1时启用-并行构建
pwaPWA 插件传递选项
pluginOptions用来传递任何第三方插件选项

开发模式下,修改配置文件需要重启server才会生效。

const { defineConfig } = require('@vue/cli-service')
const CompressionPlugin = require('compression-webpack-plugin');

module.exports = defineConfig({
  transpileDependencies: true, //默认false,是否需要转译的第三方依赖
  publicPath: process.env.BASE_URL, //基本url,多用于指定子路径
  outputDir:"dist",                 //默认dist,编译输出的目录
  assetsDir: "",          //默认空,放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录
  indexPath:"index.html", //默认'index.html',生成的 index.html 的输出路径 (相对于 outputDir)
  filenameHashing:true,   //默认true,静态资源 (js、css、img、fonts) 文件名是否包含哈希值,作用是控制缓存
  devServer:{
    liveReload: false,    //默认ture,false关闭热更新
    host:"localhost",			//设置开发服务器的地址、端口号,默认端口号为8080
    port:'3000',
    proxy:"http://localhost:4000", //任何未知请求代理到http://localhost:4000
  },
  pluginOptions: {
    foo: {
      // 插件可以作为 `options.pluginOptions.foo` 访问这些选项。
    }
  },
  configureWebpack: config => {
    config.optimization = {
      splitChunks: {                 // 开启分离js
        chunks: "all",               //async异步代码分割; initial同步代码分割; all同步异步分割都开启
        // minSize: 10000,           //字节 引入的文件大于10kb才进行分割
        automaticNameDelimiter: '-', //缓存组和生成文件名称之间的连接符
        // name: true,               //缓存组里面的filename生效,覆盖默认命名
        cacheGroups: {               //按组件模块分割
          "element-ui": {
            name: 'eu',
            test: /[\\/]node_modules[\\/]element-ui[\\/]/,
            priority: -10
          },
        }
      }
    };
    config.plugins.push(
      new CompressionPlugin({   //CompressionPlugin gizp压缩插件
        algorithm: 'gzip',      // 使用gzip压缩
        test: /\.js$|\.html$|\.css$/, // 匹配文件名
        filename: '[path][base].gz',  // 压缩后的文件名
        minRatio: 1,        // 压缩率小于1才会压缩,默认0.8?
        threshold: 40960,   // 对超过40k的数据压缩
        deleteOriginalAssets: false, // 是否删除未压缩的源文件,谨慎设置
      }));
  },
  chainWebpack: config => {
    // GraphQL Loader
    config.module
      .rule('graphql')
      .test(/\.graphql$/)
      .use('graphql-tag/loader')
      .loader('graphql-tag/loader')
      .end()
      // 你还可以再添加一个 loader
      .use('other-loader')
      .loader('other-loader')
      .end()
  }
})

vue 中的webpack配置是在vue.config.js 中的 configureWebpack chainWebpack选项,最终会被合并到 webpack配置里。

//输出被cli处理过的完整webpack配置,到一个文件进行查看
vue inspect >a.json

process.env/模式

process.env是Node.js中的环境对象,记录了当前系统环境的变量信息,是一个全局对象。而这里的环境是webpack的编译环境,可以在JS中使用,会通过插件webpack.DefinePlugin静态注入到客户端代码中。

vue-cli 中的 process.env 默认包含BASE_URL、NODE_ENV:

BASE_URL: "/"		//部署的基础URL路径,和 vue.config.js 中的 publicPath 选项相符
NODE_ENV: "development"	//编译环境的模式,"development""production""test" 中的一个
VUE_APP_CLI_UI_URL: ""	//

process.env.NODE_ENV 为 vue-cli的编译环境模式,分为 开发、测试、生产 三个模式,用来区分不同编译环境。在正常开发中,我们都至少需要开发模式、正式生产模式,不同模式需要编译、引用资源都有所不同。如开发环境不需要hash、压缩,需要热更新。生产环境需要hash、代码压缩、混淆等。

vue-cli 默认有三个模式:process.env.NODE_ENV

  • development:开发模式,npm run serve, 用于启动热更新,不会对资源哈希处理。
  • production:生产模式,npm run build
  • test:测试模式,npm run test:unit,构建用于测试的环境,不会处理那些和单元测试无关的资源,如图片。

如果需要很多自定义的环境变量,可以在项目根目录中放置下列文件来指定环境变量:

.env                # 在所有的环境中被载入
.env.local          # 在所有的环境中被载入,但会被 git 忽略
.env.[mode]         # 只在指定的模式中被载入
.env.[mode].local   # 只在指定的模式中被载入,但会被 git 忽略

每个环境文件只包含[键=值]对

VUE_APP_TITLE = '奥特曼管理系统'
BASE_URL= '/aotm/'
API_URL = https://abc-pre.com

在vue-cli中,只有NODE_ENV,BASE_URL 和以 VUE_APP_ 开头的变量将通过 webpack.DefinePlugin 静态地嵌入到客户端侧的代码中。

public/资源编译

public 目录存放静态资源,编译时会被拷贝输出,而不经过webpack处理,可以通过绝对路径方式引用/path。使用绝对地址引用时,需要注意如果不是部署跟根域名目录,需要设置基础路径publicPath

public/index.html文件会当做模板处理,在构建中注入资源引用。因为是模板文件,可以使用插值,html-webpack-plugin暴露的值,或客户端环境变量。

<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= process.env.VUE_APP_TITLE %></title>

JavaScript、CSS 或 *.vue 中引用的相对路径资源,会被webpack处理。webpack内部会把所有资源URL都解析为一个模块依赖,如require('./image.png'),然后再匹配其正确的文件路径。这个过程会对资源做一些优化:

  • 小于8KB的资源内联,以减少HTTP的请求数量,可通过chainWebpack调整(vue.config.js)。
  • 脚本、样式资源会被合并打包、压缩,提升网络加载效率。
  • 文件丢失会在编译时报错。
  • 文件名包含哈希(每次编译都不一样),不用担心浏览器缓存了。

资源URL 转换规则

  • /绝对路径:以/开头的 URL为绝对路径,如 /images/foo.png,它将会被保留不变。
  • .相对路径:以.开头的 URL ,它会作为一个相对模块请求被解释且基于你的文件系统中的目录结构进行解析。
  • ~模块路径:以~开头的 URL,其后的任何内容都会作为一个模块请求被解析,这意味着你可以引用 Node 模块中的资源。
  • @ 默认为指向<projectRoot>/src的一个路径别名,仅作用于模版中。

浏览器兼容性browserslist

浏览器兼容性设置存在于package.json文件中的browserslist,或单独的文件.browserslistrc,指定了项目兼容的浏览器范围。在JS(@babel/preset-env)、CSS(Autoprefixer)编译中会用到,用于代码的兼容性转译。

{
  "browserslist": [
    "> 1%",             //全球市场占有率大于 1% 的浏览器
    "last 2 versions",  //浏览器的最后 2 个版本
    "not dead",         //还没死的:超过 24 个月没被官方维护的浏览器
    "not ie <= 8",      //不支持ie8及以下
  ]
}

有了babel编译,可以兼容低版本浏览器,但会导致JS文件庞大,运行低效。vue提供一个现代模式:--modern (modern /ˈmɑːdərn/ 现代的)

 npm run build --modern

加上--modern参数,采用现代模式编译代码会生成2个版本的代码,一个现代版本,面向支持ES modules的现代浏览;一个兼容的版本,面向远古的浏览器。

<script type="module" src="module.mjs"></script> <!--加载现代版本的JS文件-->
<script nomodule src="fallback.js"></script>		 <!--加载兼容版本的JS文件-->

vue-cli中默认使用@vue/babel-preset-app预设,配置了常规最优的polyfill配置,它通过 @babel/preset-env 和 browserslist 配置来决定项目需要的 polyfill。如果项目是一个库(JS库、或者组件Component库),则不建议babel编译,可以交给使用库的应用来处理。在babel.config.js中设置useBuiltIns: false


参考资料


©️版权申明:版权所有@安木夕,本文内容仅供学习,欢迎指正、交流,转载请注明出处!原文编辑地址-语雀