@hanomag_131

React/vue и cms?

Здравствуйте, в общем есть вопросы, можно ли писать фронт на реакте или вью и использовать какую-то cms? Можно ли любую cms использовать (mobx, битрикс)? Я изучил реакт и хотел бы его использовать при создании сайтов, но на фирме где я работаю пишут просто html страницы и закидывают их в cms, как я понял cms дают возможность клиенту самостоятельно после сдачи проекта менять содержимое сайта. Как вообще клиенты потом меняют содержимое сайта если нет cms, т.е есть только к примеру бэкенд на php, и фронт на реакте или вью?
  • Вопрос задан
  • 204 просмотра
Пригласить эксперта
Ответы на вопрос 3
@mletov
Погуглите Headless CMS.
Очень многие популярные CMS имеют свою headless версию, т е есть админка и есть REST API, которая отдается на основе данных, занесенных в эту админку.

Соответственно, морду вы можете писать на чем хотите: Angular, React, Vue и т д
И даже вообще можете разместить ее на другом домене.

Как вообще клиенты потом меняют содержимое сайта если нет cms, т.е есть только к примеру бэкенд на php, и фронт на реакте или вью?

На том же реакте тоже можно написать админку и через нее обновлять данные.
Ответ написан
firedragon
@firedragon
Senior .NET developer
Вот пример роутера для vue
// Imports
import Vue from 'vue'
import Router from 'vue-router'
import { authGuard, logoutHabdler } from '@/helpers'

Vue.use(Router)

const router = new Router({
  mode: 'history',
  base: process.env.BASE_URL,
  scrollBehavior: (to, from, savedPosition) => {
    if (to.hash) return { selector: to.hash }
    if (savedPosition) return savedPosition

    return { x: 0, y: 0 }
  },
  routes: [
    {
      path: '/logout',
      beforeEnter: logoutHabdler,
    },
    {
      path: '/',
      component: () => import('@/layouts/home/Index.vue'),
      children: [
        {
          path: '',
          name: 'Home',
          component: () => import('@/views/home/Index.vue'),
        },

        {
          path: 'about',
          name: 'About',
          component: () => import('@/views/about/Index.vue'),
        },
        {
          path: 'description',
          name: 'Description',
          component: () => import('@/views/description/Index.vue'),
        },
        {
          path: 'price',
          name: 'Price',
          component: () => import('@/views/price/Index.vue'),
        },
        {
          path: 'login',
          name: 'Login',
          component: () => import('@/views/login/Index.vue'),
        },
        {
          path: 'legal',
          name: 'Legal',
          component: () => import('@/views/home/Legal.vue'),
        },
        {
          path: 'eula',
          name: 'Eula',
          component: () => import('@/views/home/Eula.vue'),
        },
        {
          path: 'condition',
          name: 'Condition',
          component: () => import('@/views/home/Condition.vue'),
        },
        {
          path: 'disclosure/:id?',
          name: 'Disclosure',
          component: () => import('@/views/home/Disclosure.vue'),
        },
        {
          path: 'userlist/:id?',
          name: 'UserList',
          component: () => import('@/views/home/UserList.vue'),
        },
        {
          path: 'open/:id?',
          name: 'SuccessorList',
          component: () => import('@/views/home/SuccessorList.vue'),
        },
      ],
    },
    {
      path: '/user',
      component: () => import('@/layouts/user/Index.vue'),
      beforeEnter: authGuard,
      children: [
        {
          path: '',
          name: 'UserHome',
          component: () => import('@/views/user/Index.vue'),
        },
        {
          path: 'store/:id?',
          name: 'UserStore',
          component: () => import('@/views/user/Store.vue'),
        },
        {
          path: 'faq',
          name: 'UserFaq',
          component: () => import('@/views/user/Faq.vue'),
        },
        {
          path: 'messages',
          name: 'UserMessages',
          component: () => import('@/views/user/Messages.vue'),
        },
        {
          path: 'contacts',
          name: 'UserContacts',
          component: () => import('@/views/user/Contacts.vue'),
        },
        {
          path: 'profile',
          name: 'UserProfile',
          component: () => import('@/views/user/Profile.vue'),
        },
        {
          path: 'payment/:id',
          name: 'Payment',
          component: () => import('@/views/user/Payment.vue'),
        },
      ],
    },
    {
      path: '*',
      component: () => import('@/layouts/user/Page404.vue'),
      children: [
        {
          path: '*',
          name: 'Page404',
          component: () => import('@/views/user/Page404.vue'),
        },
       ],
  },
  ],
})

export default router


