一个vue项目开发的复盘,思如泉涌~~__Vue.js
发布于 3 年前 作者 banyungong 1288 次浏览 来自 分享
粉丝福利 : 关注VUE中文社区公众号,回复视频领取粉丝福利

一、项目搭建

脚手架安装、运行

npm install -g @vue/cli // 全局安装脚手架
vue create my-project // 创建项目
npm i // 项目初始化
npm run serve 或npm run build  // 运行起来

vue UI安装、运行

vue ui // 进入项目仪表盘

注意:命令行界面不可以关掉,界面操作时,命令行会响应执行

image.png

点击下拉菜单,进入vue项目管理器

image.png

点击创建标签页,进入创建项目入口面板

image.png

点击下拉菜单,新建文件夹或选择文件夹

image.png

点击创建项目

image.png

填写项目初始化信息

image.png

预设配置

image.png

初始功能配置

选择router+使用配置文件+3个默认勾选的,eslint可以去掉,格式检查过于繁琐。

image.png

image.png

其他配置

选择2.0版本,3.x界面搭建方式正在动手试验中。

url模式选择,选择hash模式

选择语法检查image.png

image.png

保存预设并创建项目

image.png

image.png

创建成功

image.png

运行项目

进入任务面板

image.png

点击运行

image.png

运行成功,打开网页

image.png

image.png

安装插件和依赖

插件

vue-cli-plugin-element    // 插件名称

image.png

依赖

分别在vue UI管理器界面搜索以下依赖点击安装

#安装依赖后需要重新编译

axios // 运行依赖

import axios from 'axios'; 
Vue.prototype.$http = axios;

less loader // 开发依赖

less // 开发依赖 //less loader 依赖于 less

运行依赖和开发依赖区别?

devDependencies 开发依赖

开发依赖是什么,也就是开发中所使用的的依赖,线上生产环境上并不需要他们

**开发依赖的目的:**是为了减少在安装依赖时node_modules的体积,提升安装依赖的速度,节省线上及其的硬盘资源以及部署上线的时间。

npm i xxx -D    // 下同
npm i xxx --save-dev

有哪些开发依赖

image.png

dependencies 运行依赖

npm i xxx -S    // 下同
npm i xxx --save

插件与依赖的区别?

image.png

作用不同

插件也是封装了一系列功能的组件包,但是它是依赖于一个软件环境(这里注意不是运行环境)的,属于软件的一部分功能。

比如vue-cli-plugin-element这个插件就依赖于vue-cli。 它的作用是使这个软件在调用依赖包中的功能时更加的方便,帮助vue-cli修改项目中element的配置。换句话说就是:插件就是帮助软件更好,更方便的使用依赖的。

安装方式不同

vue add @vue/cli-plugin-eslint

二、项目开发

http管理

配置axios请求拦截器+基准地址

开发基准地址
import axios from 'axios'

// 配置请求的根路径
axios.defaults.baseURL = 'http://127.0.0.1:8888/api/private/v1/'

// 配置token在请求头中发送:区别在url中发送token
axios.interceptors.request.use(config => {
  config.headers.Authorization = window.sessionStorage.getItem('token')
  // 在最后必须 return config
  return config
})

权限管理

接口权限:token

如果没有token,则不能请求除登录接口之外的接口

#token
获取
	登录后获取
保存
	window.sessionStorage.setItem('token', res.data.token)
	或在vuex中保存(如需缓存token放在了vuex配合本地存储),vuex运行在内存中,关闭应用就会消失,利用本地存储进行中转,下次登录时取出,重新存入vuex中
发送给服务端
	在请求头中发送
    axios.interceptors.request.use(config => {
    config.headers.Authorization = window.sessionStorage.getItem('token')
    return config
    })
    
	在url中发送

路由权限:路由守卫

利用token做路由权限控制,如果没有token,则不能通过url进行页面跳转

// 挂载路由导航守卫
router.beforeEach((to, from, next) => {
  // to 将要访问的路径
  // from 代表从哪个路径跳转而来
  // next 是一个函数,表示放行
  //     next()  放行    next('/login')  强制跳转

  if (to.path === '/login') return next()
  // 获取token
  const tokenStr = window.sessionStorage.getItem('token')
  if (!tokenStr) return next('/login')
  next()
})

按钮权限

// 0:不可见 1:不可编辑 2:可编辑
控制可见性
	v-if实现按钮的条件渲染
控制可编辑性
	按钮标签的:disabled属性

菜单权限

