Compare commits

...

19 Commits

Author SHA1 Message Date
24c4444601 Merge pull request #113 from aleleba/PR-119605
Some checks failed
Main Workflow / unit-front-end-testing (push) Failing after 1m36s
Main Workflow / cypress-components-testing (push) Failing after 56s
Main Workflow / end-to-end-testing (push) Failing after 57s
Main Workflow / test-build-package (push) Has been skipped
Main Workflow / publish-npm (push) Has been skipped
PR-119605: updating packages.
2025-06-06 01:08:58 -06:00
73dcc53b13 PR-119605: fix unit testing. 2025-06-06 07:05:06 +00:00
43b9463777 PR-119605: updating packages. 2025-06-06 06:59:12 +00:00
a48cab48b0 Merge pull request #112 from aleleba/PR-687356
Some checks failed
Main Workflow / unit-front-end-testing (push) Failing after 1m19s
Main Workflow / end-to-end-testing (push) Failing after 1m20s
Main Workflow / cypress-components-testing (push) Failing after 1m26s
Main Workflow / test-build-package (push) Has been skipped
Main Workflow / publish-npm (push) Has been skipped
PR-687356: Updating packages and adding support to HMR to server also.
2025-04-18 12:13:54 -06:00
846d498025 PR-687356: Updating packages and adding support to HMR to server also. 2025-04-18 18:10:39 +00:00
4ca7a5a191 Merge pull request #111 from aleleba/PR-415815
Some checks failed
Main Workflow / unit-front-end-testing (push) Failing after 1m56s
Main Workflow / cypress-components-testing (push) Failing after 1m54s
Main Workflow / end-to-end-testing (push) Failing after 1m2s
Main Workflow / test-build-package (push) Has been skipped
Main Workflow / publish-npm (push) Has been skipped
PR-415815: fixing webpack build.
2025-04-12 09:59:43 -06:00
519aa86c79 PR-415815: adding PUBLIC_URL to e2e testing. 2025-04-12 15:56:44 +00:00
2539dcb7b1 PR-415815: fixing webpack build. 2025-04-12 15:51:29 +00:00
6c4ea9dad1 Merge pull request #110 from aleleba/PR-247699
Some checks failed
Main Workflow / end-to-end-testing (push) Failing after 1m15s
Main Workflow / cypress-components-testing (push) Failing after 1m54s
Main Workflow / unit-front-end-testing (push) Failing after 2m47s
Main Workflow / test-build-package (push) Has been skipped
Main Workflow / publish-npm (push) Has been skipped
PR-247699: fixing name of unit testing workflow.
2025-04-11 12:39:05 -06:00
1ec2fc29a1 PR-247699: using latest versions of workflows versions. 2025-04-11 18:37:00 +00:00
6ec54f195a PR-247699: using node LTS on CI/CD 2025-04-11 18:28:28 +00:00
1e17457c5d PR-247699: fixing name of unit testing workflow. 2025-04-11 18:20:15 +00:00
f04553d033 Merge pull request #109 from aleleba/PR-538901
Some checks failed
Main Workflow / unit-front-end-testing (16.x) (push) Failing after 2m3s
Main Workflow / cypress-components-testing (push) Failing after 2m2s
Main Workflow / end-to-end-testing (push) Failing after 1m8s
Main Workflow / test-build-package (push) Has been skipped
Main Workflow / publish-npm (push) Has been skipped
PR-538901: updating token of npm.
2025-04-11 01:07:08 -06:00
da60aeea25 PR-538901: updating token of npm. 2025-04-11 07:02:41 +00:00
e9f955406f Merge pull request #108 from aleleba/PR-128452
PR-128452: fixing publishing to npm.
2025-04-11 00:51:19 -06:00
32fd90f55b PR-128452: fixing publishing to npm. 2025-04-11 06:46:53 +00:00
04c03f7404 Merge pull request #107 from aleleba/PR-589725
PR-589725: Updating packages, fixing redux actions and fixing linting.
2025-04-11 00:28:31 -06:00
bf1a6a2996 PR-589725: fixing express 5 wildcard migration. 2025-04-11 06:25:53 +00:00
be0bb6238f PR-589725: Updating packages, fixing redux actions and fixing linting. 2025-04-11 06:06:54 +00:00
27 changed files with 3039 additions and 5825 deletions

