项目

217 阅读6分钟

技术栈

  • 构建工具 @vue/cli3
  • 状态管理:vuex
  • 路由:vue-router
  • UI 框架 element-ui
  • css预处理语言:scss
  • 代码规范:eslint

登录

1.登录方式

  • 验证码登录
  • 扫码登录

2.功能实现

  • qrcode获取二维码 get请求生成qrcode(responseType:blob)img标签渲染
  • 扫码后轮询调用直到获取user_token 成功登录返回首页
  • vuex持久化 利用vuex-persistedstate放入session
  • 因项目要求用于长期登录(+判断用户是否已经登录)token存放cookie中
  • token验证过期后刷新token(更新vuex,cookie,请求头中的token)

退出登录

  • api返回成功后,清空cookie,清空session,跳转登录页

权限

1.登录权限:

手机app扫码成功后返回token,将token存入cookie,并存入vuex 之后在axios的请求拦截器service.interceptors.request.use中将token放入到请求头中 。 http.js

service.interceptors.request.use(
 //1.cookie中获取token
 //2. 对比cookie中token与vuex中的token,如果不一致证明环境有其他账号登录,清空vuex跳转登录页面
)
service.interceptors.response.use(
//1.token过期刷新后存入header中,同时保存cookie
)

2.页面权限(菜单权限 + 按钮权限):

router.beforeEach()中判断权限,无权限直接跳转到404页面。

3.菜单白名单配置:

通过路由的meta属性给页面添加白名单权限,如果meta设置了当前页面为所有人都可以访问的话,就直接跳转,不判断是否有权限

4.按钮权限:

  • 1.每个模块对应有四种权限,查询(get),添加(post),更新(put),删除(delete)
  • 2.利用十进制和二进制来表示当前模块所拥有的权限。1111(15),转换后的二进制与权限的关系表示:从右至左数(1代表拥有该权限,0代表不拥有),第一位代表查询,第二位代表添加,第三位代表更新,第四位代表删除。如eg:二进制1111(15),代表用于查询,添加,更新,删除四种权限。
  • 3.判断对应模块没有此权限时,移除当前按钮dom元素。

5.接口权限:

最后再加上请求控制作为最后一道防线,路由可能配置失误,按钮可能忘了加权限,这种时候请求控制可以用来兜底,越权请求将在前端被拦截。

项目亮点

  1. 项目较大,本地分模块加载(一个模块为pages目录下的一个文件夹利用require.context 实现自动注册。) require.context函数接受三个参数
  • directory {String} -读取文件的路径
  • useSubdirectories {Boolean} -是否遍历文件的子目录
  • regExp {RegExp} -匹配文件的正则