如果后端返回的菜单列表没有某个页面的地址,则无法通过点击的方式进行跳转:通过组件的索引控制跳转的页面

// 页面权限实际上就是菜单权限,如果说我们没有去某个页面的导航菜单,实际上就是没有去那个页面的权限了,所以说页面权限的实际就是菜单权限。

业务功能

登录退出功能

其他功能

前端三基础+组件UI+各路插件进行实现

MQTT功能

1、安装依赖包

npm install mqtt --save

2、项目中引入

import mqtt from 'mqtt'

3、理解MQTT

以区别于请求响应模式的订阅-发布模式进行数据的获取,通过MQTT代理服务器可以作为中间节点,其他客户端或者服务端作为中间节点的连接点,客户端或者服务端都可以进行订阅某个主题,当某个连接点发布了消息,其他订阅了这个主题的节点将会在监听的函数中收到相关消息(数据)。

此时对收到的消息(数据)进行if等判断即可区别不同主题(不同主题类似于不同接口,有一个特定的主码,比如666,代表特定的消息,实际生活的场景如订阅了某前端公众号或某邮箱的某个主题新闻等,一有发布就)就会通知你进行查收,然而,mqtt就是在监听中进行查收的。

三、项目优化、打包、部署

编译模式:开发模式development、生产模式production

项目优化

打包报告生成

// 命令方式生成
vue-cli-service build --report
// 可视化面板中运行生成,如下图

通过externals 加载外部CDN资源

问题
	默认情况下,通过import语法导入的第三方依赖包,最终会被打包合并到同一个文件中,从而导致打包成功后,单文件体积	 过大的问题。
方法
	为了解决上述问题,可以通过webpack的externals节点,来配置并加载外部的CDN资源。凡是声明在externals 中的第三		方依赖包,都不会被打包。
	第一步:配置,查看vue.config.js配置文件
	第二步:在public/index.html文件的头部,添加CDN资源引用 删除main-prod.js(发布阶段)中对应的import语句
	第三步:查看打包结果
	

第二步:CDN引入方法示例

<head>
	<!-- nprogress 的样式表文件 -->
    <link rel="stylesheet" href="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.css" />
    <!-- 富文本编辑器 的样式表文件 -->
    <link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.core.min.css" />
    <link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.snow.min.css" />
    <link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.bubble.min.css" />


    <script src="https://cdn.staticfile.org/vue/2.5.22/vue.min.js"></script>
    <script src="https://cdn.staticfile.org/vue-router/3.0.1/vue-router.min.js"></script>
    <script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
    <script src="https://cdn.staticfile.org/lodash.js/4.17.11/lodash.min.js"></script>
    <script src="https://cdn.staticfile.org/echarts/4.1.0/echarts.min.js"></script>
    <script src="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.js"></script>
    <!-- 富文本编辑器的 js 文件 -->
    <script src="https://cdn.staticfile.org/quill/1.3.4/quill.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue-quill-editor@3.0.4/dist/vue-quill-editor.js">			</script>
</head>    

第三步:查看CDN加载效果

优化前

image-20210307113404960

优化后

image-20210307115725431

通过CDN加载ElementUI

问题:按需加载被打包进vendors.js
    虽然在开发阶段,我们启用了element-ui组件的按需加载,尽可能的减少了打包的体积,但是那些被按需加载的组件,还是		被打包,占用了较大的文件体积。此时,我们可以将element-ui中的组件,也通过CDN的形式来加载,这样能够进—步减小打	包后的文件体积。
方法:
	在main-prod.js中,注释掉element-ui按需加载的代码 // import './plugins/element.js'
	在index.html的头部区域中,通过cD加载element-ui的js和css样式
<head>
	<!-- element-ui 的样式表文件 -->
    <link rel="stylesheet" href="https://cdn.staticfile.org/element-ui/2.8.2/theme-chalk/index.css" />
    
    <!-- element-ui 的 js 文件 -->
    <script src="https://cdn.staticfile.org/element-ui/2.8.2/index.js"></script>
</head>

优化前

image-20210307120034793

优化后

image-20210307120818598

按需加载index.html的CDN资源

配置
	查看vue.config.js
修改index.html:条件加载
	 // 条件渲染网页标题
	 <title><%= htmlWebpackPlugin.options.isProd ? '' : 'dev - ' %>电商后台管理系统</title>
	 // 条件加载CDN
	 <% if(htmlWebpackPlugin.options.isProd){ %>
	 	// 这里放CDN资源
	 <% } %>
