一、为什么选择Nuxt.js
多数是基于webpack构建的项目,编译出来的html文件,资源文件都被打包到js中,以下图404页面代码为例。从代码中可以看出,这样的页面是不利于 搜索引擎优化(SEO, Search Engine Optimization) ,并且 内容到达时间(time-to-content) (或称之为首屏渲染时长)也有很大的优化空间。为了解决以上问题,引入了 Nuxt.js 框架。
vue官网对于Nuxt.js也是很推荐的,除此之外,Nuxt.js的开发者积极活跃,版本迭代迅速。经过一系列rc版本后,终于在1月9日发布了 v1.0.0 正式版本!
图1. 使用webpack构建的HTML(代码已格式化)
图2. 使用 Nuxt.js 构建的HTML(代码已格式化)
二、Nuxt.js 简介Nuxt.js 是一个基于 Vue.js 的通用应用框架,它预设了利用 Vue.js 开发 服务端渲染(SSR, Server Side Render) 的应用所需要的各种配置,同时也可以一键生成静态站点。
作为框架,Nuxt.js 为 客户端/服务端 这种典型的应用架构模式提供了许多有用的特性,例如异步数据加载、中间件支持、布局支持等。区别于其他 vue SSR 框架,Nuxt.js 有以下比较明显的特性。
自动代码分层
强大的路由功能,支持异步数据(路由无需额外配置)
HTML头部标签管理(依赖 vue-meta 实现)
内置 webpack 配置,无需额外配置
三、项目实战1、项目创建官方提供了基于 vue-cli 脚手架工具,常用的有如下三个,更多脚手架工具可以查看nuxt-community 。本项目使用的是 express-template。
vue init nuxt-community/starter-template <project-name> vue init nuxt-community/koa-template <project-name> vue init nuxt-community/express-template <project-name>
2、开发
1)目录结构
├─assets 资源目录,未编译的静态资源如less、js ├─components 组件目录 ├─layouts 布局目录 ├─mock mock数据 ├─node_modules ├─pages 页面目录 ├─index.vue ├─.... ├─plugins 插件 ├─server express服务 ├─static 静态文件目录 ├─store vuex store ├─utils 工具方法
2)配置
Nuxt.js 默认的配置涵盖了大部分使用情形,也可通过修改 nuxt.config.js 来覆盖默认配置。
// nuxt.config.js 文件配置 const path = require('path') module.exports = { // Headers of the page head: { title: '默认共用title', meta: [ { charset: 'utf-8' }, { 'http-equiv': 'pragma', content: 'no-cache' }, { 'http-equiv': 'cache-control', content: 'no-cache' }, { 'http-equiv': 'expires', content: '0' }, { content: 'telephone=no', name: 'format-detection' } ], // html head 中创建 script 标签 script: [ { innerHTML: require('./assets/js/flexible_nuxt'), type: 'text/javascript', charset: 'utf-8'} ], // 不对<script>标签中内容做转义处理 __dangerouslyDisableSanitizers: ['script'] }, // Global CSS css: ['~/assets/css/reset.css', '~/assets/css/main.less'], // Global env env: { __ENV: process.env.__ENV }, build: { vendor: ['axios'], postcss: [ require('postcss-px2rem')({ remUnit: 75 }) ], extend (config, ctx) { if (ctx.isClient) { // 拓展 webpack 配置 config.entry['polyfill'] = ['babel-polyfill'] config.module.rules.push({ enforce: 'pre', test: /\.(js|vue)$/, loader: 'eslint-loader', exclude: /(node_modules)/ }) // 添加 alias 配置 Object.assign(config.resolve.alias, { 'utils': path.resolve(__dirname, 'utils') }) } } }, plugins: [{src: '~plugins/toast', ssr: false}, {src: '~plugins/dialog', ssr: false}] }
HTML头部标签管理:
Nuxt.js 通过 vue-meta 实现头部标签管理,在 nuxt.config.js 中的 head 配置。所有的页面都会走这个配置,如果想要修改某一页面的title,可以在 pages/**.vue 文件下,添加如下配置,这时该页面的标题就变成了“收车费”,其余页面还保持原有标题不变。
在config header配置中, __dangerouslyDisableSanitizers: ['script'] 主要是为了不对<script>标签中内容做转义处理。看下面的例子🌰:
head: { title: 'myTitle', meta: [ { charset: 'utf-8' }, { 'http-equiv': 'pragma', content: 'no-cache' }, { 'http-equiv': 'cache-control', content: 'no-cache' }, { 'http-equiv': 'expires', content: '0' }, { content: 'telephone=no', name: 'format-detection' } ], script: [ { innerHTML: 'console.log("hello")', type: 'text/javascript', charset: 'utf-8'} ] },
生成 html:
复制代码 代码如下:
<script data-n-head="true" type="text/javascript" charset="utf-8">console.log("hello")</script>
我们发现 vue-meta 把引号做了转义处理,加入 __dangerouslyDisableSanitizers: ['script'] 后,就不会再对这些字符做转义了,该字段使用需慎重!
3)路由
Nuxt.js 依据 pages 目录结构,自动生成 vue-router 模块的路由配置。
假设 pages 的目录结构如下:
那么,Nuxt.js 自动生成的路由配置如下:
嵌套路由: