nuxt是一个基于 Vue.js的服务端渲染应用框架,为了解决C端项目诸如"首屏加载速度" "SEO优化"之类的痛点而生,从发布到现在已经接近两年趋于稳定.我接手这个商城也有一段时间了,本着提高自己的目的再来梳理下我对这个框架的认识.
应用流程
下图阐述的是Nuxt.js 应用一个完整的服务器请求到渲染(或用户通过 <nuxt-link> 切换路由渲染页面)的流程.首先是服务器端接受到请求,然后nuxt服务启动,这时候也初始化了vuex.然后依次通过中间件去匹配 配置(config.js) 布局(layout) 具体页面,在页面组件被加载之前服务器端执行异步数据方法(asyncData 和 fetch),最后输出模板.这里我们要注意的是,只有beforeCreate和created会在服务器端和浏览器端均被调用.
项目结构
我们这个项目应该是用官方提供的starter模板启动,让我们一个个来分析.
- nuxt是自动生成的,关于布局 请求 loading 中间件 路由 vuex的一些官方封装,无需过多关注.
- api用于存放项目地址和localstorage的一些命名.
- assets用于存放一些静态资源,我们这里有 全局CSS iconfont文件 图片 element-ui主题 全局工具类js函数.这里的文件会被webpack做构建编译处理,而static不会.
- components用于存放一些公共组件,框架并不会对其进行增强.
- layouts是一些布局文件,404页面也放在这里了.在page下的页面文件里指定layout就可以使用这里的布局.
- locales是我们用于国际化的一些语言文件
- middleware是一些运行在页面渲染之前的自定义函数,我们这里主要是语言切换和loading.
- pages用于组织应用的路由和视图.nuxt比较省心的地方是已经约定了路由配置的自动生成,所以同时也需要注意文件的地址.
-
plugins配置需要在 根vue.js应用实例化之前需要运行的 Javascript 插件,我们这里有全局过滤器,element-ui的国际化配置,用于站长统计的piwik,以及对于第三方库vue-loading的引用和配置.
- static 用于存放应用的静态文件,此类文件不会被 Nuxt.js 调用 Webpack 进行构建编译处理。 服务器启动的时候,该目录下的文件会映射至应用的根路径 / 下。我们这里只有favicon.ico.
- store用于组织应用的Vuex 状态树文件.这里涉及到两个方法,一个是fetch,会在渲染页面前被调用,作用是填充store 数据;一个是nuxtServerInit 方法,是在启动nuxt应用时去填充stores数据.这个方法我们就是用来拿token和进行其他初始化.
- 下面的文件都比较常见了,eslint代码检查 package.json依赖管理 lock版本锁定,mes_pc.js里面存了给服务器用的启动配置.nuxt.config.js是核心,在下一小节进行讲解.
nuxt.config.js分析
const webpack = require('webpack')
const NLE = require('./api/constant')
module.exports = {
/*
** Headers of the page
*/
head: {
title: '欧亚商城',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width' },
{ hid: 'description', name: 'description', content: 'Nuxt.js project' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
/*
** Customize the progress bar color
*/
loading: { color: '#019ae0' },
plugins: [
{ src: '~plugins/vue-lazyload', ssr: true },
{ src: '~plugins/piwik', ssr: false },
{ src: '~plugins/filter', ssr: true },
{ src: '~plugins/i18n', ssr: true }
],
css: [
// 项目中的 CSS 文件
'bootstrap/dist/css/bootstrap.min.css',
'~/assets/fontsize/iconfont.css',
'~/assets/theme/index.css',
'~/assets/style/common.css',
'~/assets/style/global.css',
'~/assets/style/home.css',
'~/assets/style/transform.css'
],
modules: [
'@nuxtjs/axios'
],
router: {
middleware: ['startLoading', 'i18n']
},
axios: {
baseURL: NLE.BASE_API_URL, // 配置接口地址
browserBaseURL: NLE.BASE_API_URL,
credentials: false,
init (axios, ctx) {
axios.defaults.timeout = 60000 // 响应时间
axios.defaults.responseType = 'json'
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8' // 配置请求头
},
requestInterceptor (config, {store}) {
// console.log(process.env.SERVER, 111)
process.client && store.commit('onLoading', true)
config.headers.versions = 'multi-specification'
config.headers.language = store.state.locale
const token = store.state.login_state
if (token) config.headers.Authorization = token
return config
},
responseInterceptor (response, {store}) {
process.client && store.commit('onLoading', false)
return response
},
errorHandler (error, {redirect, store}) {
process.client && store.commit('onLoading', false)
const status = error.response.status
if (status === 401 || status === 402) redirect('/login')
return error
},
redirectError: {
401: '/login'
}
},
/*
** Build configuration
*/
build: {
plugins: [
new webpack.optimize.MinChunkSizePlugin({minChunkSize: 15000})
],
vendor: ['element-ui', 'localStorage', 'vue-i18n'],
/*
** Run ESLint on save
*/
extend (config, ctx) {
if (ctx.dev && ctx.isClient) {
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/
})
}
}
}
}
- head用于配置应用的的title和meta等信息
- 在页面切换的时候,Nuxt.js 使用内置的加载组件显示加载进度条。通过Loading我们可以进行定置,这里我们指定了颜色.
- plugins指定了实例化之前运行的Vue.js插件,首先配置路径,然后用 ssr: false 变量来配置插件只从客户端还是服务端运行.
- css指定了全局css文件和第三方css库
- router可用于覆盖 Nuxt.js 默认的 vue-router 配置,我们这里主要是给每个页面设置默认中间件.
- axios配置可以单独抽成一个文件.这里我们设置了如响应时间 返回格式 请求格式 baseUrl之类的基本参数,然后配置了请求拦截 返回拦截 错误处理,主要是对 loading的管理 token的携带 语言包配置在请求头里,以及特定状态码的重定向等等.
- build是自定义webpack配置,会覆盖掉nuxt.js默认的.这里用MinChunkSizePlugin指定了chunk 体积,vendor提取出了会被频繁使用的公共库.extend这里主要是通过一些参数,使得在开发环境&客户端环境下使用了eslint代码检查.
- 此外还有一些配置项,比较实用的是env用来定义环境变量 dev配置开发还是生产模式,这样我们的axios就不用手动改baseUrl了.
单个页面分析
(未完待续)