查看效果
	到dist的index.html中查看
	开发模式:到浏览器中打开index.html

路由分组懒加载

懒加载:用到的时候才加载,没用到的时候不加载。图片懒加载、组件(路由)懒加载。

路由分组:同一组的被打包到同一个js文件中,加载的时候一起加载,这样所有组件就被切割成多个部分,而不是一次性加载所有组件。

具体需要3步:
安装 代码分割插件 开发依赖
	@babel/plugin-syntax-dynamic-import包
配置
	查看配置bable.config.js  代码分割插件配置
改造组件import方式
	将router.js的组件引入方式改为按需加载引入的形式,即异步组件导入方式+配合代码分割分组
     // 这个动态导入会返回一个 `Promise` 对象。
     () => import('./my-async-component')
	
#router.js
// import Login from './components/Login.vue'
const Login = () => import(/* webpackChunkName: "login_home_welcome" */ './components/Login.vue')
// import Home from './components/Home.vue'
const Home = () => import(/* webpackChunkName: "login_home_welcome" */ './components/Home.vue')
// import Welcome from './components/Welcome.vue'
const Welcome = () => import(/* webpackChunkName: "login_home_welcome" */ './components/Welcome.vue')

// import Users from './components/user/Users.vue'
const Users = () => import(/* webpackChunkName: "Users_Rights_Roles" */ './components/user/Users.vue')
// import Rights from './components/power/Rights.vue'
const Rights = () => import(/* webpackChunkName: "Users_Rights_Roles" */ './components/power/Rights.vue')
// import Roles from './components/power/Roles.vue'
const Roles = () => import(/* webpackChunkName: "Users_Rights_Roles" */ './components/power/Roles.vue')



优化前

image-20210307230834729

优化后

image-20210307231001786

项目打包

项目部署

  • 后端部署:express(后端)创建服务器并托管为静态资源,监听并启动入口程序,让程序运行在某个端口
    • 与后端API程序是两个程序
  • 后端优化
    • 开启gizip传输压缩
      • image-20210309222909713
    • 压缩前

image-20210309222820607

  • 压缩后

    • image-20210309223154975
  • 开启HTTPS

    • image-20210309223719948
    • image-20210309223940885
    • image-20210309224102414
  • 启用PM2

    • 问题:命令行启动,复制地址在浏览器打开,关闭命令行,发现页面打不开了。不关闭命令行又难以管理
    • image-20210309224841727
    • image-20210309225000379

dist页面空白

module.exports = {
  publicPath: './',         //配置本地引用目录文件,如不配置,默认为`/`
}

接口请求失败

基准地址需要更改为上线后的的基准地址,而不是局域网的开发地址

三、插件统计

nprogress 进度条

作用:开启请求数据时的进度条

安装

导入main.js
    // 导入 NProgress 包对应的JS和CSS
    import NProgress from 'nprogress'
    import 'nprogress/nprogress.css'
配置
axios.interceptors.request.use(config => {
  // console.log(config)
  NProgress.start()
  // 在最后必须 return config
  return config
})
// 在 response 拦截器中,隐藏进度条 NProgress.done()
axios.interceptors.response.use(config => {
  NProgress.done()
  return config
})

babel-p1ugin-transform-remove-console 调试语句消除

问题
	当vue-cli在ui界面任务下进行build生成生产环境代码时,如果碰到有console类型的语句,是会报错的。
作用
	消除开发阶段调试使用的console.log语句
安装
	npm install babel-plugin-transform-remove-console --save-dev
	或vue ui图形界面中中搜索开发依赖进行安装
配置
	.babelrc(官方推荐)
	查看babel.config.js配置文件代码、注释(vue对应的配置文件)
使用方法
	构建项目时自动生效,打开浏览器调试台,可以查看效果

Prettier - Code formatter 格式化代码

安装
配置
	.prettierrc中进行配置编辑器格式化

四、配置文件

.prettierrc vsCode格式化配置文件

配置:调整编辑器代码格式化
{
  "semi": false,   		  // 关闭分号
  "singleQuote": true,    // 引号格式化为单引号
  "printWidth": 200 	 // 代码多宽换行
}

![](static/image-20210306170224399.png

.eslintrc.js 格式检查配置文件

配置:取消检查函数括号前空格
module.exports = {
  root: true,
  env: {
    node: true
  },
  'extends': [
    'plugin:vue/essential',
    '@vue/standard'
  ],
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
      // 配置不检查函数前的空格
    'space-before-function-paren': 0
  },
  parserOptions: {
    parser: 'babel-eslint'
  }
}