View File

@ -14,19 +14,15 @@ jobs:
# Job to run unit tests
unit-front-end-testing:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v3
- name: Use Node.js 16
uses: actions/setup-node@v3
- uses: actions/checkout@v4
- name: Use Node.js LTS
uses: actions/setup-node@v4
with:
node-version: 16
node-version: 'lts/*'
cache: 'npm'
registry-url: https://registry.npmjs.org/
- run: npm ci
- run: npm ci --legacy-peer-deps
- run: npm test
# Job to run Cypress component tests
@ -34,11 +30,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
# Install NPM dependencies, cache them correctly
# and run all Cypress tests
- name: Install dependencies
run: npm ci
run: npm ci --legacy-peer-deps
- name: Cypress run
uses: cypress-io/github-action@v6 # use the explicit version number
with:
@ -50,13 +46,14 @@ jobs:
runs-on: ubuntu-latest
env:
PORT: 3000
PUBLIC_URL: /
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
# Install NPM dependencies, cache them correctly
# and run all Cypress tests
- name: Install dependencies
run: npm ci
run: npm ci --legacy-peer-deps
- name: Cypress run
uses: cypress-io/github-action@v6 # use the explicit version number
with:
@ -70,12 +67,12 @@ jobs:
needs: [ unit-front-end-testing, cypress-components-testing, end-to-end-testing ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 16
node-version: 'lts/*'
registry-url: https://registry.npmjs.org/
- run: npm ci
- run: npm ci --legacy-peer-deps
- run: npm run build
# Job to publish the package to NPM
@ -84,12 +81,12 @@ jobs:
needs: [ unit-front-end-testing, cypress-components-testing, end-to-end-testing ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 16
node-version: 'lts/*'
registry-url: https://registry.npmjs.org/
- run: npm ci
- run: npm ci --legacy-peer-deps
- run: npm publish --access=public
env:
NPM_PERSONAL_TOKEN: ${{secrets.npm_token}}

View File

@ -6,12 +6,12 @@ It is not a project like create-react-app, create-react-app is used as a starter
Tech(Library or Framework) | Version |
--- | --- |
React (Render Library) | 18.3.1
React (Render Library) | 19.1.0
Redux (Global State Management) | 5.0.1
React Router DOM (Routing) | 6.26.2
React Router DOM (Routing) | 7.6.2
Jest (Testing) | 29.7.0
Cypress (E2E Testing) | 13.14.2
Typescript | 5.6.2
Cypress (E2E Testing) | 14.4.1
Typescript | 5.8.3
## Setup
To create a new project run in the terminal:

View File

@ -2,7 +2,7 @@
const { execSync } = require('child_process');
var fs = require('fs');
const isWin = process.platform === "win32";
const isWin = process.platform === 'win32';
const runCommand = command => {
try{
@ -12,7 +12,7 @@ const runCommand = command => {
return false;
}
return true;
}
};
const runCommandWithOutput = command => {
try{
@ -21,7 +21,7 @@ const runCommandWithOutput = command => {
console.error(`Failed to execute ${command}`, e);
return false;
}
}
};
const replaceTextOnFile = ({
file,
@ -29,7 +29,7 @@ const replaceTextOnFile = ({
textReplace,
arrOfObjectsBeReplaced
}) => {
let data
let data;
try{
data = fs.readFileSync(file, 'utf8');
} catch (e) {
@ -37,7 +37,7 @@ const replaceTextOnFile = ({
return false;
}
let result
let result;
if(arrOfObjectsBeReplaced){
arrOfObjectsBeReplaced.forEach( obj => {
if(result){
@ -45,19 +45,19 @@ const replaceTextOnFile = ({
}else{
result = data.replace(obj.textToBeReplaced, obj.textReplace).replace(/^\s*[\r\n]/gm, ' ');
}
})
});
}else{
result = data.replace(textToBeReplaced, textReplace).replace(/^\s*[\r\n]/gm, ' ');
}
try{
console.log('text changed')
console.log('text changed');
fs.writeFileSync(file, result, 'utf8');
} catch (e) {
console.error(`Failed to read file ${file}`, e);
return false;
}
}
};
const repoName = process.argv[2];
const gitCheckoutCommand = `git clone --depth 1 https://github.com/aleleba/create-react-ssr ${repoName}`;
@ -65,13 +65,13 @@ console.log(`Cloning the repository with name ${repoName}`);
const checkedOut = runCommand(gitCheckoutCommand);
if(!checkedOut) process.exit(-1);
const actualVersion = runCommandWithOutput(`cd ${repoName} && node -p "require('./package.json').version"`).toString().trim()
const actualVersion = runCommandWithOutput(`cd ${repoName} && node -p "require('./package.json').version"`).toString().trim();
const installDepsCommand = `cd ${repoName} && npm i`;
const cleanGitHistoryCommand = `cd ${repoName} && rm -rf .git && git init && git add --all -- ":!.github" ":!bin" && git commit -m "Initial commit"`
const cleanGitHistoryCommandWindows = `cd ${repoName} && rmdir .git /s /q && git init && git add --all -- ":!.github" ":!bin" && git commit -m "Initial commit"`
const deleteFoldersCommand = `cd ${repoName} && rm -rf .github && rm -rf bin`
const deleteFoldersCommandWindows = `cd ${repoName} && rmdir .github /s /q && rmdir bin /s /q`
const installDepsCommand = `cd ${repoName} && npm i --legacy-peer-deps`;
const cleanGitHistoryCommand = `cd ${repoName} && rm -rf .git && git init && git add --all -- ":!.github" ":!bin" && git commit -m "Initial commit"`;
const cleanGitHistoryCommandWindows = `cd ${repoName} && rmdir .git /s /q && git init && git add --all -- ":!.github" ":!bin" && git commit -m "Initial commit"`;
const deleteFoldersCommand = `cd ${repoName} && rm -rf .github && rm -rf bin`;
const deleteFoldersCommandWindows = `cd ${repoName} && rmdir .github /s /q && rmdir bin /s /q`;
console.log(`Installing dependencies for ${repoName}`);
const installedDeps = runCommand(installDepsCommand);
@ -82,28 +82,28 @@ replaceTextOnFile({
file: `./${repoName}/package.json`,
arrOfObjectsBeReplaced: [
{
textToBeReplaced: `"bin": "./bin/cli.js",`,
textReplace: ``
textToBeReplaced: '"bin": "./bin/cli.js",',
textReplace: ''
},
{
textToBeReplaced: `"version": "${actualVersion}",`,
textReplace: `"version": "0.0.1",`
textReplace: '"version": "0.0.1",'
},
{
textToBeReplaced: `"name": "@aleleba/create-react-ssr",`,
textToBeReplaced: '"name": "@aleleba/create-react-ssr",',
textReplace: `"name": "${repoName}",`
}
]
})
});
console.log(`Cleaning History of Git for ${repoName}`);
const cleanGitHistory = isWin ? runCommand(cleanGitHistoryCommandWindows) : runCommand(cleanGitHistoryCommand);
if(!cleanGitHistory) process.exit(-1);
console.log("Congratulations! You are ready. Follow the following commands to start");
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: "auto"), PREFIX_URL=your_prefix_url(optional)(default: ""), ONLY_EXACT_PATH=true(optional)(default: false)');
console.log(`Then you can run: npm start:dev`);
console.log('Then you can run: npm start:dev');
const deleteFolders = isWin ? runCommand(deleteFoldersCommandWindows) : runCommand(deleteFoldersCommand);
if(!deleteFolders) process.exit(-1);

View File

@ -4,7 +4,7 @@ export const deFaultValues = {
PUBLIC_URL: 'auto',
PREFIX_URL: '',
ONLY_EXACT_PATH: false,
}
};
export const config = {
ENV: process.env.ENV ? process.env.ENV : deFaultValues.ENV,
@ -14,4 +14,4 @@ export const config = {
ONLY_EXACT_PATH: process.env.ONLY_EXACT_PATH ? process.env.ONLY_EXACT_PATH === 'true' : deFaultValues.ONLY_EXACT_PATH,
};
export default config
export default config;

View File

@ -22,7 +22,7 @@ import './commands';
// Alternatively you can use CommonJS syntax:
// require('./commands')
import { mount } from '@cypress/react'
import { mount } from '@cypress/react';
// Augment the Cypress namespace to include type definitions for
// your custom command.

View File

@ -4,19 +4,22 @@ import reactPlugin from 'eslint-plugin-react';
import globals from 'globals';
export default tseslint.config(
{
ignores: [
'**/build/**',
'**/webpack.config.ts',
'**/webpack.config.dev.ts',
'**/webpack.config.dev.server.ts',
'**/webpack.cy.config.ts',
'**/service-worker.ts',
'**/serviceWorkerRegistration.ts',
'node_modules/**'
]
},
eslint.configs.recommended,
...tseslint.configs.recommended,
{
files: ['**/*.{js,jsx,ts,tsx}'],
ignores: [
'build/',
'webpack.config.ts',
'webpack.config.dev.ts',
'webpack.config.dev.server.ts',
'webpack.cy.config.ts',
'service-worker.ts',
'serviceWorkerRegistration.ts'
],
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
@ -42,14 +45,21 @@ export default tseslint.config(
}
},
rules: {
// Include here the recommended rules for react
...reactPlugin.configs.recommended.rules,
'indent': ['error', 'tab'],
'linebreak-style': ['error', 'unix'],
'quotes': ['error', 'single'],
'semi': ['error', 'always'],
'eol-last': ['error', 'always'],
'@typescript-eslint/no-var-requires': 'off',
// Include here the recommended rules for react
...reactPlugin.configs.recommended.rules
'@typescript-eslint/no-require-imports': 'off',
'no-undef': 'off',
'@typescript-eslint/no-namespace': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unused-expressions': 'off',
}
}
);

8230
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,19 @@
{
"name": "@aleleba/create-react-ssr",
"version": "3.9.28",
"version": "3.10.1",
"description": "Starter Kit of server side render of react",
"bin": "./bin/cli.js",
"main": "src/server/index",
"scripts": {
"start": "node build/server/app-server.js",
"start:dev": "rm -rf build && webpack --mode=development --config webpack.config.dev.server.ts",
"start:dev-win": "(if exist build rmdir /s /Q build) && webpack --mode=development --config webpack.config.dev.server.ts",
"start:dev": "rm -rf build && webpack --watch --mode=development --config webpack.config.dev.server.ts",
"start:dev-win": "(if exist build rmdir /s /Q build) && webpack --watch --mode=development --config webpack.config.dev.server.ts",
"build": "webpack-cli --config webpack.config.ts",
"lint": "eslint ./ --ext .js --ext .ts --ext .jsx --ext .tsx",
"lint:fix": "eslint ./ --ext .js --ext .ts --ext .jsx --ext .tsx --fix",
"test": "jest",
"test:watch": "jest --watch",
"check-updates": "npx npm-check-updates -u && npm i",
"check-updates": "npx npm-check-updates -u && npm i --legacy-peer-deps",
"cy:open": "npx cypress open",
"cy:run": "cypress run",
"cy:run-component": "cypress run --headless --component"
@ -36,20 +36,20 @@
},
"homepage": "https://github.com/aleleba/create-react-ssr#readme",
"dependencies": {
"@babel/register": "^7.25.9",
"dotenv": "^16.4.7",
"express": "^4.21.2",
"@babel/register": "^7.27.1",
"dotenv": "^16.5.0",
"express": "^5.1.0",
"helmet": "^8.1.0",
"history": "^5.3.0",
"ignore-styles": "^5.0.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-redux": "^9.2.0",
"react-router-dom": "^7.4.0",
"react-router-dom": "^7.6.2",
"react-router-hash-link": "^2.4.3",
"redux": "^5.0.1",
"webpack": "^5.98.0",
"webpack-dev-server": "^5.2.0",
"webpack": "^5.99.9",
"webpack-dev-server": "^5.2.2",
"webpack-manifest-plugin": "^5.0.1",
"workbox-background-sync": "^7.3.0",
"workbox-broadcast-update": "^7.3.0",
@ -65,26 +65,27 @@
"workbox-streams": "^7.3.0"
},
"devDependencies": {
"@babel/core": "^7.26.10",
"@babel/preset-env": "^7.26.9",
"@babel/preset-react": "^7.26.3",
"@babel/preset-typescript": "^7.27.0",
"@babel/core": "^7.27.4",
"@babel/preset-env": "^7.27.2",
"@babel/preset-react": "^7.27.1",
"@babel/preset-typescript": "^7.27.1",
"@cypress/react": "^9.0.1",
"@eslint/js": "^9.23.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.15",
"@eslint/js": "^9.28.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.6.0",
"@redux-devtools/extension": "^3.3.0",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.2.0",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^14.6.1",
"@types/jest": "^29.5.14",
"@types/node": "^22.13.13",
"@types/react": "^19.0.12",
"@types/react-dom": "^19.0.4",
"@types/node": "^22.15.30",
"@types/react": "^19.1.6",
"@types/react-dom": "^19.1.6",
"@types/webpack": "^5.28.5",
"@types/webpack-hot-middleware": "^2.25.9",
"@types/webpack-node-externals": "^3.0.4",
"@typescript-eslint/eslint-plugin": "^8.28.0",
"@typescript-eslint/parser": "^8.28.0",
"@typescript-eslint/eslint-plugin": "^8.33.1",
"@typescript-eslint/parser": "^8.33.1",
"babel-jest": "^29.7.0",
"babel-loader": "^10.0.0",
"clean-webpack-plugin": "^4.0.0",
@ -92,27 +93,28 @@
"copy-webpack-plugin": "^13.0.0",
"css-loader": "^7.1.2",
"css-minimizer-webpack-plugin": "^7.0.2",
"cypress": "^14.2.0",
"eslint": "^9.23.0",
"eslint-plugin-react": "^7.37.4",
"eslint-webpack-plugin": "^5.0.0",
"cypress": "^14.4.1",
"eslint": "^9.28.0",
"eslint-plugin-react": "^7.37.5",
"eslint-webpack-plugin": "^5.0.1",
"file-loader": "^6.2.0",
"globals": "^16.0.0",
"globals": "^16.2.0",
"html-webpack-plugin": "^5.6.3",
"identity-obj-proxy": "^3.0.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest-fetch-mock": "^3.0.3",
"jiti": "^2.4.2",
"mini-css-extract-plugin": "^2.9.2",
"react-refresh": "^0.16.0",
"react-refresh": "^0.17.0",
"resolve-ts-aliases": "^1.0.1",
"sass": "^1.86.0",
"sass": "^1.89.1",
"sass-loader": "^16.0.5",
"style-loader": "^4.0.0",
"terser-webpack-plugin": "^5.3.14",
"ts-jest": "^29.3.0",
"typescript": "^5.8.2",
"typescript-eslint": "^8.28.0",
"ts-jest": "^29.3.4",
"typescript": "^5.8.3",
"typescript-eslint": "^8.33.1",
"url-loader": "^4.1.1",
"webpack-cli": "^6.0.1",
"webpack-dev-middleware": "^7.4.2",

View File

@ -1,4 +1,4 @@
import * as express from "express"
import * as express from 'express';
declare global {
namespace Express {

View File

@ -1,4 +1,11 @@
declare module "*.svg" {
declare module '*.svg' {
const content: any;
export default content;
}
declare const module: {
hot?: {
accept(dep?: string, callback?: () => void): void;
dispose(callback: () => void): void;
};
};

View File

@ -6,10 +6,10 @@ import initialStateReducer from '../frontend/reducers/initialState';
import setStore from '../frontend/setStore';
export const ProviderMock = ({ children, initialState }: { children: any, initialState?: any}) => {
let initialStateMock = initialStateReducer
let initialStateMock = initialStateReducer;
if(initialState !== undefined){
initialStateMock = initialState
initialStateMock = initialState;
}
const history = createMemoryHistory();
@ -21,7 +21,7 @@ export const ProviderMock = ({ children, initialState }: { children: any, initia
{children}
</Router>
</Provider>
)
}
);
};
export default ProviderMock;

View File

@ -1,9 +1 @@
import test, { TTest } from './testAction';
export type TAction = TTest
const actions = {
test
}
export default actions
export * from '@actions/testAction';

View File

@ -16,10 +16,10 @@ export type TTest = IChangeHello
const changeHello = (payload: string) => ({
type: ActionTypesTest.ChangeHello,
payload
})
});
const actions = {
changeHello
}
};
export default actions
export default actions;

View File

@ -1,7 +1,7 @@
import React from 'react';
import logo from '../logo.svg';
import './InitialComponent.scss';
import { Link } from "react-router-dom";
import { Link } from 'react-router-dom';
const OtherComponent = () => (
<div className="App">

View File

@ -4,7 +4,7 @@ import { useRoutes } from 'react-router-dom';
import routes from '../../routes';
const PrincipalRoutes = () => {
let element = useRoutes(routes);
const element = useRoutes(routes);
return element;
};

View File

@ -18,6 +18,6 @@ describe('<App/> Component', () => {
<ProviderMock>
<App />
</ProviderMock>
)
})
})
);
});
});

