nuxt企业商城小结

nuxt是一个基于 Vue.js的服务端渲染应用框架,为了解决C端项目诸如"首屏加载速度" "SEO优化"之类的痛点而生,从发布到现在已经接近两年趋于稳定.我接手这个商城也有一段时间了,本着提高自己的目的再来梳理下我对这个框架的认识.

应用流程

下图阐述的是Nuxt.js 应用一个完整的服务器请求到渲染(或用户通过 <nuxt-link> 切换路由渲染页面)的流程.首先是服务器端接受到请求,然后nuxt服务启动,这时候也初始化了vuex.然后依次通过中间件去匹配 配置(config.js) 布局(layout) 具体页面,在页面组件被加载之前服务器端执行异步数据方法(asyncData 和 fetch),最后输出模板.这里我们要注意的是,只有beforeCreate和created会在服务器端和浏览器端均被调用.


image.png

项目结构

image.png

我们这个项目应该是用官方提供的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的引用和配置.


    image.png
  • 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了.

单个页面分析

(未完待续)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,039评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,223评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,916评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,009评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,030评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,011评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,934评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,754评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,202评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,433评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,590评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,321评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,917评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,568评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,738评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,583评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,482评论 2 352

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生_X自主阅读 15,979评论 3 119
  • https://cn.vuejs.org 转载 :OpenDigg awesome-github-vue 是由Op...
    文朝明阅读 6,589评论 0 38
  • 转载 :OpenDiggawesome-github-vue 是由OpenDigg整理并维护的Vue相关开源项目库...
    果汁密码阅读 23,116评论 8 124
  • 曾经以为 盛开的花朵是生命的极致 夜晚的黑暗有蛐蛐的奏鸣就是水墨画 张无忌的人生是最完美的描绘 有电视的下午是最幸...
    乐行僧阅读 365评论 0 1
  • 第一章 站在阴森森的大铁门外,白芨不禁抖擞着,卷起袖子,是一层鸡皮疙瘩。 这里,就是父亲大人说的借住的地方吗? 穿...
    唐山耶阅读 5,194评论 0 12