mirror of
https://github.com/aleleba/create-react-ssr.git
synced 2025-01-08 04:56:57 -06:00
PR-049111: making mayor change for add support to prefix url.
This commit is contained in:
parent
8ddd290adb
commit
e70d0a01ca
@ -3,4 +3,8 @@ ENV= #Default production
|
||||
#App Port
|
||||
PORT= #Default 80
|
||||
#PUBLIC URL
|
||||
PUBLIC_URL= #Default /
|
||||
PUBLIC_URL= #Default 'auto'
|
||||
#Prefix URL
|
||||
PREFIX_URL= #Default ''
|
||||
#ONLY EXACT PATH
|
||||
ONLY_EXACT_PATH= #Default false
|
12
README.md
12
README.md
@ -25,13 +25,17 @@ You will need to create a new .env file at the root of the project for global co
|
||||
This is an exaple of config.
|
||||
```
|
||||
#Environment
|
||||
ENV=development #Default production
|
||||
ENV= #Default production
|
||||
#App Port
|
||||
PORT=3000 #Default 80
|
||||
PORT= #Default 80
|
||||
#PUBLIC URL
|
||||
#PUBLIC_URL= #Default /
|
||||
PUBLIC_URL= #Default 'auto'
|
||||
#Prefix URL
|
||||
PREFIX_URL= #Default ''
|
||||
#ONLY EXACT PATH
|
||||
ONLY_EXACT_PATH= #Default false
|
||||
```
|
||||
The default environment is production, the app port defauld is 80 and the default public url is "/".
|
||||
The default environment is production, the app port defauld is 80 and the default public url is "auto", use prefix url if you want a prefix on base url, use exact path to validate if you want to have strict exact paths.
|
||||
|
||||
### For Development
|
||||
In the terminal run:
|
||||
|
@ -102,7 +102,7 @@ if(!cleanGitHistory) process.exit(-1);
|
||||
|
||||
console.log("Congratulations! You are ready. Follow the following commands to start");
|
||||
console.log(`cd ${repoName}`);
|
||||
console.log('Create a .env file with ENV=development(defauld: production), PORT=3000 (default: 80), PUBLIC_URL=your_public_url(optional)(default: /)');
|
||||
console.log('Create a .env file with ENV=development(defauld: production), PORT=3000 (default: 80), PUBLIC_URL=your_public_url(optional)(default: "auto"), PREFIX_URL=your_prefix_url(optional)(default: ""), ONLY_EXACT_PATH=true(optional)(default: false)');
|
||||
console.log(`Then you can run: npm start:dev`);
|
||||
|
||||
const deleteFolders = isWin ? runCommand(deleteFoldersCommandWindows) : runCommand(deleteFoldersCommand);
|
||||
|
@ -1,11 +1,15 @@
|
||||
export const config = {
|
||||
ENV: process.env.ENV,
|
||||
PORT: process.env.PORT,
|
||||
PUBLIC_URL: process.env.PUBLIC_URL,
|
||||
};
|
||||
|
||||
export const deFaultValues = {
|
||||
ENV: 'production',
|
||||
PORT: 3000,
|
||||
PUBLIC_URL: '/',
|
||||
}
|
||||
PORT: 80,
|
||||
PUBLIC_URL: 'auto',
|
||||
PREFIX_URL: '',
|
||||
ONLY_EXACT_PATH: false,
|
||||
}
|
||||
|
||||
export const config = {
|
||||
ENV: process.env.ENV ? process.env.ENV : deFaultValues.ENV,
|
||||
PORT: process.env.PORT ? process.env.PORT : deFaultValues.PORT,
|
||||
PUBLIC_URL: process.env.PUBLIC_URL ? process.env.PUBLIC_URL : deFaultValues.PUBLIC_URL,
|
||||
PREFIX_URL: process.env.PREFIX_URL ? process.env.PREFIX_URL : deFaultValues.PREFIX_URL,
|
||||
ONLY_EXACT_PATH: process.env.ONLY_EXACT_PATH ? process.env.ONLY_EXACT_PATH === 'true' : deFaultValues.ONLY_EXACT_PATH,
|
||||
};
|
||||
|
@ -3,6 +3,9 @@ module.exports = {
|
||||
"testEnvironment": "jsdom",
|
||||
moduleNameMapper: {
|
||||
"\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/src/__mocks__/fileMock.ts",
|
||||
"@components": "<rootDir>/src/frontend/components/",
|
||||
"@styles": "<rootDir>/src/frontend/styles/",
|
||||
"@config": "<rootDir>/config/",
|
||||
"\\.(css|sass|scss|less)$": "identity-obj-proxy"
|
||||
},
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@aleleba/create-react-ssr",
|
||||
"version": "3.5.7",
|
||||
"version": "3.6.0",
|
||||
"description": "Starter Kit of server side render of react",
|
||||
"bin": "./bin/cli.js",
|
||||
"main": "src/server/index",
|
||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
6
src/@types/index.d.ts
vendored
6
src/@types/index.d.ts
vendored
@ -1,4 +1,8 @@
|
||||
declare module "*.svg" {
|
||||
const content: any;
|
||||
export default content;
|
||||
}
|
||||
}
|
||||
|
||||
declare module "@config" {
|
||||
export const config: any;
|
||||
}
|
||||
|
@ -1,12 +1,11 @@
|
||||
import React from 'react';
|
||||
import logo from '../logo.svg';
|
||||
import './InitialComponent.scss';
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
const InitialComponent = () => (
|
||||
<div className="App">
|
||||
<header className="App-header">
|
||||
<img src={logo} className="App-logo" alt="logo" />
|
||||
<img src="assets/img/logo.svg" className="App-logo" alt="logo" />
|
||||
<p>
|
||||
Edit <code>src/frontend/InitialComponent.jsx</code> and save to reload.
|
||||
</p>
|
||||
|
@ -6,7 +6,7 @@ import { Link } from "react-router-dom";
|
||||
const OtherComponent = () => (
|
||||
<div className="App">
|
||||
<header className="App-header">
|
||||
<img src={logo} className="App-logo" alt="logo" />
|
||||
<img src="assets/img/logo.svg" className="App-logo" alt="logo" />
|
||||
<p>
|
||||
Edit <code>src/frontend/OtherComponent.jsx</code> and save to reload.
|
||||
</p>
|
||||
|
@ -28,7 +28,7 @@ interface IHot {
|
||||
accept: any
|
||||
}
|
||||
|
||||
const { ENV } = config;
|
||||
const { ENV, PREFIX_URL } = config;
|
||||
|
||||
const preloadedState = window.__PRELOADED_STATE__;
|
||||
const store = setStore({ initialState: preloadedState });
|
||||
@ -41,7 +41,7 @@ if(ENV === 'development') {
|
||||
const root = createRoot(container);
|
||||
root.render(
|
||||
<Provider store={store}>
|
||||
<Router>
|
||||
<Router basename={PREFIX_URL}>
|
||||
<App />
|
||||
</Router>
|
||||
</Provider>
|
||||
@ -51,7 +51,7 @@ if(ENV === 'development') {
|
||||
// add "const root" to be able to rerender.
|
||||
ENV === 'production' && hydrateRoot(container,
|
||||
<Provider store={store}>
|
||||
<Router>
|
||||
<Router basename={PREFIX_URL}>
|
||||
<App />
|
||||
</Router>
|
||||
</Provider>,
|
||||
|
@ -12,5 +12,4 @@ const INITIAL_COMPONENT = {
|
||||
element: <InitialComponent />,
|
||||
};
|
||||
|
||||
|
||||
export default [ INITIAL_COMPONENT, OTHER_COMPONENT ];
|
||||
|
@ -2,7 +2,7 @@
|
||||
import express from 'express';
|
||||
import webpack from 'webpack';
|
||||
import helmet from 'helmet';
|
||||
import { config } from '../../config';
|
||||
import { config } from '@config';
|
||||
|
||||
//Dependencies of HotReloading
|
||||
import webpackConfig from '../../webpack.config.dev';
|
||||
@ -24,9 +24,9 @@ import { getHashManifest, haveVendorsCss } from './utilsServer';
|
||||
//App
|
||||
import App from '../frontend/components/App';
|
||||
|
||||
const { ENV, PORT } = config;
|
||||
const { ENV, PORT, PREFIX_URL, ONLY_EXACT_PATH } = config;
|
||||
|
||||
const routesUrls = routes.map( route => route.path);
|
||||
const routesUrls = routes.map( route => route.path );
|
||||
|
||||
const app = express();
|
||||
|
||||
@ -47,6 +47,7 @@ if(ENV === 'development'){
|
||||
}else{
|
||||
const baseUrl = __dirname.replace(/\/server(.*)/,'');
|
||||
const fullURL = `${baseUrl}` ;
|
||||
console.log(fullURL)
|
||||
app
|
||||
.use((req, res, next) => {
|
||||
if(!req.hashManifest) req.hashManifest = getHashManifest();
|
||||
@ -102,17 +103,21 @@ const setResponse = (html, preloadedState, manifest) => {
|
||||
};
|
||||
|
||||
const renderApp = (req, res, next) => {
|
||||
if(routesUrls.includes(req.url)){
|
||||
const store = setStore({ initialState });
|
||||
const preloadedState = store.getState();
|
||||
const html = renderToString(
|
||||
// @ts-ignore:next-line
|
||||
<Provider store={store}>
|
||||
<StaticRouter location={req.url}>
|
||||
<App />
|
||||
</StaticRouter>
|
||||
</Provider>
|
||||
);
|
||||
const store = setStore({ initialState });
|
||||
const preloadedState = store.getState();
|
||||
const html = renderToString(
|
||||
// @ts-ignore:next-line
|
||||
<Provider store={store}>
|
||||
<StaticRouter location={`${PREFIX_URL}${req.url}`} basename={PREFIX_URL}>
|
||||
<App />
|
||||
</StaticRouter>
|
||||
</Provider>
|
||||
);
|
||||
if(ONLY_EXACT_PATH){
|
||||
if(routesUrls.includes(req.url)){
|
||||
res.send(setResponse(html, preloadedState, req.hashManifest));
|
||||
}
|
||||
} else {
|
||||
res.send(setResponse(html, preloadedState, req.hashManifest));
|
||||
}
|
||||
next();
|
||||
@ -121,7 +126,6 @@ const renderApp = (req, res, next) => {
|
||||
app
|
||||
.get('*', renderApp);
|
||||
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Server running on port ${PORT}`);
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import fs from 'fs';
|
||||
import { config } from '../../config';
|
||||
|
||||
const { ENV } = config;
|
||||
const { ENV } = config
|
||||
|
||||
export const getHashManifest = () => {
|
||||
try {
|
||||
@ -17,7 +17,7 @@ export const getHashManifest = () => {
|
||||
export const haveVendorsCss = (manifest, memoryFs) => {
|
||||
try {
|
||||
const baseUrl = __dirname.replace(/\/server(.*)/,'');
|
||||
const fullURL = `${baseUrl}${manifest ? manifest['vendors.css'] : '/build/assets/vendors.css'}`;
|
||||
const fullURL = `${baseUrl}${manifest ? `/${manifest['vendors.css']}` : '/build/assets/vendors.css'}`;
|
||||
ENV === 'production' && fs.readFileSync(fullURL).toString();
|
||||
ENV === 'development' && memoryFs.readFileSync(fullURL).toString();
|
||||
return true
|
||||
@ -25,4 +25,4 @@ export const haveVendorsCss = (manifest, memoryFs) => {
|
||||
// console.error(err);
|
||||
return false
|
||||
}
|
||||
};
|
||||
};
|
@ -21,10 +21,10 @@ const config: Configuration = {
|
||||
resolve: {
|
||||
extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
|
||||
alias: {
|
||||
'@app': path.resolve(__dirname, 'src/frontend/components/App'),
|
||||
'@components': path.resolve(__dirname, 'src/frontend/components/'),
|
||||
'@styles': path.resolve(__dirname, 'src/frontend/styles/'),
|
||||
}
|
||||
'@config': path.resolve(__dirname, 'config/'),
|
||||
},
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
@ -58,7 +58,7 @@ const config: Configuration = {
|
||||
test: fontsAndImagesExtensions,
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: '/assets/[name].[ext]',
|
||||
name: 'assets/[name].[ext]',
|
||||
emitFile: false,
|
||||
},
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import { deFaultValues } from './config';
|
||||
import { config as envConfig } from './config';
|
||||
import webpack, { Configuration } from 'webpack';
|
||||
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
||||
import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
|
||||
@ -33,18 +33,19 @@ if(fs.existsSync(`${ROOT_DIR}/../public/img`)){
|
||||
}
|
||||
|
||||
const config: Configuration = {
|
||||
entry: ['webpack-hot-middleware/client?path=/reload_wss&timeout=2000&reload=true&autoConnect=true', `${ROOT_DIR}/../src/frontend/index.tsx`],
|
||||
entry: [`webpack-hot-middleware/client?path=${envConfig.PREFIX_URL}/reload_wss&timeout=2000&reload=true&autoConnect=true`, `${ROOT_DIR}/../src/frontend/index.tsx`],
|
||||
output: {
|
||||
path: BUILD_DIR,
|
||||
filename: 'assets/app.js',
|
||||
publicPath: deFaultValues.PUBLIC_URL,
|
||||
publicPath: envConfig.PUBLIC_URL,
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.js', '.jsx','.ts','.tsx', '.json'],
|
||||
alias: {
|
||||
'@components': path.resolve(__dirname, 'src/frontend/components/'),
|
||||
'@styles': path.resolve(__dirname, 'src/frontend/styles/'),
|
||||
}
|
||||
'@components': path.resolve(__dirname, '../src/frontend/components/'),
|
||||
'@styles': path.resolve(__dirname, '../src/frontend/styles/'),
|
||||
'@config': path.resolve(__dirname, '../config/'),
|
||||
},
|
||||
},
|
||||
devtool: 'inline-source-map',
|
||||
mode: 'development',
|
||||
@ -92,7 +93,7 @@ const config: Configuration = {
|
||||
}),
|
||||
new ESLintPlugin(),
|
||||
new webpack.EnvironmentPlugin({
|
||||
...deFaultValues,
|
||||
...envConfig,
|
||||
}),
|
||||
new CopyPlugin({
|
||||
patterns: copyPatterns
|
||||
|
@ -1,6 +1,6 @@
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import { deFaultValues } from './config';
|
||||
import { config as envConfig } from './config';
|
||||
import webpack from 'webpack';
|
||||
import CompressionWebpackPlugin from 'compression-webpack-plugin';
|
||||
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
||||
@ -46,13 +46,14 @@ const frontendConfig = {
|
||||
output: {
|
||||
path: BUILD_DIR,
|
||||
filename: 'assets/app-[name]-[fullhash].js',
|
||||
publicPath: deFaultValues.PUBLIC_URL,
|
||||
publicPath: envConfig.PUBLIC_URL,
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.js', '.jsx','.ts','.tsx', '.json'],
|
||||
alias: {
|
||||
'@components': path.resolve(__dirname, 'src/frontend/components/'),
|
||||
'@styles': path.resolve(__dirname, 'src/frontend/styles/'),
|
||||
'@config': path.resolve(__dirname, 'config/'),
|
||||
}
|
||||
},
|
||||
mode: 'production',
|
||||
@ -100,6 +101,7 @@ const frontendConfig = {
|
||||
}),
|
||||
new WebpackManifestPlugin({
|
||||
fileName: 'assets/manifest-hash.json',
|
||||
publicPath: envConfig.PREFIX_URL,
|
||||
}),
|
||||
new CleanWebpackPlugin({
|
||||
cleanOnceBeforeBuildPatterns: [
|
||||
@ -109,7 +111,7 @@ const frontendConfig = {
|
||||
}),
|
||||
new ESLintPlugin(),
|
||||
new webpack.EnvironmentPlugin({
|
||||
...deFaultValues,
|
||||
...envConfig,
|
||||
}),
|
||||
new CopyPlugin({
|
||||
patterns: copyPatterns
|
||||
@ -154,13 +156,14 @@ const serverConfig = {
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'build'),
|
||||
filename: 'server/app-[name].js',
|
||||
publicPath: deFaultValues.PUBLIC_URL,
|
||||
publicPath: envConfig.PUBLIC_URL,
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.js', '.jsx','.ts','.tsx', '.json'],
|
||||
alias: {
|
||||
'@components': path.resolve(__dirname, 'src/frontend/components/'),
|
||||
'@styles': path.resolve(__dirname, 'src/frontend/styles/'),
|
||||
'@config': path.resolve(__dirname, 'config/'),
|
||||
}
|
||||
},
|
||||
mode: 'production',
|
||||
@ -208,12 +211,10 @@ const serverConfig = {
|
||||
}),
|
||||
new WebpackManifestPlugin({
|
||||
fileName: 'assets/manifest-hash.json',
|
||||
publicPath: envConfig.PREFIX_URL,
|
||||
}),
|
||||
new CleanWebpackPlugin(),
|
||||
new ESLintPlugin(),
|
||||
new webpack.EnvironmentPlugin({
|
||||
...deFaultValues,
|
||||
}),
|
||||
new InjectManifest({
|
||||
swSrc: './service-worker.ts',
|
||||
swDest: 'service-worker.js',
|
||||
|
Loading…
Reference in New Issue
Block a user