View File

@ -1,10 +1,6 @@
import { combineReducers } from 'redux';
import testReducer from './testReducer';
import { IChangeHelloPayload } from '../actions/testAction';
export interface IInitialState {
testReducer?: IChangeHelloPayload | undefined
}
export * from './initialState';
const rootReducer = combineReducers({
// Here comes the reducers

View File

@ -1,3 +1,6 @@
import { IInitialState } from './';
import { IChangeHelloPayload } from '@actions';
export interface IInitialState {
testReducer?: IChangeHelloPayload | undefined
}
const initialState: IInitialState = {};
export default initialState;

View File

@ -1,10 +1,10 @@
import { TAction } from '../actions';
import { TTest } from '@actions';
const initialState = {
hello: 'world'
};
const testReducer = (state = initialState, action: TAction) => {
const testReducer = (state = initialState, action: TTest) => {
switch (action.type){
case 'CHANGE_HELLO': {
const newHello = action.payload.hello;

View File

@ -3,8 +3,7 @@ import { legacy_createStore as createStore} from 'redux'; //, applyMiddleware
// import { Provider } from 'react-redux';
import { composeWithDevTools as composeWithDevToolsWeb } from '@redux-devtools/extension';
import { config } from '../../config';
import reducer, { IInitialState } from './reducers';
import reducer, { IInitialState } from '@reducers';
const { ENV } = config;
@ -15,11 +14,11 @@ const composeEnhancers = composeWithDevToolsWeb({
const setStore = ({ initialState }: { initialState: IInitialState | undefined }) => {
const store = ENV === 'development' ? createStore(
reducer,
initialState,
initialState as any,
composeEnhancers(),
) : createStore(
reducer,
initialState,
initialState as any,
);
return store;
};

View File

@ -129,8 +129,21 @@ const renderApp = (req, res, next) => {
};
app
.get('*', renderApp);
.get('/{*splat}', renderApp);
app.listen(PORT, () => {
const server = app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
// --- HMR Support ---
if (module.hot) {
module.hot.accept();
module.hot.dispose(() => {
console.log('🔁 [HMR] Disposing backend module...');
if (server) {
server.close(() => {
console.log('🛑 Server closed due to HMR');
});
}
});
}

View File

@ -3,7 +3,7 @@ import webpackNodeExternals from 'webpack-node-externals';
import WebpackShellPluginNext from 'webpack-shell-plugin-next';
import { resolveTsAliases } from 'resolve-ts-aliases';
import path from 'path';
import { Configuration } from 'webpack';
import webpack, { Configuration } from 'webpack';
const ROOT_DIR = path.resolve(__dirname);
const resolvePath = (...args: string[]) => path.resolve(ROOT_DIR, ...args);
const BUILD_DIR = resolvePath('build');
@ -18,7 +18,18 @@ const config: Configuration = {
mode: 'development',
name: 'server',
entry: {
server: `${ROOT_DIR}/src/server/index.ts`,
server: [
'webpack/hot/poll?1000',
`${ROOT_DIR}/src/server/index.ts`
],
},
watchOptions: {
ignored: [
'**/src/frontend/**',
'**/public/**',
'**/build/**',
'**/node_modules/**'
]
},
resolve: {
extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
@ -49,7 +60,16 @@ const config: Configuration = {
'options': {
modules: {
auto: /\.module\.\w+$/i,
},
url: {
filter: (url) => {
// No procesar URLs absolutas que comienzan con /
if (url.startsWith('/')) {
return false;
}
return true;
}
},
},
},
'sass-loader',
@ -79,8 +99,11 @@ const config: Configuration = {
libraryTarget: 'commonjs2',
},
node: false,
externals: [webpackNodeExternals()],
externals: [webpackNodeExternals({
allowlist: ['webpack/hot/poll?1000']
})],
plugins: [
new webpack.HotModuleReplacementPlugin(),
new MiniCssExtractPlugin({
filename: 'assets/app.css',
}),

View File

@ -35,6 +35,12 @@ if(fs.existsSync(`${ROOT_DIR}/../public/img`)){
});
}
if(fs.existsSync(`${ROOT_DIR}/../public/fonts`)){
copyPatterns.push({
from: `${ROOT_DIR}/../public/fonts`, to: 'assets/fonts',
});
}
const config: Configuration = {
entry: [`webpack-hot-middleware/client?path=${envConfig.PREFIX_URL}/reload_wss&timeout=2000&reload=true&autoConnect=true`, `${ROOT_DIR}/../src/frontend/index.tsx`],
output: {
@ -68,7 +74,16 @@ const config: Configuration = {
'options': {
modules: {
auto: /\.module\.\w+$/i,
},
url: {
filter: (url) => {
// No procesar URLs absolutas que comienzan con /
if (url.startsWith('/')) {
return false;
}
return true;
}
},
},
},
'sass-loader',

View File

@ -41,6 +41,12 @@ if(fs.existsSync(`${ROOT_DIR}/public/img`)){
});
}
if(fs.existsSync(`${ROOT_DIR}/public/fonts`)){
copyPatterns.push({
from: `${ROOT_DIR}/public/fonts`, to: 'assets/fonts',
});
}
const frontendConfig = {
entry: {
frontend: `${ROOT_DIR}/src/frontend/index.tsx`,
@ -73,7 +79,16 @@ const frontendConfig = {
'options': {
modules: {
auto: /\.module\.\w+$/i,
},
url: {
filter: (url) => {
// No procesar URLs absolutas que comienzan con /
if (url.startsWith('/')) {
return false;
}
return true;
}
},
},
},
'sass-loader',
@ -186,7 +201,16 @@ const serverConfig = {
'options': {
modules: {
auto: /\.module\.\w+$/i,
},
url: {
filter: (url) => {
// No procesar URLs absolutas que comienzan con /
if (url.startsWith('/')) {
return false;
}
return true;
}
},
},
},
'sass-loader',

View File

@ -23,6 +23,12 @@ if(fs.existsSync(copyFromUrl)){
});
}
if(fs.existsSync(`${path.resolve(__dirname)}/public/fonts`)){
copyPatterns.push({
from: `${path.resolve(__dirname)}/public/fonts`, to: 'assets/fonts',
});
}
export default {
entry: './src/frontend/components/index.tsx',
resolve: {
@ -71,7 +77,16 @@ export default {
'options': {
modules: {
auto: /\.module\.\w+$/i,
},
url: {
filter: (url) => {
// No procesar URLs absolutas que comienzan con /
if (url.startsWith('/')) {
return false;
}
return true;
}
},
},
},
'sass-loader',