语法: require.context(directory, useSubdirectories = false, regExp = /^.//);

借用webpack官网的例子

require.context('./test', false, /.test.js$/);

  1. 前端首屏菜单点击后生成tab,tab过长显示左右箭头类似el自定义增加标签页触发器(利用keep-alive页面是否缓存)

问题: 页面刷新打开的tab不会消失
原因: 因为存入 Vuex 中的数据,一刷新页面,就会清空,那么当然找不到当前路由,就进入 404 页面了 。
解决:

  • 一、 可以 将 静态和 动态 构成的完整路由 存放在 sessionStronge / localStronge 中,然后页面刷新时,通过在 全局入口文件 App.vue 的 生命周期 created 中 ,将 router = sessionStronge / localStronge 存入的完整的路由,页面在刷新时,它会重新加载完整的路由。
  • 二、如果是使用Vuex来获取和解析用户菜单的话, 那么你可以在全局入口文件 App.vue 的 生命周期 created 中 ,再次执行 Vuex Action 来重新加载用户菜单
  1. 打包优化
  2. vuex模块化( namespaced: true//带命名空间)
//1
import { createNamespacedHelpers } from 'vuex'
const { mapState } = createNamespacedHelpers('user')
  computed: {
    ...mapState({
      userName: state => state.userName
    }
    )
  }
//2
import { mapState } from 'vuex'
  computed: {
    ...mapState({
      userName: state => state.user.userName
    }
    )
  } 
  1. 将vue实例封装为一个app实例并挂载到window上便于全局引用,扩展性强

项目文件配置

  • 代理

webpack 打包&项目优化

clean-webpack-plugin:

帮我们清除 打包之后 dist 目录下的其他多余或者无用的代码 因为我们之前可能生成过其他的 代码 如果不清楚的话 可能 多个代码掺杂在一起 容易把我们搞混乱了 clean-webpack-plugin 插件 就是这样由来的 每次生成代码之前 先将 dist 目录 清空。

1.安装

npm i clean-webpack-plugin -D

2.引入

const {CleanWebpackPlugin}=require(‘clean-webpack-plugin’);

之前的版本可能是 直接引入 没有用对象结构这个是我看最新的官网介绍的引入方式

3.使用 在webpack.config.js的plugins 中配置

new CleanWebpackPlugin() 

运行 npm run build 就可以看到效果了

webpack build后生成的app、vendor、manifest

  1. app.js是入口js
  2. vendor是通过提取公共模块插件来提取的代码块(webpack本身带的模块化代码部分)。
  3. manifest则是在vendor的基础上,再抽取出要经常变动的部分,比如关于异步加载js模块部分的内容。

抽离第三方模块(webpack.dll.conf.js)

这里我们使用webpack内置的DllPlugin DllReferencePlugin进行抽离 在与webpack配置文件同级目录下新建webpack.dll.config.js 类似于库(element-ui,vue,axios...)在项目中不会经常变更的webpack只需要打包项目本身的文件代码,而不会再去编译第三方库。

// webpack.dll.config.js
const path = require("path");
const webpack = require("webpack");
module.exports = {
 // 你想要打包的模块的数组
 entry: {
   vendor: ['vue','element-ui'] 
 },
 output: {
   path: path.resolve(__dirname, 'static/js'), // 打包后文件输出的位置
   filename: '[name].dll.js',
   library: '[name]_library' 
    // 这里需要和webpack.DllPlugin中的`name: '[name]_library',`保持一致。
 },
 plugins: [
   new webpack.DllPlugin({
     path: path.resolve(__dirname, '[name]-manifest.json'),
     name: '[name]_library', 
     context: __dirname
   })
 ]
};


package.json中配置如下命令

"dll": "webpack --config build/webpack.dll.config.js"

接下来在我们的vue.config.js中增加以下代码

configureWebpack: {
  plugins: [
    new webpack.DllReferencePlugin({
      context: __dirname,
      //对应webpack.dll.config.js生成的json文件路径
      manifest: require('./vendor-manifest.json')
    }),
    new CopyWebpackPlugin([ // 拷贝生成的文件到dist目录 这样每次不必手动去cv
      {from: 'static', to:'static'}
    ]),
    //将dll注入html中
    new AddAssetHtmlPlugin({
      //dll文件位置
      filepath: path.resolve(__dirname,"./plublic/vender/*.js"),
      //dll引用路径
      publicPath:"./vender",
      //dll最终输出目录
      outputPath:"./vender"
    }),
  ]
};

执行

npm run dll

这样如果我们没有更新第三方依赖包,就不必npm run dll。直接执行npm run dev npm run build的时候会发现我们的打包速度明显有所提升。因为我们已经通过dllPlugin将第三方依赖包抽离出来了。

HappyPack

HappyPack的基本原理是将这部分任务分解到多个子进程中去并行处理,子进程处理完成后把结果发送到主进程中,从而减少总的构建时间

webpack-parallel-uglify-plugin 增强代码压缩

优化代码压缩时间

babel 去除console

babel.config.js 内配置:

module.exports = {
  presets: ['@vue/cli-plugin-babel/preset'],
  'env': {
    'development': {
      'plugins': ['dynamic-import-node']
    },
    'production': {
      'plugins': ['transform-remove-console']
    }
  }
}

vue.config.js

configureWebpack:{
  plugins:[
  //将lodash挂载到全局,避免组件内import
    new webpack.ProvidePlugin({
     _: 'lodash' 
    })
  ]
}

感谢

链接:juejin.cn/post/703378…

链接:juejin.cn/post/693274…

链接:juejin.cn/post/684490…

原文链接:blog.csdn.net/qq_21567385…

原文链接:blog.csdn.net/yunchong_zh…