Укажите URL-путь в качестве переменной для приложений REACT SSR, созданных вручную (т. Е. НЕ с использованием Next JS) - PullRequest
0 голосов
/ 09 июля 2020

Примечание. Я не использую Next JS для своего приложения SSR. Я также не использовал приложение create-react-app для создания своего приложения.

У меня есть приложение React Server Side Rendered (SSR), которое было создано вручную (в отличие от использования такого инструмента, как create-react -приложение). Я использую WebPack для объединения кода на стороне сервера и кода на стороне клиента. Я прошел отличный курс Udemy https://www.udemy.com/course/server-side-rendering-with-react-and-redux/, чтобы понять, как создать приложение React SSR

My Application

Структура приложения

enter image description here

webpack.base.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif)$/i,
        use: 'file-loader',
      },
      {
        test: /\.(js|jsx)$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
        query: {
          cwd: __dirname,
        },
      },
    ],
  },

  resolve: {
    extensions: ['.js', '.jsx'],
  },
};

webpack.client.config.js

const path = require('path');
const { merge } = require('webpack-merge');
const CopyPlugin = require('copy-webpack-plugin');
const baseConfig = require('./webpack.base.config.js');

const config = {

  entry: './src/client/client.jsx',

  output: {
    filename: 'client-bundle.js',
    path: path.resolve(__dirname, 'public'),
  },

  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(__dirname, 'src', 'styles'),
          to: path.resolve(__dirname, 'public'),
        },
      ],
    }),
  ],
};

module.exports = merge(baseConfig, config);

webpack.server.config.js

const path = require('path');
const { merge } = require('webpack-merge');
const webpackNodeExternals = require('webpack-node-externals');
const baseConfig = require('./webpack.base.config.js');

const config = {
  target: 'node',

  entry: './src/server/server.js',

  output: {
    filename: 'server-bundle.js',
    path: path.resolve(__dirname, 'build'),
  },

  externals: [webpackNodeExternals()],
};

module.exports = merge(baseConfig, config);

Routes

{
    ...Home,
    path: '/',
    exact: true,
},
{
    ...Page1,
    path: '/page1',
    exact: true,
},

Client Side Routing


  ...

Server Side Routing


    ...

Server Side generated HTML template


  
      $ {content} 

Ответы [ 2 ]

1 голос
/ 09 июля 2020

Вы можете просто добавить переменную env basePath, а затем использовать ее для установки ваших маршрутов.

Routes

{
    ...Home,
    path: `${process.env.basePath}/`,
    exact: true,
},
{
    ...Page1,
    path: `${process.env.basePath}/page1`,
    exact: true,
},

Теперь, если ваш basePath равен '/ a / b ', ваш компонент индекса будет доступен на yourdomain/a/b/, а page1 будет доступен на yourdomain/a/b/page1

0 голосов
/ 14 июля 2020

Сообщение Hassaan Tauqir выше, которое я пометил как ответ, помогло мне уточнить решение. Спасибо Hassaan.

package. json

Измените сценарии для среды PRODUCTION, чтобы указать BASE_URL.

"prod:build-server-bundle": "cross-env BASE_URL=/a/b webpack --config webpack.server.config.js",
"prod:build-client-bundle": "cross-env BASE_URL=/a/b webpack --config webpack.client.config.js",

Примечание: вы должны использовать «cross-env», иначе это не будет работать во всех операционных системах, поэтому мне пришлось сначала установить «cross-env»

npm install cross-env

Я оставил сценарии РАЗРАБОТКИ без изменений, как и я. не нужен путь при локальном тестировании

"dev:build-server-bundle": "webpack --config webpack.server.config.js --watch",
"dev:build-client-bundle": "webpack --config webpack.client.config.js --watch",

webpack.base.config. js

Чтение в BASE_URL

«BASE_URL» доступен в «webpack.base.config. js». Я добавил код, чтобы я мог обрабатывать "BASE_URL", указанный в конце sla sh или нет.

// Set up the BASE_URL parameter, ensuring it does not have a trailing slash
let BASE_URL = '';
if (process.env.BASE_URL) {
  BASE_URL = process.env.BASE_URL.toString().trim();
  if (BASE_URL.substr(-1) === '/') {
    BASE_URL = BASE_URL.substr(0, BASE_URL.length - 1);
  }
}

publicPath

В модуле " .exports "добавьте раздел" output "и добавьте параметр" publicPath ". «publicPath» позволяет указать базовый путь для всех ресурсов в вашем приложении, например, у меня есть изображения, на которые я ссылаюсь в своем приложении, используя следующий код.

import myImage from '../images/myImage.png';
....
<img src={myImage } alt="myImage " />
....
 

«publicPath» должен заканчиваться конечный sla sh, поэтому, если у нас есть BASE_URL, я добавляю / в противном случае оставляю его пустым.

output: {
    publicPath: (BASE_URL) ? `${BASE_URL}/` : '',
},
  

Для получения дополнительной информации о «publicPath» см. https://webpack.js.org/guides/public-path/

webpack.DefinePlugin

В «module.exports» добавьте параметр «webpack.DefinePlugin», задающий переменную среды, которая будет передаваться при сбросе приложения

plugins: [
    new webpack.DefinePlugin({
      'process.env.BASE_URL': JSON.stringify(BASE_URL),
    }),
],    

Для получения дополнительной информации о «DefaultPlugin» см. https://webpack.js.org/plugins/define-plugin/

Маршрутизация на стороне сервера

Добавьте «базовое имя» в маршрутизатор на стороне сервера, значение которого является переменной, указанной в "DefinePlugin" в файле конфигурации веб-пакета

<StaticRouter context={context} location={req.path} basename={process.env.BASE_URL}>
    ...
</StaticRouter>

Маршрутизация на стороне клиента

Добавьте «базовое имя» к маршрутизатору на стороне клиента, значением которого является переменная spe указано в "DefinePlugin" в файле конфигурации веб-пакета

<BrowserRouter basename={process.env.BASE_URL}>
    ...
</BrowserRouter>
...