Некоторое время обдумывал идею личного проекта. Закончил использование Vue просто для удовольствия (никаких технических причин для этого выбора). Детали этого проекта скрыты, но самое главное, мне нужно было:

  • Управление состоянием
  • Создавать динамические маршруты
  • Обработка на сервер

SSR (рендеринг на стороне сервера) был моей главной заботой - о состоянии и маршрутизации можно было позаботиться за пару минут.

Самым быстрым путем был плагин предварительного рендеринга Webpack. Но не слишком быстро; Если в вашем приложении много динамических маршрутов, этот плагин может быть не лучшим выбором, потому что он не был для меня

Помимо собственной реализации решения с помощью vue-server-renderer, единственным вариантом, который у меня оставался, был Nuxt.

Nuxt для ленивых

Да, если вы меня встречали, значит, вы знаете, какой я ленивый. Что еще хуже, мой мозг категорически отказывается идти долгим путем к проблемам, когда есть проверенный и надежный ярлык.

Nuxt позволяет вам просто написать приложение Vue с рендерингом на сервере, не ограничиваясь низкоуровневой реализацией. Он был вдохновлен Next, который широко известен в сообществе React как средство решения связанных проблем.

SSR Gotchas

Nuxt звучит настолько интересно, что вы сразу бы сразу к нему применили. К сожалению, в SSR есть некоторые ошибки, и использование таких инструментов, как Nuxt или Next (в зависимости от обстоятельств) не скрывает этих ошибок; вам еще нужно с ними разобраться.

Первое, с чем вы наверняка столкнетесь, - это попытка получить доступ к объектам browser или document еще до того, как они будут готовы. Помните, что ваш шаблон сначала отображается на сервере, а не на клиенте. Когда вы пытаетесь получить доступ к этим объектам слишком рано, сервер выдает ошибку, подобную следующей, в зависимости от того, в каком случае:

> window is not defined

Возможно, вы захотите держаться подальше от таких объектов и обращаться к ним только с помощью методов жизненного цикла, таких как mounted, что гарантирует готовность клиента. Плохая новость в том, что большинство библиотек, которые вы импортируете в свой проект, будут пытаться получить доступ window или document до того, как приложение будет отображено в браузере.

На решение этой проблемы у меня ушло несколько часов отладки, поиска в Google, бесконечных открытых вкладок Chrome и поиска проблем с Github.

Это был мой способ обойти это ...

Первая попытка: дождитесь рендеринга браузера

Предполагая, что у вас есть следующая логика компонентов:

// Problem here
window.globalVar = 'global variable'
export default {
  mounted() {
    console.log(window.globalVar);
  },
}

К сожалению, окно будет неопределенным. Большинство плагинов, таких как vue-select (которые я использовал), обращаются к объекту окна так рано, как это.

Nuxt предоставляет флаг для объекта process, который вы можете использовать, чтобы проверить, установлен ли браузер. Вышеуказанная проблема будет легко устранена:

if (process.browser) {
  window.globalVar = 'global variable'
}
export default {
  mounted() {
    console.log(window.globalVar);
  },
}

Следовательно, в случаях, когда вы используете плагин, который обращается к объекту окна сразу, как они импортируются, это должно работать:

let pluginLib;
if (process.browser) {
  pluginLib = require('plugin-name');
}
export default {
  mounted() {
    console.log(pluginLib);
  },
}

Не забудьте включить плагин в массив vendor сборки:

// nuxt.config.js
build: {
  vendor: ['plugin-name']
}

Это будет работать для вас, пока ваша сторонняя библиотека не станет той, которая должна внедрить шаблон в представление (что и делает большинство библиотек пользовательского интерфейса). В моем случае это был vue-select. По некоторым причинам возникла следующая ошибка:

> You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

Это привело к моей второй попытке.

Вторая попытка: плагины Vue

С подсказками, которые я почерпнул из этой проблемы, я смог написать плагин, который загружается только на клиенте. Сначала создайте плагин в папке plugins:

import Vue from 'vue'
import vSelect from 'vue-select';
const VueSelect = {
  install(Vue, options) {
    Vue.component('v-select', vSelect)
  }
};
Vue.use(VueSelect);
export default VueSelect;

Затем сообщите Nuxt, что это следует загружать только в браузере, используя свойство ssr и задав значение false.

// nuxt.config.js
plugins: [
  
  { src: '~plugins/vue-select', ssr: false }
]

Конечно, не загружайте как файл поставщика:

// nuxt.config.js
build: {
   vendor: ['vue-select']
}

Не стесняйтесь сообщить мне, если вы застряли с интеграцией другого плагина, и я могу попытаться помочь.

Ваше здоровье!