babel.config.js 插件配置

配置:发布阶段移除console
// transform-remove-console固定配置:对比下个代码块的动态判断配置
// 缺点:开发阶段 、生产阶段都会移除console.log(),不符合预期的需求,需求只需要移除生产阶段的console就OK
module.exports = {
  presets: ['@vue/app'],
  plugins: [
    [
      'component',
      {
        libraryName: 'element-ui',
        styleLibraryName: 'theme-chalk'
      }
    ],
    // 新增的代码:插入一个插件数组即可对插件配置成功
    ['transform-remove-console']
    '@babel/plugin-syntax-dynamic-import'
  ]
}
// transform-remove-console动态判断配置
// 生产(发布)阶段需要用到的 babel 插件
const prodPlugins = []
// 是否是生产阶段
if (process.env.NODE_ENV === 'production') {
    // 构建一个数组,在plugins节点中插入
  prodPlugins.push('transform-remove-console')
}

module.exports = {
  presets: ['@vue/app'],
  plugins: [
    [
      'component',
      {
        libraryName: 'element-ui',
        styleLibraryName: 'theme-chalk'
      }
    ],
    // 展开发布产品时候的插件数组
    ...prodPlugins,
    '@babel/plugin-syntax-dynamic-import'
  ]
}

配置代码分割插件
module.exports = {
  plugins: [
    [
    ],
    // 与其他配置的数组同一级
    '@babel/plugin-syntax-dynamic-import'
  ]
}

vue.config.js webpack打包配置

通过vue-cli 3.0工具生成的项目,默认隐藏了所有webpack的配置项,目的是为了屏蔽项目的配置过程,让程序员把工作的重心,放到具体功能和业务逻辑的实现上。配置文档

在vue.configjs 导出的配置对象中,新增configureWebpack或chainWebpack 节点,来自定义webpack的打包配置

在这里, configureWebpack和chainWebpack的作用相同,唯一的区别就是它们修改webpack配置的方式不同: chainWebpack通过链式编程的形式,来修改默认的webpack配置configureWebpack通过操作对象的形式,来修改默认的webpack配置

配置:分离开发模式和发布模式打包入口(省略配置baseUrl)
配置
    module.exports = {
      chainWebpack: config => {
        // 发布模式:得到、清空、追加
        config.when(process.env.NODE_ENV === 'production', config => {
          config
            .entry('app')
            .clear()
            .add('./src/main-prod.js')
        })
        // 开发模式
        config.when(process.env.NODE_ENV === 'development', config => {
          config
            .entry('app')
            .clear()
            .add('./src/main-dev.js')
        })
      }
    }
创建
	src/main-dev.js
	src/main-prod.js
配置:第三方依赖采用CDN加载
module.exports = {
  chainWebpack: config => {
    // 发布模式
    config.when(process.env.NODE_ENV === 'production', config => {
      // 配置取消第三方依赖进行打包成vendors.js
      config.set('externals', {
        vue: 'Vue',
        'vue-router': 'VueRouter',
        axios: 'axios',
        lodash: '_',
        echarts: 'echarts',
        nprogress: 'NProgress',
        'vue-quill-editor': 'VueQuillEditor'
      })
    })

    // 开发模式
    config.when(process.env.NODE_ENV === 'development', config => {
    	// 其他配置
    })
  }
}

配置:配置CDN资源按需加载,开发模式不需要
module.exports = {
  chainWebpack: (config) => {
    // 发布模式
    config.when(process.env.NODE_ENV === 'production', (config) => {
     // 开发模式下返回生产模式的flag
      config.plugin('html').tap((args) => {
        args[0].isProd = true
        return args
      })
    })

    // 开发模式
    config.when(process.env.NODE_ENV === 'development', (config) => {
	// 开发模式下返回不是生产模式的flag
      config.plugin('html').tap((args) => {
        args[0].isProd = false
        return args
      })
    })
  },
}

五、代码段复用

配置性的代码段

// 判断vue项目的编译模式是处于开发模式或生产模式
process.env.NODE_ENV === 'development'
process.env.NODE_ENV === 'production'

本文提供了一个项目复盘的思路,进行了全面的解剖,我个人认为是有挺大参考价值的,当我们完成了某项计划和行动,复盘可以理清思路,让表达更加清晰。

转载请联系作者授权并放上小小的一条链接~

版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 作者: Mindos__全掘金的最靓的仔 原文链接:https://juejin.im/post/6939479680269418526

回到顶部