Size: a a a

Nuxt.js — русскоговорящее сообщество

2020 May 03

А

Александр in Nuxt.js — русскоговорящее сообщество
RusaXXX
Но этот вариант отлично ложиться на моц сервис. У нас нода это bff к сервисам. На нем нукст и обращения к апи других сервисов
пишу более развёрнуто полное решение
источник

А

Александр in Nuxt.js — русскоговорящее сообщество
Реализация Nuxt Advanced SSR:
1. подключаем обёртки серверного и клиентского апи
nuxt.config.js
plugins: [
   '~/plugins/api-context.server.js' // подключится на только для серверной части
   , '~/plugins/api-context.client.js' // подключится на только для клиентской части
],

2. Клиентское апи забирает данные по http через axios
api-context.client.js
export default (context, inject) => {
   inject('api', async (controller, method, params) => {
       ...
       return await context.$axios['$' + (params ? 'post' : 'get')]('/api/' + controller + '/' + method, params);

3. Серверное апи подключает файл соответствующего контроллера, передаёт ему соединение MySQL и выполняется непосредственно на сервере.
api-context.server.js
export default (context, inject) => {
   inject('api', async (controller, method, params) => {
       ...
       let db = await db_pool.getConnection();
       let api = require('~/api/' + controller);
       ...
       let result = await api[method](db, params);
       ...
       return result;

4. Для обработки клиентских запросов поднимется соответствующее serverMiddleware
nuxt.config.js
serverMiddleware: [
   ...
   {path: '/api', handler: body_parser.json()},
   {path: '/api', handler: (req, res, next) => {
       const url = require('url');
       req.query = url.parse(req.url, true).query;
       next();
   }},
   ...
   {path: '/api', handler: '~/serverMiddleware/api-server.js'},
   ...

5. api-server для клиентских запросов выглядит примерно так
/serverMiddleware/api-server.js
export default async(req, res, next) => {
   ...
   let db = await db_pool.getConnection();
   let url = parseAndCheck(req._parsedUrl.pathname);
   url = url.split('/');
   let method = url.pop();
   let controller = url.join('/');
   let api = require('~/api/' + controller);
   let result = await api[method](db, req.params);
   res.end(JSON.stringify(result));
   ...

6. Пример контроллера:
/api/items.js
let index = async db => {
   let [results, schema] = await db.query(`SELECT * FROM items`);

   return {items: results, schema: db.schemaFromQuery(schema)};
};

export {index}

7. вызов контроллера в компоненте
/components/Items.vue
<template>
   <div>
       <b-button @click.prevent="$fetch">Refresh</b-button>
       <b-table :items="items"></b-table>
   </div>
</template>
<script>
   export default {
       data () {
           return {
               items: []
           }
       }
       , async fetch () {
           let res = await this.$api('items', 'index');
           this.items = res.items;
       }
   }
</script>

Сейчас при заходе на страницу и серверном рендеренге, http запросы никуда отправляться не будут, Нода напрямую вызовет метод контроллера, который сделает запрос к MySQL, а при нажатии на кнопку Refresh, уйдёт запрос
/api/items
и serverMiddleware вернёт данные по http
источник

Д

Деда in Nuxt.js — русскоговорящее сообщество
Александр
Реализация Nuxt Advanced SSR:
1. подключаем обёртки серверного и клиентского апи
nuxt.config.js
plugins: [
   '~/plugins/api-context.server.js' // подключится на только для серверной части
   , '~/plugins/api-context.client.js' // подключится на только для клиентской части
],

2. Клиентское апи забирает данные по http через axios
api-context.client.js
export default (context, inject) => {
   inject('api', async (controller, method, params) => {
       ...
       return await context.$axios['$' + (params ? 'post' : 'get')]('/api/' + controller + '/' + method, params);

3. Серверное апи подключает файл соответствующего контроллера, передаёт ему соединение MySQL и выполняется непосредственно на сервере.
api-context.server.js
export default (context, inject) => {
   inject('api', async (controller, method, params) => {
       ...
       let db = await db_pool.getConnection();
       let api = require('~/api/' + controller);
       ...
       let result = await api[method](db, params);
       ...
       return result;

4. Для обработки клиентских запросов поднимется соответствующее serverMiddleware
nuxt.config.js
serverMiddleware: [
   ...
   {path: '/api', handler: body_parser.json()},
   {path: '/api', handler: (req, res, next) => {
       const url = require('url');
       req.query = url.parse(req.url, true).query;
       next();
   }},
   ...
   {path: '/api', handler: '~/serverMiddleware/api-server.js'},
   ...

5. api-server для клиентских запросов выглядит примерно так
/serverMiddleware/api-server.js
export default async(req, res, next) => {
   ...
   let db = await db_pool.getConnection();
   let url = parseAndCheck(req._parsedUrl.pathname);
   url = url.split('/');
   let method = url.pop();
   let controller = url.join('/');
   let api = require('~/api/' + controller);
   let result = await api[method](db, req.params);
   res.end(JSON.stringify(result));
   ...

6. Пример контроллера:
/api/items.js
let index = async db => {
   let [results, schema] = await db.query(`SELECT * FROM items`);

   return {items: results, schema: db.schemaFromQuery(schema)};
};

export {index}

7. вызов контроллера в компоненте
/components/Items.vue
<template>
   <div>
       <b-button @click.prevent="$fetch">Refresh</b-button>
       <b-table :items="items"></b-table>
   </div>
</template>
<script>
   export default {
       data () {
           return {
               items: []
           }
       }
       , async fetch () {
           let res = await this.$api('items', 'index');
           this.items = res.items;
       }
   }
</script>

Сейчас при заходе на страницу и серверном рендеренге, http запросы никуда отправляться не будут, Нода напрямую вызовет метод контроллера, который сделает запрос к MySQL, а при нажатии на кнопку Refresh, уйдёт запрос
/api/items
и serverMiddleware вернёт данные по http
Кеширование, очереди, сервисы?
источник

Д

Деда in Nuxt.js — русскоговорящее сообщество
Пункт 6 особенно. Бэк это не только обращение к базе данных
источник

Д

Деда in Nuxt.js — русскоговорящее сообщество
Для пет проекта может и пойдёт но не для какого то сложного
источник

Д

Деда in Nuxt.js — русскоговорящее сообщество
По мне это все равно что на swift написать ios приложение, и на нем же бэк. Вроде можно но зачем?
источник

А

Александр in Nuxt.js — русскоговорящее сообщество
@DreaMinder, сделал замеры
источник

А

Александр in Nuxt.js — русскоговорящее сообщество
Замеры на тестовой страничке. Страничка как из пункта 7
1) запрос страницы с пустым fetch - в среднем около 100мс, притом разброс ~ от 60 до 200
2) запрос страницы, fetch с одним вызовом апи моим способом
async fetch () {
   let res = await this.$api('items', 'index');
   this.items = res.items;
}
в среднем - 220мс, разброс от 190 до 300
3) вызов fetch кнопкой Refresh - ~38мс
4) запрос страницы, fetch с 10ю вызовами апи моим способом
async fetch () {
   let p_res1 = this.$api('items', 'index');
   let p_res2 = this.$api('items', 'index');
   let p_res3 = this.$api('items', 'index');
   let p_res4 = this.$api('items', 'index');
   let p_res5 = this.$api('items', 'index');
   let p_res6 = this.$api('items', 'index');
   let p_res7 = this.$api('items', 'index');
   let p_res8 = this.$api('items', 'index');
   let p_res9 = this.$api('items', 'index');
   let p_res10 = this.$api('items', 'index');

   let [res1, res2, res3, res4, res5, res6, res7, res8, res9, res10]
       = await Promise.all([
           p_res1, p_res2, p_res3, p_res4, p_res5, p_res6, p_res7, p_res8, p_res9, p_res10
   ]);

   this.items = res1.items;
}
в среднем около 250мс, но тоже разные значения видел от 210 до 450

5) то же что и 4, но вызов апи не напрямую, а через axios
в среднем 400мс, самое минимальное видел 371
источник

А

Александр in Nuxt.js — русскоговорящее сообщество
т.е. финальные цифры 250 и 400
источник

BS

Bogdan Saliuk in Nuxt.js — русскоговорящее сообщество
Александр
т.е. финальные цифры 250 и 400
Это не так работает :)
источник

D

DreaMinder in Nuxt.js — русскоговорящее сообщество
Александр
Замеры на тестовой страничке. Страничка как из пункта 7
1) запрос страницы с пустым fetch - в среднем около 100мс, притом разброс ~ от 60 до 200
2) запрос страницы, fetch с одним вызовом апи моим способом
async fetch () {
   let res = await this.$api('items', 'index');
   this.items = res.items;
}
в среднем - 220мс, разброс от 190 до 300
3) вызов fetch кнопкой Refresh - ~38мс
4) запрос страницы, fetch с 10ю вызовами апи моим способом
async fetch () {
   let p_res1 = this.$api('items', 'index');
   let p_res2 = this.$api('items', 'index');
   let p_res3 = this.$api('items', 'index');
   let p_res4 = this.$api('items', 'index');
   let p_res5 = this.$api('items', 'index');
   let p_res6 = this.$api('items', 'index');
   let p_res7 = this.$api('items', 'index');
   let p_res8 = this.$api('items', 'index');
   let p_res9 = this.$api('items', 'index');
   let p_res10 = this.$api('items', 'index');

   let [res1, res2, res3, res4, res5, res6, res7, res8, res9, res10]
       = await Promise.all([
           p_res1, p_res2, p_res3, p_res4, p_res5, p_res6, p_res7, p_res8, p_res9, p_res10
   ]);

   this.items = res1.items;
}
в среднем около 250мс, но тоже разные значения видел от 210 до 450

5) то же что и 4, но вызов апи не напрямую, а через axios
в среднем 400мс, самое минимальное видел 371
на каждом вызове апи аутентификация? а на прямых вызовах ее нет? ну может быть, ок, но юзкейс очень редкий
источник

D

DreaMinder in Nuxt.js — русскоговорящее сообщество
я бы в любом случае сделал прослойку BFF будь у меня более 3х одновременных вызовов апи на страницу
источник

А

Александр in Nuxt.js — русскоговорящее сообщество
DreaMinder
на каждом вызове апи аутентификация? а на прямых вызовах ее нет? ну может быть, ок, но юзкейс очень редкий
не, вызов апи простой довольно
- чтение 200 файлов
- и читаем из БД
источник

А

Александр in Nuxt.js — русскоговорящее сообщество
никаких ни авторизаций ничего нет
источник

А

Александр in Nuxt.js — русскоговорящее сообщество
что за прослойка BFF ?
источник

D

DreaMinder in Nuxt.js — русскоговорящее сообщество
backend for frontend. Чтобы фронт запрашивал одним запросом сагрегированные данные
источник

BS

Bogdan Saliuk in Nuxt.js — русскоговорящее сообщество
DreaMinder
backend for frontend. Чтобы фронт запрашивал одним запросом сагрегированные данные
а если данные жирные?
источник

AB

Artem Biryukov in Nuxt.js — русскоговорящее сообщество
Александр
Реализация Nuxt Advanced SSR:
1. подключаем обёртки серверного и клиентского апи
nuxt.config.js
plugins: [
   '~/plugins/api-context.server.js' // подключится на только для серверной части
   , '~/plugins/api-context.client.js' // подключится на только для клиентской части
],

2. Клиентское апи забирает данные по http через axios
api-context.client.js
export default (context, inject) => {
   inject('api', async (controller, method, params) => {
       ...
       return await context.$axios['$' + (params ? 'post' : 'get')]('/api/' + controller + '/' + method, params);

3. Серверное апи подключает файл соответствующего контроллера, передаёт ему соединение MySQL и выполняется непосредственно на сервере.
api-context.server.js
export default (context, inject) => {
   inject('api', async (controller, method, params) => {
       ...
       let db = await db_pool.getConnection();
       let api = require('~/api/' + controller);
       ...
       let result = await api[method](db, params);
       ...
       return result;

4. Для обработки клиентских запросов поднимется соответствующее serverMiddleware
nuxt.config.js
serverMiddleware: [
   ...
   {path: '/api', handler: body_parser.json()},
   {path: '/api', handler: (req, res, next) => {
       const url = require('url');
       req.query = url.parse(req.url, true).query;
       next();
   }},
   ...
   {path: '/api', handler: '~/serverMiddleware/api-server.js'},
   ...

5. api-server для клиентских запросов выглядит примерно так
/serverMiddleware/api-server.js
export default async(req, res, next) => {
   ...
   let db = await db_pool.getConnection();
   let url = parseAndCheck(req._parsedUrl.pathname);
   url = url.split('/');
   let method = url.pop();
   let controller = url.join('/');
   let api = require('~/api/' + controller);
   let result = await api[method](db, req.params);
   res.end(JSON.stringify(result));
   ...

6. Пример контроллера:
/api/items.js
let index = async db => {
   let [results, schema] = await db.query(`SELECT * FROM items`);

   return {items: results, schema: db.schemaFromQuery(schema)};
};

export {index}

7. вызов контроллера в компоненте
/components/Items.vue
<template>
   <div>
       <b-button @click.prevent="$fetch">Refresh</b-button>
       <b-table :items="items"></b-table>
   </div>
</template>
<script>
   export default {
       data () {
           return {
               items: []
           }
       }
       , async fetch () {
           let res = await this.$api('items', 'index');
           this.items = res.items;
       }
   }
</script>

Сейчас при заходе на страницу и серверном рендеренге, http запросы никуда отправляться не будут, Нода напрямую вызовет метод контроллера, который сделает запрос к MySQL, а при нажатии на кнопку Refresh, уйдёт запрос
/api/items
и serverMiddleware вернёт данные по http
Ужос
источник

Д

Деда in Nuxt.js — русскоговорящее сообщество
DreaMinder
backend for frontend. Чтобы фронт запрашивал одним запросом сагрегированные данные
Ммм, когда каждый компонент на странице сам себе запрашивает данные это плохо?
источник

D

DreaMinder in Nuxt.js — русскоговорящее сообщество
Деда
Ммм, когда каждый компонент на странице сам себе запрашивает данные это плохо?
depends, бывает и плохо и хорошо
источник