1、项目简介
-
这个项目分为三个页面:首页,登录页、个人中心页。
-
通过vue-router对于路由来做出权限的控制。
-
首页无需登陆,点击个人中心按钮会检测当前是否是登录状态,若没有登录则进入到登录页,进行登录操作。登录之后进入个人中心页,首页登录按钮变为退出按钮
-
页面之间的状态都是通过vuex来进行管理。
项目技术栈
- vue
- vue-router
- vuex
- vue-router
- axios
- less
- webpack
- eslint
项目运行
npm install
npm run dev
启动服务
npm run dev 开发环境
npm run build 生产环境
npm ru lint 代码格式检查
2、项目结构
├── README.md 项目介绍
├── index.html 入口页面
├── build 构建脚本目录
│ ├── webpack.base.conf.js webpack基础配置,开发环境,生产环境都依赖
│ ├── webpack.dev.conf.js webpack开发环境配置
│ ├── webpack.prod.conf.js webpack生产环境配置
│ ├── build.js 生产环境构建脚本
│ ├── dev-server.js 开发服务器热重载脚本,主要用来实现开发阶段的页面自动刷新
│ ├── utils.js 构建相关工具方法
├── config 项目配置
│ ├── dev.env.js 开发环境变量
│ ├── index.js 项目配置文件
│ ├── prod.env.js 生产环境变量
├── src 源码目录
│ ├── main.js 入口文件
│ ├── config 入口相关配置文件
│ ├── app.vue 根组件
│ ├── components 公共组件目录
│ │ └── base 基础组件
│ │ └── layouts 布局组件
│ │ └──header.vue 头部组件
│ ├── styles 样式资源
│ │ └── index.less 样式入口
│ │ └── var.less 变量
│ │ └── reset.less 重置样式
│ │ └── common.less 公共样式
│ ├── images 图片资源
│ │ └── auth 验证模块图片
│ ├── services 接口服务
│ │ └── auth 验证模块接口
│ ├── pages 页面目录
│ │ └── auth 验证模块
│ │ └── login.vue 登录文件
│ ├── routes 路由目录
│ │ └── auth 验证模块
│ │ └── index.js 验证模块入口
│ │ └── index 所有模块汇总
│ ├── store 应用级数据(state)
│ │ └── index.js 所有模块数据汇总
│ │ └── type.js 类型汇总
│ │ └── auth 验证相关数据模块
│ │ └── index.js 验证模块入口
│ │ └── actions.js actions
│ │ └── mutations.js mutations
│ │ └── getters.js getters
│ │ └── state.js 默认状态
│
├── .eslintrc.js eslint规则配置
├── package.json
以上目录都是按照模块来进行划分的:
主要分为build和src两层,build层就是存放webpack配置文件。src又分为pages,images、router、store、components、styles、services
pages主要是用来存放业务组件
images用于存放图片
router用于控制项目路由
store用于管理页面数据
components用于存放公共的组件包括layout一些布局组件
styles用于存放一些公共的样式文件
services用于管理接口(API)
3、项目配置文件
3.1开发环境
dev-sever.js
主要分享以下几个配置重点:
DefinePlugin
new webpack.DefinePlugin({
__DEV__: true
})
你可以理解为,通过配置了DefinePlugin,那么这里面的标识就相当于全局变量,你的业务代码可以直接使用配置的标识。
那么在你的业务代码中可以直接使用,比如有一个index.js
在index.js 你可以直接这样使用:
// index.js
if (__DEV__){
// 任意代码
console.log(‘这个是我通过webpack配置的全局标识’)
}
opn
//自动打开chrome浏览器
var opn=require('opn');
opn('http://localhost:8080', {app: 'chrome'});
webpack-dev-middleware && webpack-hot-middleware
var webpackConfig = require('./webpack.dev.conf')
var compiler = webpack(webpackConfig)
// webpack-dev-middleware的作用
// 1.将编译后的生成的静态文件放在内存中,所以在npm run dev后磁盘上不会生成文件
// 2.当文件改变时,会自动编译。
// 3.当在编译过程中请求某个资源时,webpack-dev-server不会让这个请求失败,而是会一直阻塞它,直到webpack编译完毕
var devMiddleware = require('webpack-dev-middleware')(compiler, {
// 绑定中间件的公共路径,与webpack配置的路径相同
publicPath: webpackConfig.output.publicPath,
// 向控制台显示任何内容
quiet: true
})
// webpack-hot-middleware的作用就是实现浏览器的无刷新更新
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
log: () => {
}
})
3.2生产环境
webpack.prod.config.js
主要分享以下几个配置重点:
ImageminPlugin
new ImageminPlugin({
test: 'static/img/**',
jpegtran: {
progressive: true,
},
optipng: {
optimizationLevel: 3
},
maxConcurrency: Infinity,
})
CopyWebpackPlugin
new CopyWebpackPlugin([{
from: __dirname + '/src/public'
}]);
//作用:把public 里面的内容全部拷贝到编译目录
from 定义要拷贝的源目录 from: __dirname + ‘/src/public’
to 定义要拷贝到的目标目录 from: __dirname + ‘/dist’
toType file 或者 dir 可选,默认是文件
force 强制覆盖先前的插件 可选 默认false
context 可选 默认base context可用specific context
flatten 只拷贝文件不管文件夹 默认是false
ignore 忽略拷贝指定的文件 可以用模糊匹配
UglifyJsPlugin
new webpack.optimize.UglifyJsPlugin({
comments: false,//去掉注释
compress: {
warnings: false,//忽略警告,要不然会有一大堆的黄色字体出现……
drop_console: true,
pure_funcs: ['console.log']
},
sourceMap: false
})
CommonsChunkPlugin
new webpack.optimize.CommonsChunkPlugin({
name: 'common',
filename: 'static/js/[name].js?[chunkhash]',
minChunks: Infinity,
})
minChunks
其中第一name的commons是一个entry入口,里面是一个依赖包的数组。minChunks设置为Infinity这个配置保证没其它的模块会打包进 公共chunk。因为说实话,CommonsChunkPlugin的commons分析实在是不怎么只能,还是手动控制会更好一些。 当然,你可以传入一个 function ,以添加定制的逻辑(默认是 chunk 的数量),这个函数会被 CommonsChunkPlugin 插件回调,并且调用函数时会传入 module 和 count 参数
ExtractTextPlugin
将js中引入的css分离的插件
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].css?[contenthash]')
})
OptimizeCSSPlugin
压缩提取出的css,并解决ExtractTextPlugin分离出的js重复问题(多个文件引入同一css文件)
4、关于路由
关于的vue-router的几个要点:
首先本项目采用的是vue-router的history模式,mode为H5 history模式,这样在路由跳转的时候不会携带#
const router = new VueRouter({
mode: 'history',
routes,
});
关于路由有一个很重要的配置:
eg)
const Home = r => require.ensure(dependencies: String[], callback: function(require), chunkName: String);
webpack 在编译时,会静态地解析代码中的 require.ensure(),同时将模块添加到一个分开的 chunk 当中。 这个新的 chunk 会被 webpack 通过 jsonp 来按需加载
dependencies 这是一个字符串数组,通过这个参数,在所有的回调函数的代码被执行前, 我们可以将所有需要用到的模块进行声明。
callback 当所有的依赖都加载完成后,webpack会执行这个回调函数。require 对象的一个实现会作为一个参数传递给这个回调函数。
chunkName chunkName 是提供给这个特定的 require.ensure() 的 chunk 的名称。
这里边有个很重要的一点是在咱们的生产环境webpack.prod.config.js中需要加上如下配置:
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].js?[chunkhash]'),
chunkFilename: utils.assetsPath('js/[name].js?[chunkhash]')
}
必须在输出的时候加上chunkFilename参数,这样打包后的文件才会跟上述路由的chunkName一致。否则打包后的js文件会按照webpack自己定义生成的类似0.js,1.js这种。
**require.ensure()**这个方法能够很成功帮助我们完成业务组件按序加载,减少app.js的体积,加速我们的项目编译及页面加载速度。
实际组件路由如下:
const Home = r => require.ensure([], () => r(require('@/pages/home/index.vue')), 'home');
const arr = [
{
path: '',
name: 'home',
component: Home,
meta: {
auth: false,
},
},
];
export default arr;
同时路由这里又做了权限的控制,调用的是上述生成的实例router.beforeEach(),然后控制meta.auth为true即可,当然这里也同样配合了vuex里的authenticated这个state数据来同时做出验证
router.beforeEach((to, from, next) => {
const matched = router.getMatchedComponents(to); // 是否有匹配组件
// console.log(matched);
// 配置404页面
if (matched.length > 0) {
if (to.matched.some(m => m.meta.auth) && !store.state.auth.authenticated) {
/*
* If the user is not authenticated and visits
* a page that requires authentication, redirect to the login page
*/
next({
name: 'login',
});
} else if (to.matched.some(m => m.meta.guest) && store.state.auth.authenticated) {
/*
* If the user is authenticated and visits
* an guest page, redirect to the dashboard page
*/
next({
name: 'home',
});
} else {
next();
}
} else {
next({
name: '404',
});
}
});
5、关于vuex
可以参考我的上一篇文章: 简单的vuex解析
代码请参考这里: code
6、关于eslint
在webpack.config.js配置如下:
{
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter')
}
}
同样如果想定义一些自己的规则的话可以在.eslintrc.js文件中的rules修改即可
'rules': {
'global-require': 0,
'import/first': 0,
'no-console': 0,
'no-param-reassign': 0,
'no-multi-assign': 0,
// don't require .vue extension when importing
'import/extensions': ['error', 'always', {
'js': 'never',
'vue': 'never'
}],
'import/no-unresolved': 0,
'import/extensions': 0,
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
}
7、总结
如有感兴趣的同学可以把代码copy下来跑一遍code
github:github.com/Caoyp666/vu…
此文仅供大家参考,如有不对的地方欢迎各位大佬指点!