Вот конкретно этот кусок обрабатывает пути /user/store/какойто_идентификатор
{
          path: 'store/:id?',
          name: 'UserStore',
          component: () => import('@/views/user/Store.vue'),
        },


Соответственно вы можете создать путь для ваших страниц

далее
vue.config.js

const path = require('path')
const PrerenderSPAPlugin = require('@dreysolano/prerender-spa-plugin')
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer
const isDev = process.env.NODE_ENV !== 'production'
const plugins = isDev
  ? []
  : [
      new PrerenderSPAPlugin({
        // Required - The path to the webpack-outputted app to prerender.
        staticDir: path.join(__dirname, 'dist'),

        // Optional - The path your rendered app should be output to.
        // (Defaults to staticDir.)
        // outputDir: path.join(__dirname, 'prerendered'),

        // Optional - The location of index.html
        indexPath: path.join(__dirname, 'dist', 'index.html'),

        // Required - Routes to render.
        // Генерируйте пути из бд и билдите приложение какким нибудь скриптом на основе базы данных
        routes: ['/', '/about', '/description', '/price', '/about'],

        // Optional - Allows you to customize the HTML and output path before
        // writing the rendered contents to a file.
        // renderedRoute can be modified and it or an equivelant should be returned.
        // renderedRoute format:
        // {
        //   route: String, // Where the output file will end up (relative to outputDir)
        //   originalRoute: String, // The route that was passed into the renderer, before redirects.
        //   html: String, // The rendered HTML for this route.
        //   outputPath: String // The path the rendered HTML will be written to.
        // }
        postProcess (renderedRoute) {
          // Ignore any redirects.
          renderedRoute.route = renderedRoute.originalRoute
          // Basic whitespace removal. (Don't use this in production.)
          // renderedRoute.html = renderedRoute.html.split(/>[\s]+</gim).join('><');
          // Remove /index.html from the output path if the dir name ends with a .html file extension.
          // For example: /dist/dir/special.html/index.html -> /dist/dir/special.html
          if (renderedRoute.route.endsWith('.html')) {
            renderedRoute.outputPath = path.join(
              __dirname,
              'dist',
              renderedRoute.route,
            )
          }

          return renderedRoute
        },

        // Optional - Uses html-minifier (https://github.com/kangax/html-minifier)
        // To minify the resulting HTML.
        // Option reference: https://github.com/kangax/html-minifier#options-quick-reference
        minify: {
          collapseBooleanAttributes: true,
          collapseWhitespace: true,
          decodeEntities: true,
          keepClosingSlash: true,
          sortAttributes: true,
        },

        // Server configuration options.
        server: {
          // Normally a free port is autodetected, but feel free to set this if needed.
          port: 8001,
        },

        // The actual renderer to use. (Feel free to write your own)
        // Available renderers: https://github.com/Tribex/prerenderer/tree/master/renderers
        renderer: new Renderer({
          // Optional - The name of the property to add to the window object with the contents of `inject`.
          injectProperty: '__PRERENDER_INJECTED',
          // Optional - Any values you'd like your app to have access to via `window.injectProperty`.
          inject: {
            foo: 'bar',
            prerender: false,
          },

          // Optional - defaults to 0, no limit.
          // Routes are rendered asynchronously.
          // Use this to limit the number of routes rendered in parallel.
          maxConcurrentRoutes: 4,

          // Optional - Wait to render until the specified event is dispatched on the document.
          // eg, with `document.dispatchEvent(new Event('custom-render-trigger'))`
          // renderAfterDocumentEvent: 'custom-render-trigger',

          // Optional - Wait to render until the specified element is detected using `document.querySelector`
          renderAfterElementExists: '#app',

          // Optional - Wait to render until a certain amount of time has passed.
          // NOT RECOMMENDED
          renderAfterTime: 5000, // Wait 5 seconds.

          // Other puppeteer options.
          // (See here: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions)
          headless: true, // Display the browser window when rendering. Useful for debugging.
        }),
      }),
    ]

module.exports = {

  devServer: {
    disableHostCheck: true,
    progress: false,
    before () { // Output the same message as the react dev server to get the Spa middleware working with vue.
      console.info('Starting the development server...')
    },
  },
  transpileDependencies: ['vuetify'],

  configureWebpack: {
    plugins: [...plugins],
  },
}


В итоге получите SPA приложение с поисковой оптимизацией
Ответ написан
Комментировать
Sanes
@Sanes
Самый простой вариант потренироваться Wordpress REST API
Только ваш код вряд ли понравится поисковым системам. Для этого нужен SSR.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы