Некоторое время назад компания просто использовала Nuxt.js для создания проекта, и им поделились внутри компании, его разобрали и разослали. Эта статья больше подходит для студентов, которые плохо знакомы с Nuxt.js, и в основном рассказывает о некоторых конфигурациях, сделанных в процессе сборки. Студентам, впервые использующим Nuxt.js, рекомендуется сначала пройти его.официальная документация, а затем вернитесь к моей статье.
1. Зачем использовать Nuxt.js
Излишне говорить, что причина в том, чтобы использовать возможности рендеринга на стороне сервера Nuxt.js для решения проблемы SEO проекта Vue.
Во-вторых, простое сравнение проектов Nuxt.js и чистого Vue.
1. Различные целевые продукты после сборки
vue: dist
nuxt: .nuxt
2. Процесс рендеринга веб-страницы
vue: рендеринг на стороне клиента, сначала скачать js, а потом рендерить страницу через ajax;
nuxt: рендеринг на стороне сервера, который может быть выполнен сразу после того, как сервер соединит html, а первый экран может быть выполнен без инициирования ajax-запроса;
3. Процесс развертывания
vue: Просто разверните каталог dist на сервере, сервера нет, вам нужно использовать nginx в качестве веб-сервера;
NUXT: Необходимо развернуть почти все файлы на сервер (кроме Node_Modules, .git), со своим собственным сервером требуется управление PM2 (перезагрузка PM2 требуется для развертывания), если требуется доменное имя, NGINX требуется в качестве прокси.
4. Вход в проект
vue: /src/main.js
, вы можете выполнить некоторую работу по инициализации для глобальной регистрации в main.js;
nuxt: нет входного файла main.js, необходимо пройти операцию инициализации проектаnuxt.config.js
Выполните задания по настройке.
3. Создайте проект Nuxt.js с нуля и настройте его.
создать новый проект
Установить непосредственно с помощью строительных лесов:
npx create-nuxt-app <项目名>
Выберите один из вариантов выше.
Стоит упомянуть, что оChoose custom server framework
(Выберите фреймворк на стороне сервера), вы можете выбрать фреймворк на стороне сервера в соответствии с вашей бизнес-ситуацией, распространенными являются Express, Koa, по умолчанию None, то есть сервер Nuxt по умолчанию, я выбрал его здесьExpress
.
- Выберите сервер Nuxt по умолчанию, не будет генерироваться
server
Папки, все операции рендеринга на стороне сервера выполняются Nuxt за вас, и вам не нужно заботиться о деталях на стороне сервера. Опыт разработки ближе к проекту Vue. Недостатком является то, что вы не можете сделать некоторые настраиваемые операции на стороне сервера. - Выберите другую серверную структуру, например
Express
, будет генерироватьserver
Папка, которая поможет вам создать базовую среду сервера Node, в которой вы можете выполнять некоторые операции с узлом. Например, бизнес-потребности моей компании (разбор protobuf) используютExpress
, делаем слой форварда на реальный серверный апи, после парсинга протобуфа на стороне ноды возвращаем json данные клиенту.
а такжеChoose Nuxt.js modules
(выберите модуль nuxt.js), вы можете выбратьaxios
а такжеPWA
, если выбран axios, это поможет вам зарегистрироваться под экземпляром nuxt$axios
, чтобы можно было прямо в файле .vuethis.$axios
Обратиться с просьбой.
Включить проверку eslint
существуетnuxt.config.js
Добавьте в свойство сборки:
build: {
extend (config, ctx) {
// Run ESLint on save
if (ctx.isDev && ctx.isClient) {
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/
})
}
}
}
Таким образом, вы можете проверить синтаксис, сохранив файл во время разработки. Правила, используемые nuxt по умолчанию:@nuxtjs(Нижний слой происходит изeslint-config-standard), правила настраиваются в/.eslintrc.js
:
module.exports = {
root: true,
env: {
browser: true,
node: true
},
parserOptions: {
parser: 'babel-eslint'
},
extends: [
'@nuxtjs', // 该规则对应这个依赖: @nuxtjs/eslint-config
'plugin:nuxt/recommended'
],
// add your custom rules here
rules: {
'nuxt/no-cjs-in-config': 'off'
}
}
Если вы не привыклиstandard
команды правил могут@nuxtjs
Сменить на что-то другое.
Унифицированное управление переменными среды с помощью dotenv и @nuxtjs/dotenv
На стороне узла нам нравится использоватьdotenv
Чтобы управлять переменными окружения в проекте, поместите все переменные окружения в корневой каталог.env
середина.
- Установить:
npm i dotenv
- использовать:
- Создайте новый в корневом каталоге
.env
файл и запишите переменные среды, которыми необходимо управлять, например, адрес сервераAPIHOST
:
APIHOST=http://your_server.com/api
- существует
/server/index.js
Используется в (этот файл автоматически генерируется инфраструктурой сервера Express):
require('dotenv').config()
// 通过process.env即可使用
console.log(process.env.APIHOST) // http://your_server.com/api
На данный момент мы просто делаем сервер доступным.env
Файл только, клиент NUXT не может использовать.env
,согласно сДокументация Nuxt.jsСказал, что переменные среды клиента могут быть помещены вnuxt.config.js
середина:
module.exports = {
env: {
baseUrl: process.env.BASE_URL || 'http://localhost:3000'
}
}
Но если узлу и клиенту необходимо использовать одну и ту же переменную среды (одна и та же переменная SECRET будет использоваться, когда аутентификация API упоминается позже), им необходимоnuxt.config.js
а также.env
Поддерживать это поле сложнее, мы предпочитаем, чтобы переменные среды хранились только в одном месте, поэтому для решения этой проблемы я нашел@nuxtjs/dotenv
Эта зависимость позволяет клиентам nuxt использовать ее напрямую..env
, что оправдало наши ожидания.
- Установить:
npm i @nuxtjs/dotenv
Клиент также проходитprocess.env.XXX
использовать, больше нет примеров.
Таким образом, мы проходимdotenv
а также@nuxtjs/dotenv
Эти два пакета могут единообразно управлять переменными в среде разработки.
Кроме того,@nuxtjs/dotenv
Позволяет указать дополнительные файлы env при упаковке. Например, при разработке мы используем.env
, но онлайн-версия, которую мы упаковали, хочет использовать другие переменные среды.В этом случае вы можете указать другой файл во время сборки, например/.env.prod
, как раз вnuxt.config.js
Уточнить:
module.exports = {
modules: [
['@nuxtjs/dotenv', { filename: '.env.prod' }] // 指定打包时使用的dotenv
],
}
@nuxtjs/модуль тостов
Можно сказать, что Toast — это очень распространенная функция, и общие фреймворки пользовательского интерфейса будут иметь эту функцию. Но если ваш сайт не использует UI-фреймворк, а оповещение слишком уродливое, вы можете ввести этот модуль:
npm install @nuxtjs/toast
затем вnuxt.config.js
введен в
module.exports = {
modules: [
'@nuxtjs/toast',
['@nuxtjs/dotenv', { filename: '.env.prod' }] // 指定打包时使用的dotenv
],
toast: {// toast模块的配置
position: 'top-center',
duration: 2000
}
}
Таким образом, nuxt будет зарегистрирован во всем мире.$toast
Методы в вашем распоряжении, очень удобно:
this.$toast.error('服务器开小差啦~~')
this.$toast.error('请求成功~~')
API-аутентификация
Для некоторых конфиденциальных служб нам может потребоваться аутентификация API, чтобы люди не могли легко украсть API на стороне нашего узла, поэтому нам необходимо создать механизм аутентификации API. Распространенным решением является jwt, вы можете обратиться к введению г-на Руана:Начало работы с веб-токеном JSON. Если сцена относительно простая, вы можете спроектировать ее самостоятельно, вот идея:
- Клиент и узел объявляют секретный ключ в переменной среды: SECRET=xxxx, обратите внимание, что это конфиденциально;
- Когда клиент инициирует запрос, текущая временная метка (timestamp) и
SECRET
С помощью некоторого алгоритма сгенерируйтеsignature
, возьмите его с собой, когда вы попроситеtimestamp
а такжеsignature
; - Узел получает запрос и получает
timestamp
а такжеsignature
,Будуtimestamp
Используйте тот же алгоритм, что и ключ, чтобы снова сгенерировать подпись_signature
- по сравнению с запросом клиента
signature
Генерируется по тому же алгоритму, что и node_signature
Если это согласуется, это означает, что он проходит, в противном случае аутентификация не удалась.
Конкретные шаги:
Клиент инкапсулирует аксиомы в один слой:
import axios from 'axios'
import sha256 from 'crypto-js/sha256'
import Base64 from 'crypto-js/enc-base64'
// 加密算法,需安装crypto-js
function crypto (str) {
const _sign = sha256(str)
return encodeURIComponent(Base64.stringify(_sign))
}
const SECRET = process.env.SECRET
const options = {
headers: { 'X-Requested-With': 'XMLHttpRequest' },
timeout: 30000,
baseURL: '/api'
}
// The server-side needs a full url to works
if (process.server) {
options.baseURL = `http://${process.env.HOST || 'localhost'}:${process.env.PORT || 3000}/api`
options.withCredentials = true
}
const instance = axios.create(options)
// 对axios的每一个请求都做一个处理,携带上签名和timestamp
instance.interceptors.request.use(
config => {
const timestamp = new Date().getTime()
const param = `timestamp=${timestamp}&secret=${SECRET}`
const sign = crypto(param)
config.params = Object.assign({}, config.params, { timestamp, sign })
return config
}
)
export default instance
Затем напишите промежуточное ПО аутентификации на стороне сервера,/server/middleware/verify.js
:
const sha256 = require('crypto-js/sha256')
const Base64 = require('crypto-js/enc-base64')
function crypto (str) {
const _sign = sha256(str)
return encodeURIComponent(Base64.stringify(_sign))
}
// 使用和客户端相同的一个秘钥
const SECRET = process.env.SECRET
function verifyMiddleware (req, res, next) {
const { sign, timestamp } = req.query
// 加密算法与请求时的一致
const _sign = crypto(`timestamp=${timestamp}&secret=${SECRET}`)
if (_sign === sign) {
next()
} else {
res.status(401).send({
message: 'invalid token'
})
}
}
module.exports = { verifyMiddleware }
Наконец, укажите это промежуточное ПО в маршруте, который требует аутентификации,/server/index.js
:
const { Router } = require('express')
const { verifyMiddleware } = require('../middleware/verify.js')
const router = Router()
// 在需要鉴权的路由加上
router.get('/test', verifyMiddleware, function (req, res, next) {
res.json({name: 'test'})
})
Обработка статических файлов
Есть корневой каталог/static
Папка, мы надеемся, что к файлам в ней можно получить доступ напрямую через URL-адрес, который должен быть в/server/index.js
Добавьте предложение:
const express = require('express')
const app = express()
app.use('/static', express.static('static'))
В-четвертых, связанные с развитием Nuxt
Жизненный цикл
Nuxt продлевает жизненный цикл Vue примерно следующим образом:
export default {
middleware () {}, //服务端
validate () {}, // 服务端
asyncData () {}, //服务端
fetch () {}, // store数据加载
beforeCreate () { // 服务端和客户端都会执行},
created () { // 服务端和客户端都会执行 },
beforeMount () {},
mounted () {} // 客户端
}
asyncData
Этот метод является одним из самых больших преимуществ Nuxt. Возможность рендеринга на стороне сервера здесь. Обязательно используйте этот метод при рендеринге в первый раз. asyncData будет передавать параметр контекста, через который вы можете получить некоторую информацию, например:
export default {
asyncData (ctx) {
ctx.app // 根实例
ctx.route // 路由实例
ctx.params //路由参数
ctx.query // 路由问号后面的参数
ctx.error // 错误处理方法
}
}
Ошибка рендеринга и ошибка запроса AJAX
- ошибка рендеринга asyncData
использоватьasyncData
При подключении он может не отображаться из-за ошибки сервера или ошибки API. В настоящее время страница не была обработана. В этой ситуации необходимо выполнить некоторую обработку. При обнаружении ошибки asyncData перейдите на страницу ошибки. обеспечиваетcontext.error
Этот метод используется для обработки ошибок. Вызовите этот метод в asyncData, чтобы перейти на страницу с ошибкой.
export default {
async asyncData (ctx) {
// 尽量使用try catch的写法,将所有异常都捕捉到
try {
throw new Error()
} catch {
ctx.error({statusCode: 500, message: '服务器开小差了~' })
}
}
}
Таким образом, когда возникает исключение, оно переходит кстраница ошибки по умолчанию, на страницу ошибки можно попасть через/layout/error.vue
настроить.
Здесь есть проблема,context.error
Параметры должны быть примерно такими{ statusCode: 500, message: '服务器开小差了~' }
,statusCode
Должен быть код состояния http,
И ошибки, возвращаемые нашим сервером, часто имеют другие пользовательские коды, такие как{resultCode: 10005, resultInfo: '服务器内部错误' }
, вам нужно преобразовать возвращенную ошибку API.
Для удобства я ввел/plugins/ctx-inject.js
Зарегистрируйте глобальную обработку ошибок для контекста:context.$errorHandler(err)
. Инъекционный метод может означать:Внедрить $root и контекст,ctx-inject.js
:
// 为context注册全局的错误处理事件
export default (ctx, inject) => {
ctx.$errorHandler = err => {
try {
const res = err.data
if (res) {
// 由于nuxt的错误页面只能识别http的状态码,因此statusCode统一传500,表示服务器异常。
ctx.error({ statusCode: 500, message: res.resultInfo })
} else {
ctx.error({ statusCode: 500, message: '服务器开小差了~' })
}
} catch {
ctx.error({ statusCode: 500, message: '服务器开小差了~' })
}
}
}
затем вnuxt.config.js
Используйте этот плагин:
export default {
plugins: [
'~/plugins/ctx-inject.js'
]
}
После завершения инъекции мы можемasyncData
Он используется следующим образом:
export default {
async asyncData (ctx) {
// 尽量使用try catch的写法,将所有异常都捕捉到
try {
throw new Error()
} catch(err) {
ctx.$errorHandler(err)
}
}
}
- Ошибка в ajax-запросе
Для исключений ajax в это время страница была обработана, и нет необходимости переходить на страницу ошибки при возникновении ошибки.this.$toast.error(res.message)
Тост может выйти.
способ загрузки
nuxt имеет встроенную верхнюю часть страницыСтиль индикатора загрузкиРекомендуется, обеспечивая возможность перехода на страницу.
Открыть:this.$nuxt.$loading.start()
Заканчивать:this.$nuxt.$loading.finish()
Развертывание пакета
Вообще говоря, вы можете упаковать его локально перед развертыванием, запустить его локально, чтобы подтвердить его правильность, а затем загрузить его на сервер для развертывания. Заказ:
// 打包
npm run build
// 本地跑
npm start
Кроме node_modules, .git, .env, залить все остальные файлы на сервер, а потом передатьpm2
Для управления можно создать корневой каталог проектаpm2.json
Простое обслуживание:
{
"name": "nuxt-test",
"script": "./server/index.js",
"instances": 2,
"cwd": "."
}
Затем настройте переменные среды производственной среды, обычно напрямую используя.env.prod
Конфигурация:cp ./.env.prod ./.env
.
Развернут в первый раз или имеет новый пакет зависимостей, который должен быть на сервереnpm install
один раз, затем вы можете использоватьpm2
Запустите процесс:
// 项目根目录下运行
pm2 start ./pm2.json
При необходимости можно настроить загрузку на автоматический запуск pm2:pm2 save && pm2 startup
.
Следует отметить, что каждое развертывание должно перезапускать процесс:pm2 reload nuxt-test
.
5. Наконец
Nuxt.js представляет Node, аnuxt.config.js
замененыmain.js
Некоторые функции, структура каталогов и проект vue немного отличаются, и было добавлено много соглашений, которые могут быть очень незнакомы начинающим студентам.Для получения дополнительной информации вы должны прочитать официальные документы.
исходный код демо:fengxianqi/front_end-demos/src/nuxt-test.