mirror of
https://github.com/aleleba/create-react-ssr.git
synced 2025-07-07 13:18:30 -06:00
Compare commits
22 Commits
4203b17f8b
...
master
Author | SHA1 | Date | |
---|---|---|---|
24c4444601 | |||
73dcc53b13
|
|||
43b9463777
|
|||
a48cab48b0 | |||
846d498025
|
|||
4ca7a5a191 | |||
519aa86c79
|
|||
2539dcb7b1
|
|||
6c4ea9dad1 | |||
1ec2fc29a1
|
|||
6ec54f195a
|
|||
1e17457c5d
|
|||
f04553d033 | |||
da60aeea25
|
|||
e9f955406f | |||
32fd90f55b
|
|||
04c03f7404 | |||
bf1a6a2996
|
|||
be0bb6238f
|
|||
d0f4f38381 | |||
b5da68ac9a
|
|||
92138567a1
|
@ -1,10 +0,0 @@
|
|||||||
#Build
|
|
||||||
build
|
|
||||||
#Webpack
|
|
||||||
webpack.config.ts
|
|
||||||
webpack.config.dev.ts
|
|
||||||
webpack.config.dev.server.ts
|
|
||||||
webpack.cy.config.ts
|
|
||||||
#Service Worker
|
|
||||||
service-worker.ts
|
|
||||||
serviceWorkerRegistration.ts
|
|
52
.eslintrc.js
52
.eslintrc.js
@ -1,52 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
'env': {
|
|
||||||
'browser': true,
|
|
||||||
'node': true,
|
|
||||||
'es2021': true
|
|
||||||
},
|
|
||||||
'extends': [
|
|
||||||
'eslint:recommended',
|
|
||||||
'plugin:react/recommended',
|
|
||||||
'plugin:@typescript-eslint/recommended'
|
|
||||||
],
|
|
||||||
'parser': '@typescript-eslint/parser',
|
|
||||||
'parserOptions': {
|
|
||||||
'ecmaFeatures': {
|
|
||||||
'jsx': true
|
|
||||||
},
|
|
||||||
'ecmaVersion': 'latest',
|
|
||||||
'sourceType': 'module'
|
|
||||||
},
|
|
||||||
'plugins': [
|
|
||||||
'react',
|
|
||||||
'@typescript-eslint'
|
|
||||||
],
|
|
||||||
'rules': {
|
|
||||||
'indent': [
|
|
||||||
'error',
|
|
||||||
'tab'
|
|
||||||
],
|
|
||||||
'linebreak-style': [
|
|
||||||
'error',
|
|
||||||
'unix'
|
|
||||||
],
|
|
||||||
'quotes': [
|
|
||||||
'error',
|
|
||||||
'single'
|
|
||||||
],
|
|
||||||
'semi': [
|
|
||||||
'error',
|
|
||||||
'always'
|
|
||||||
],
|
|
||||||
'eol-last': [
|
|
||||||
'error',
|
|
||||||
'always'
|
|
||||||
],
|
|
||||||
'@typescript-eslint/no-var-requires': 0,
|
|
||||||
},
|
|
||||||
'settings': {
|
|
||||||
'react': {
|
|
||||||
'version': 'detect',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
39
.github/workflows/main-workflow.yml
vendored
39
.github/workflows/main-workflow.yml
vendored
@ -14,19 +14,15 @@ jobs:
|
|||||||
# Job to run unit tests
|
# Job to run unit tests
|
||||||
unit-front-end-testing:
|
unit-front-end-testing:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
node-version: [16.x]
|
|
||||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Use Node.js 16
|
- name: Use Node.js LTS
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 'lts/*'
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
registry-url: https://registry.npmjs.org/
|
registry-url: https://registry.npmjs.org/
|
||||||
- run: npm ci
|
- run: npm ci --legacy-peer-deps
|
||||||
- run: npm test
|
- run: npm test
|
||||||
|
|
||||||
# Job to run Cypress component tests
|
# Job to run Cypress component tests
|
||||||
@ -34,11 +30,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
# Install NPM dependencies, cache them correctly
|
# Install NPM dependencies, cache them correctly
|
||||||
# and run all Cypress tests
|
# and run all Cypress tests
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: npm ci --legacy-peer-deps
|
||||||
- name: Cypress run
|
- name: Cypress run
|
||||||
uses: cypress-io/github-action@v6 # use the explicit version number
|
uses: cypress-io/github-action@v6 # use the explicit version number
|
||||||
with:
|
with:
|
||||||
@ -50,13 +46,14 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
PORT: 3000
|
PORT: 3000
|
||||||
|
PUBLIC_URL: /
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
# Install NPM dependencies, cache them correctly
|
# Install NPM dependencies, cache them correctly
|
||||||
# and run all Cypress tests
|
# and run all Cypress tests
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: npm ci --legacy-peer-deps
|
||||||
- name: Cypress run
|
- name: Cypress run
|
||||||
uses: cypress-io/github-action@v6 # use the explicit version number
|
uses: cypress-io/github-action@v6 # use the explicit version number
|
||||||
with:
|
with:
|
||||||
@ -70,12 +67,12 @@ jobs:
|
|||||||
needs: [ unit-front-end-testing, cypress-components-testing, end-to-end-testing ]
|
needs: [ unit-front-end-testing, cypress-components-testing, end-to-end-testing ]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 'lts/*'
|
||||||
registry-url: https://registry.npmjs.org/
|
registry-url: https://registry.npmjs.org/
|
||||||
- run: npm ci
|
- run: npm ci --legacy-peer-deps
|
||||||
- run: npm run build
|
- run: npm run build
|
||||||
|
|
||||||
# Job to publish the package to NPM
|
# Job to publish the package to NPM
|
||||||
@ -84,12 +81,12 @@ jobs:
|
|||||||
needs: [ unit-front-end-testing, cypress-components-testing, end-to-end-testing ]
|
needs: [ unit-front-end-testing, cypress-components-testing, end-to-end-testing ]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 'lts/*'
|
||||||
registry-url: https://registry.npmjs.org/
|
registry-url: https://registry.npmjs.org/
|
||||||
- run: npm ci
|
- run: npm ci --legacy-peer-deps
|
||||||
- run: npm publish --access=public
|
- run: npm publish --access=public
|
||||||
env:
|
env:
|
||||||
NPM_PERSONAL_TOKEN: ${{secrets.npm_token}}
|
NPM_PERSONAL_TOKEN: ${{secrets.npm_token}}
|
@ -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 |
|
Tech(Library or Framework) | Version |
|
||||||
--- | --- |
|
--- | --- |
|
||||||
React (Render Library) | 18.3.1
|
React (Render Library) | 19.1.0
|
||||||
Redux (Global State Management) | 5.0.1
|
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
|
Jest (Testing) | 29.7.0
|
||||||
Cypress (E2E Testing) | 13.14.2
|
Cypress (E2E Testing) | 14.4.1
|
||||||
Typescript | 5.6.2
|
Typescript | 5.8.3
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
To create a new project run in the terminal:
|
To create a new project run in the terminal:
|
||||||
|
142
bin/cli.js
142
bin/cli.js
@ -2,62 +2,62 @@
|
|||||||
const { execSync } = require('child_process');
|
const { execSync } = require('child_process');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
|
||||||
const isWin = process.platform === "win32";
|
const isWin = process.platform === 'win32';
|
||||||
|
|
||||||
const runCommand = command => {
|
const runCommand = command => {
|
||||||
try{
|
try{
|
||||||
execSync(`${command}`, {stdio: 'inherit'});
|
execSync(`${command}`, {stdio: 'inherit'});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Failed to execute ${command}`, e);
|
console.error(`Failed to execute ${command}`, e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
};
|
||||||
|
|
||||||
const runCommandWithOutput = command => {
|
const runCommandWithOutput = command => {
|
||||||
try{
|
try{
|
||||||
return execSync(`${command}`);
|
return execSync(`${command}`);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Failed to execute ${command}`, e);
|
console.error(`Failed to execute ${command}`, e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const replaceTextOnFile = ({
|
const replaceTextOnFile = ({
|
||||||
file,
|
file,
|
||||||
textToBeReplaced,
|
textToBeReplaced,
|
||||||
textReplace,
|
textReplace,
|
||||||
arrOfObjectsBeReplaced
|
arrOfObjectsBeReplaced
|
||||||
}) => {
|
}) => {
|
||||||
let data
|
let data;
|
||||||
try{
|
try{
|
||||||
data = fs.readFileSync(file, 'utf8');
|
data = fs.readFileSync(file, 'utf8');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Failed to read file ${file}`, e);
|
console.error(`Failed to read file ${file}`, e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let result
|
let result;
|
||||||
if(arrOfObjectsBeReplaced){
|
if(arrOfObjectsBeReplaced){
|
||||||
arrOfObjectsBeReplaced.forEach( obj => {
|
arrOfObjectsBeReplaced.forEach( obj => {
|
||||||
if(result){
|
if(result){
|
||||||
result = result.replace(obj.textToBeReplaced, obj.textReplace).replace(/^\s*[\r\n]/gm, ' ');
|
result = result.replace(obj.textToBeReplaced, obj.textReplace).replace(/^\s*[\r\n]/gm, ' ');
|
||||||
}else{
|
}else{
|
||||||
result = data.replace(obj.textToBeReplaced, obj.textReplace).replace(/^\s*[\r\n]/gm, ' ');
|
result = data.replace(obj.textToBeReplaced, obj.textReplace).replace(/^\s*[\r\n]/gm, ' ');
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}else{
|
}else{
|
||||||
result = data.replace(textToBeReplaced, textReplace).replace(/^\s*[\r\n]/gm, ' ');
|
result = data.replace(textToBeReplaced, textReplace).replace(/^\s*[\r\n]/gm, ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
try{
|
try{
|
||||||
console.log('text changed')
|
console.log('text changed');
|
||||||
fs.writeFileSync(file, result, 'utf8');
|
fs.writeFileSync(file, result, 'utf8');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Failed to read file ${file}`, e);
|
console.error(`Failed to read file ${file}`, e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const repoName = process.argv[2];
|
const repoName = process.argv[2];
|
||||||
const gitCheckoutCommand = `git clone --depth 1 https://github.com/aleleba/create-react-ssr ${repoName}`;
|
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);
|
const checkedOut = runCommand(gitCheckoutCommand);
|
||||||
if(!checkedOut) process.exit(-1);
|
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 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 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 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 deleteFoldersCommand = `cd ${repoName} && rm -rf .github && rm -rf bin`;
|
||||||
const deleteFoldersCommandWindows = `cd ${repoName} && rmdir .github /s /q && rmdir bin /s /q`
|
const deleteFoldersCommandWindows = `cd ${repoName} && rmdir .github /s /q && rmdir bin /s /q`;
|
||||||
|
|
||||||
console.log(`Installing dependencies for ${repoName}`);
|
console.log(`Installing dependencies for ${repoName}`);
|
||||||
const installedDeps = runCommand(installDepsCommand);
|
const installedDeps = runCommand(installDepsCommand);
|
||||||
@ -79,31 +79,31 @@ if(!installedDeps) process.exit(-1);
|
|||||||
|
|
||||||
console.log(`Replacing Json data for ${repoName}`);
|
console.log(`Replacing Json data for ${repoName}`);
|
||||||
replaceTextOnFile({
|
replaceTextOnFile({
|
||||||
file: `./${repoName}/package.json`,
|
file: `./${repoName}/package.json`,
|
||||||
arrOfObjectsBeReplaced: [
|
arrOfObjectsBeReplaced: [
|
||||||
{
|
{
|
||||||
textToBeReplaced: `"bin": "./bin/cli.js",`,
|
textToBeReplaced: '"bin": "./bin/cli.js",',
|
||||||
textReplace: ``
|
textReplace: ''
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
textToBeReplaced: `"version": "${actualVersion}",`,
|
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}",`
|
textReplace: `"name": "${repoName}",`
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
});
|
||||||
|
|
||||||
console.log(`Cleaning History of Git for ${repoName}`);
|
console.log(`Cleaning History of Git for ${repoName}`);
|
||||||
const cleanGitHistory = isWin ? runCommand(cleanGitHistoryCommandWindows) : runCommand(cleanGitHistoryCommand);
|
const cleanGitHistory = isWin ? runCommand(cleanGitHistoryCommandWindows) : runCommand(cleanGitHistoryCommand);
|
||||||
if(!cleanGitHistory) process.exit(-1);
|
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(`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('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);
|
const deleteFolders = isWin ? runCommand(deleteFoldersCommandWindows) : runCommand(deleteFoldersCommand);
|
||||||
if(!deleteFolders) process.exit(-1);
|
if(!deleteFolders) process.exit(-1);
|
||||||
|
@ -4,7 +4,7 @@ export const deFaultValues = {
|
|||||||
PUBLIC_URL: 'auto',
|
PUBLIC_URL: 'auto',
|
||||||
PREFIX_URL: '',
|
PREFIX_URL: '',
|
||||||
ONLY_EXACT_PATH: false,
|
ONLY_EXACT_PATH: false,
|
||||||
}
|
};
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
ENV: process.env.ENV ? process.env.ENV : deFaultValues.ENV,
|
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,
|
ONLY_EXACT_PATH: process.env.ONLY_EXACT_PATH ? process.env.ONLY_EXACT_PATH === 'true' : deFaultValues.ONLY_EXACT_PATH,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config
|
export default config;
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
describe('Initial Component Tests', () => {
|
describe('Initial Component Tests', () => {
|
||||||
it('Will show the Initial Component page.', () => {
|
it('Will show the Initial Component page.', () => {
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
cy.get('a').contains('Other Component');
|
cy.get('a').contains('Other Component');
|
||||||
});
|
});
|
||||||
it('Will Redirect to Other Component page.', () => {
|
it('Will Redirect to Other Component page.', () => {
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
cy.get('a').contains('Other Component').click();
|
cy.get('a').contains('Other Component').click();
|
||||||
cy.get('a').contains('Initial Component');
|
cy.get('a').contains('Initial Component');
|
||||||
});
|
});
|
||||||
it('Will show the Other Component page.', () => {
|
it('Will show the Other Component page.', () => {
|
||||||
cy.visit('/other-component');
|
cy.visit('/other-component');
|
||||||
cy.get('a').contains('Initial Component');
|
cy.get('a').contains('Initial Component');
|
||||||
});
|
});
|
||||||
it('Will Redirect to Initial Component page.', () => {
|
it('Will Redirect to Initial Component page.', () => {
|
||||||
cy.visit('/other-component');
|
cy.visit('/other-component');
|
||||||
cy.get('a').contains('Initial Component').click();
|
cy.get('a').contains('Initial Component').click();
|
||||||
cy.get('a').contains('Other Component');
|
cy.get('a').contains('Other Component');
|
||||||
});
|
});
|
||||||
});
|
});
|
@ -22,7 +22,7 @@ import './commands';
|
|||||||
// Alternatively you can use CommonJS syntax:
|
// Alternatively you can use CommonJS syntax:
|
||||||
// require('./commands')
|
// require('./commands')
|
||||||
|
|
||||||
import { mount } from 'cypress/react18';
|
import { mount } from '@cypress/react';
|
||||||
|
|
||||||
// Augment the Cypress namespace to include type definitions for
|
// Augment the Cypress namespace to include type definitions for
|
||||||
// your custom command.
|
// your custom command.
|
||||||
|
65
eslint.config.ts
Normal file
65
eslint.config.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import eslint from '@eslint/js';
|
||||||
|
import tseslint from 'typescript-eslint';
|
||||||
|
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}'],
|
||||||
|
languageOptions: {
|
||||||
|
ecmaVersion: 'latest',
|
||||||
|
sourceType: 'module',
|
||||||
|
parser: tseslint.parser,
|
||||||
|
parserOptions: {
|
||||||
|
ecmaFeatures: {
|
||||||
|
jsx: true
|
||||||
|
},
|
||||||
|
globals: {
|
||||||
|
...globals.browser,
|
||||||
|
...globals.node,
|
||||||
|
...globals.es2021
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
react: reactPlugin,
|
||||||
|
'@typescript-eslint': tseslint.plugin
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
react: {
|
||||||
|
version: 'detect'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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',
|
||||||
|
'@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',
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
12118
package-lock.json
generated
12118
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
88
package.json
88
package.json
@ -1,19 +1,19 @@
|
|||||||
{
|
{
|
||||||
"name": "@aleleba/create-react-ssr",
|
"name": "@aleleba/create-react-ssr",
|
||||||
"version": "3.9.27",
|
"version": "3.10.1",
|
||||||
"description": "Starter Kit of server side render of react",
|
"description": "Starter Kit of server side render of react",
|
||||||
"bin": "./bin/cli.js",
|
"bin": "./bin/cli.js",
|
||||||
"main": "src/server/index",
|
"main": "src/server/index",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node build/server/app-server.js",
|
"start": "node build/server/app-server.js",
|
||||||
"start:dev": "rm -rf 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 --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",
|
"build": "webpack-cli --config webpack.config.ts",
|
||||||
"lint": "eslint ./ --ext .js --ext .ts --ext .jsx --ext .tsx",
|
"lint": "eslint ./ --ext .js --ext .ts --ext .jsx --ext .tsx",
|
||||||
"lint:fix": "eslint ./ --ext .js --ext .ts --ext .jsx --ext .tsx --fix",
|
"lint:fix": "eslint ./ --ext .js --ext .ts --ext .jsx --ext .tsx --fix",
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"test:watch": "jest --watch",
|
"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:open": "npx cypress open",
|
||||||
"cy:run": "cypress run",
|
"cy:run": "cypress run",
|
||||||
"cy:run-component": "cypress run --headless --component"
|
"cy:run-component": "cypress run --headless --component"
|
||||||
@ -36,21 +36,21 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/aleleba/create-react-ssr#readme",
|
"homepage": "https://github.com/aleleba/create-react-ssr#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/register": "^7.25.9",
|
"@babel/register": "^7.27.1",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.5.0",
|
||||||
"express": "^4.21.1",
|
"express": "^5.1.0",
|
||||||
"helmet": "^8.0.0",
|
"helmet": "^8.1.0",
|
||||||
"history": "^5.3.0",
|
"history": "^5.3.0",
|
||||||
"ignore-styles": "^5.0.1",
|
"ignore-styles": "^5.0.1",
|
||||||
"react": "^18.3.1",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^19.1.0",
|
||||||
"react-redux": "^9.1.2",
|
"react-redux": "^9.2.0",
|
||||||
"react-router-dom": "^6.28.0",
|
"react-router-dom": "^7.6.2",
|
||||||
"react-router-hash-link": "^2.4.3",
|
"react-router-hash-link": "^2.4.3",
|
||||||
"redux": "^5.0.1",
|
"redux": "^5.0.1",
|
||||||
"webpack": "^5.96.1",
|
"webpack": "^5.99.9",
|
||||||
"webpack-dev-server": "^5.1.0",
|
"webpack-dev-server": "^5.2.2",
|
||||||
"webpack-manifest-plugin": "^5.0.0",
|
"webpack-manifest-plugin": "^5.0.1",
|
||||||
"workbox-background-sync": "^7.3.0",
|
"workbox-background-sync": "^7.3.0",
|
||||||
"workbox-broadcast-update": "^7.3.0",
|
"workbox-broadcast-update": "^7.3.0",
|
||||||
"workbox-cacheable-response": "^7.3.0",
|
"workbox-cacheable-response": "^7.3.0",
|
||||||
@ -65,52 +65,58 @@
|
|||||||
"workbox-streams": "^7.3.0"
|
"workbox-streams": "^7.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.26.0",
|
"@babel/core": "^7.27.4",
|
||||||
"@babel/preset-env": "^7.26.0",
|
"@babel/preset-env": "^7.27.2",
|
||||||
"@babel/preset-react": "^7.25.9",
|
"@babel/preset-react": "^7.27.1",
|
||||||
"@babel/preset-typescript": "^7.26.0",
|
"@babel/preset-typescript": "^7.27.1",
|
||||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.15",
|
"@cypress/react": "^9.0.1",
|
||||||
|
"@eslint/js": "^9.28.0",
|
||||||
|
"@pmmmwh/react-refresh-webpack-plugin": "^0.6.0",
|
||||||
"@redux-devtools/extension": "^3.3.0",
|
"@redux-devtools/extension": "^3.3.0",
|
||||||
|
"@testing-library/dom": "^10.4.0",
|
||||||
"@testing-library/jest-dom": "^6.6.3",
|
"@testing-library/jest-dom": "^6.6.3",
|
||||||
"@testing-library/react": "^16.0.1",
|
"@testing-library/react": "^16.3.0",
|
||||||
"@testing-library/user-event": "^14.5.2",
|
"@testing-library/user-event": "^14.6.1",
|
||||||
"@types/jest": "^29.5.14",
|
"@types/jest": "^29.5.14",
|
||||||
"@types/node": "^22.9.0",
|
"@types/node": "^22.15.30",
|
||||||
"@types/react": "^18.3.12",
|
"@types/react": "^19.1.6",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "^19.1.6",
|
||||||
"@types/webpack": "^5.28.5",
|
"@types/webpack": "^5.28.5",
|
||||||
"@types/webpack-hot-middleware": "^2.25.9",
|
"@types/webpack-hot-middleware": "^2.25.9",
|
||||||
"@types/webpack-node-externals": "^3.0.4",
|
"@types/webpack-node-externals": "^3.0.4",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.14.0",
|
"@typescript-eslint/eslint-plugin": "^8.33.1",
|
||||||
"@typescript-eslint/parser": "^8.14.0",
|
"@typescript-eslint/parser": "^8.33.1",
|
||||||
"babel-jest": "^29.7.0",
|
"babel-jest": "^29.7.0",
|
||||||
"babel-loader": "^9.2.1",
|
"babel-loader": "^10.0.0",
|
||||||
"clean-webpack-plugin": "^4.0.0",
|
"clean-webpack-plugin": "^4.0.0",
|
||||||
"compression-webpack-plugin": "^11.1.0",
|
"compression-webpack-plugin": "^11.1.0",
|
||||||
"copy-webpack-plugin": "^12.0.2",
|
"copy-webpack-plugin": "^13.0.0",
|
||||||
"css-loader": "^7.1.2",
|
"css-loader": "^7.1.2",
|
||||||
"css-minimizer-webpack-plugin": "^7.0.0",
|
"css-minimizer-webpack-plugin": "^7.0.2",
|
||||||
"cypress": "^13.15.2",
|
"cypress": "^14.4.1",
|
||||||
"eslint": "^9.14.0",
|
"eslint": "^9.28.0",
|
||||||
"eslint-plugin-react": "^7.37.2",
|
"eslint-plugin-react": "^7.37.5",
|
||||||
"eslint-webpack-plugin": "^4.2.0",
|
"eslint-webpack-plugin": "^5.0.1",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
|
"globals": "^16.2.0",
|
||||||
"html-webpack-plugin": "^5.6.3",
|
"html-webpack-plugin": "^5.6.3",
|
||||||
"identity-obj-proxy": "^3.0.0",
|
"identity-obj-proxy": "^3.0.0",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"jest-environment-jsdom": "^29.7.0",
|
"jest-environment-jsdom": "^29.7.0",
|
||||||
"jest-fetch-mock": "^3.0.3",
|
"jest-fetch-mock": "^3.0.3",
|
||||||
|
"jiti": "^2.4.2",
|
||||||
"mini-css-extract-plugin": "^2.9.2",
|
"mini-css-extract-plugin": "^2.9.2",
|
||||||
"react-refresh": "^0.14.2",
|
"react-refresh": "^0.17.0",
|
||||||
"resolve-ts-aliases": "^1.0.1",
|
"resolve-ts-aliases": "^1.0.1",
|
||||||
"sass": "^1.80.7",
|
"sass": "^1.89.1",
|
||||||
"sass-loader": "^16.0.3",
|
"sass-loader": "^16.0.5",
|
||||||
"style-loader": "^4.0.0",
|
"style-loader": "^4.0.0",
|
||||||
"terser-webpack-plugin": "^5.3.10",
|
"terser-webpack-plugin": "^5.3.14",
|
||||||
"ts-jest": "^29.2.5",
|
"ts-jest": "^29.3.4",
|
||||||
"typescript": "^5.6.3",
|
"typescript": "^5.8.3",
|
||||||
|
"typescript-eslint": "^8.33.1",
|
||||||
"url-loader": "^4.1.1",
|
"url-loader": "^4.1.1",
|
||||||
"webpack-cli": "^5.1.4",
|
"webpack-cli": "^6.0.1",
|
||||||
"webpack-dev-middleware": "^7.4.2",
|
"webpack-dev-middleware": "^7.4.2",
|
||||||
"webpack-hot-middleware": "^2.26.1",
|
"webpack-hot-middleware": "^2.26.1",
|
||||||
"webpack-node-externals": "^3.0.0",
|
"webpack-node-externals": "^3.0.0",
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
// expect(element).toHaveTextContent(/react/i)
|
// expect(element).toHaveTextContent(/react/i)
|
||||||
// learn more: https://github.com/testing-library/jest-dom
|
// learn more: https://github.com/testing-library/jest-dom
|
||||||
import '@testing-library/jest-dom';
|
import '@testing-library/jest-dom';
|
||||||
|
import { TextEncoder, TextDecoder } from 'util';
|
||||||
|
|
||||||
//import fetch Mock
|
//import fetch Mock
|
||||||
import fetchMock from 'jest-fetch-mock';
|
import fetchMock from 'jest-fetch-mock';
|
||||||
@ -18,3 +19,6 @@ function() {
|
|||||||
removeListener: () => {/**/}
|
removeListener: () => {/**/}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
global.TextEncoder = TextEncoder;
|
||||||
|
global.TextDecoder = TextDecoder as typeof global.TextDecoder;
|
||||||
|
2
src/@types/express/index.d.ts
vendored
2
src/@types/express/index.d.ts
vendored
@ -1,4 +1,4 @@
|
|||||||
import * as express from "express"
|
import * as express from 'express';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
namespace Express {
|
namespace Express {
|
||||||
|
9
src/@types/index.d.ts
vendored
9
src/@types/index.d.ts
vendored
@ -1,4 +1,11 @@
|
|||||||
declare module "*.svg" {
|
declare module '*.svg' {
|
||||||
const content: any;
|
const content: any;
|
||||||
export default content;
|
export default content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare const module: {
|
||||||
|
hot?: {
|
||||||
|
accept(dep?: string, callback?: () => void): void;
|
||||||
|
dispose(callback: () => void): void;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
@ -6,22 +6,22 @@ import initialStateReducer from '../frontend/reducers/initialState';
|
|||||||
import setStore from '../frontend/setStore';
|
import setStore from '../frontend/setStore';
|
||||||
|
|
||||||
export const ProviderMock = ({ children, initialState }: { children: any, initialState?: any}) => {
|
export const ProviderMock = ({ children, initialState }: { children: any, initialState?: any}) => {
|
||||||
let initialStateMock = initialStateReducer
|
let initialStateMock = initialStateReducer;
|
||||||
|
|
||||||
if(initialState !== undefined){
|
if(initialState !== undefined){
|
||||||
initialStateMock = initialState
|
initialStateMock = initialState;
|
||||||
}
|
}
|
||||||
|
|
||||||
const history = createMemoryHistory();
|
const history = createMemoryHistory();
|
||||||
const store = setStore({ initialState: initialStateMock });
|
const store = setStore({ initialState: initialStateMock });
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<Router location={history.location} navigator={history}>
|
<Router location={history.location} navigator={history}>
|
||||||
{children}
|
{children}
|
||||||
</Router>
|
</Router>
|
||||||
</Provider>
|
</Provider>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default ProviderMock;
|
export default ProviderMock;
|
||||||
|
@ -1,9 +1 @@
|
|||||||
import test, { TTest } from './testAction';
|
export * from '@actions/testAction';
|
||||||
|
|
||||||
export type TAction = TTest
|
|
||||||
|
|
||||||
const actions = {
|
|
||||||
test
|
|
||||||
}
|
|
||||||
|
|
||||||
export default actions
|
|
||||||
|
@ -14,12 +14,12 @@ export interface IChangeHelloPayload {
|
|||||||
export type TTest = IChangeHello
|
export type TTest = IChangeHello
|
||||||
|
|
||||||
const changeHello = (payload: string) => ({
|
const changeHello = (payload: string) => ({
|
||||||
type: ActionTypesTest.ChangeHello,
|
type: ActionTypesTest.ChangeHello,
|
||||||
payload
|
payload
|
||||||
})
|
});
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
changeHello
|
changeHello
|
||||||
}
|
};
|
||||||
|
|
||||||
export default actions
|
export default actions;
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import logo from '../logo.svg';
|
import logo from '../logo.svg';
|
||||||
import './InitialComponent.scss';
|
import './InitialComponent.scss';
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
const OtherComponent = () => (
|
const OtherComponent = () => (
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<header className="App-header">
|
<header className="App-header">
|
||||||
<img src="assets/img/logo.svg" className="App-logo" alt="logo" />
|
<img src="assets/img/logo.svg" className="App-logo" alt="logo" />
|
||||||
<p>
|
<p>
|
||||||
Edit <code>src/frontend/OtherComponent.jsx</code> and save to reload.
|
Edit <code>src/frontend/OtherComponent.jsx</code> and save to reload.
|
||||||
</p>
|
</p>
|
||||||
<Link className="App-link" to="/">Initial Component</Link>
|
<Link className="App-link" to="/">Initial Component</Link>
|
||||||
</header>
|
</header>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default OtherComponent;
|
export default OtherComponent;
|
||||||
|
@ -4,7 +4,7 @@ import { useRoutes } from 'react-router-dom';
|
|||||||
import routes from '../../routes';
|
import routes from '../../routes';
|
||||||
|
|
||||||
const PrincipalRoutes = () => {
|
const PrincipalRoutes = () => {
|
||||||
let element = useRoutes(routes);
|
const element = useRoutes(routes);
|
||||||
return element;
|
return element;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,20 +4,20 @@ import { ProviderMock } from '@mocks';
|
|||||||
import App from '@components/App';
|
import App from '@components/App';
|
||||||
|
|
||||||
describe('<App/> Component', () => {
|
describe('<App/> Component', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fetchMock.resetMocks();
|
fetchMock.resetMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should render root <App /> Component', async () => {
|
it('Should render root <App /> Component', async () => {
|
||||||
fetchMock.mockResponseOnce(JSON.stringify({
|
fetchMock.mockResponseOnce(JSON.stringify({
|
||||||
//First Data Fetch
|
//First Data Fetch
|
||||||
data: 'data'
|
data: 'data'
|
||||||
}));
|
}));
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<ProviderMock>
|
<ProviderMock>
|
||||||
<App />
|
<App />
|
||||||
</ProviderMock>
|
</ProviderMock>
|
||||||
)
|
);
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
import { combineReducers } from 'redux';
|
import { combineReducers } from 'redux';
|
||||||
import testReducer from './testReducer';
|
import testReducer from './testReducer';
|
||||||
import { IChangeHelloPayload } from '../actions/testAction';
|
export * from './initialState';
|
||||||
|
|
||||||
export interface IInitialState {
|
|
||||||
testReducer?: IChangeHelloPayload | undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
const rootReducer = combineReducers({
|
const rootReducer = combineReducers({
|
||||||
// Here comes the reducers
|
// Here comes the reducers
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
import { IInitialState } from './';
|
import { IChangeHelloPayload } from '@actions';
|
||||||
|
export interface IInitialState {
|
||||||
|
testReducer?: IChangeHelloPayload | undefined
|
||||||
|
}
|
||||||
const initialState: IInitialState = {};
|
const initialState: IInitialState = {};
|
||||||
export default initialState;
|
export default initialState;
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { TAction } from '../actions';
|
import { TTest } from '@actions';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
hello: 'world'
|
hello: 'world'
|
||||||
};
|
};
|
||||||
|
|
||||||
const testReducer = (state = initialState, action: TAction) => {
|
const testReducer = (state = initialState, action: TTest) => {
|
||||||
switch (action.type){
|
switch (action.type){
|
||||||
case 'CHANGE_HELLO': {
|
case 'CHANGE_HELLO': {
|
||||||
const newHello = action.payload.hello;
|
const newHello = action.payload.hello;
|
||||||
|
@ -3,8 +3,7 @@ import { legacy_createStore as createStore} from 'redux'; //, applyMiddleware
|
|||||||
// import { Provider } from 'react-redux';
|
// import { Provider } from 'react-redux';
|
||||||
import { composeWithDevTools as composeWithDevToolsWeb } from '@redux-devtools/extension';
|
import { composeWithDevTools as composeWithDevToolsWeb } from '@redux-devtools/extension';
|
||||||
import { config } from '../../config';
|
import { config } from '../../config';
|
||||||
import reducer, { IInitialState } from './reducers';
|
import reducer, { IInitialState } from '@reducers';
|
||||||
|
|
||||||
|
|
||||||
const { ENV } = config;
|
const { ENV } = config;
|
||||||
|
|
||||||
@ -15,11 +14,11 @@ const composeEnhancers = composeWithDevToolsWeb({
|
|||||||
const setStore = ({ initialState }: { initialState: IInitialState | undefined }) => {
|
const setStore = ({ initialState }: { initialState: IInitialState | undefined }) => {
|
||||||
const store = ENV === 'development' ? createStore(
|
const store = ENV === 'development' ? createStore(
|
||||||
reducer,
|
reducer,
|
||||||
initialState,
|
initialState as any,
|
||||||
composeEnhancers(),
|
composeEnhancers(),
|
||||||
) : createStore(
|
) : createStore(
|
||||||
reducer,
|
reducer,
|
||||||
initialState,
|
initialState as any,
|
||||||
);
|
);
|
||||||
return store;
|
return store;
|
||||||
};
|
};
|
||||||
|
@ -14,7 +14,7 @@ import webpackHotMiddleware from 'webpack-hot-middleware';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { renderToString } from 'react-dom/server';
|
import { renderToString } from 'react-dom/server';
|
||||||
//Router
|
//Router
|
||||||
import { StaticRouter } from 'react-router-dom/server';
|
import { StaticRouter } from 'react-router-dom';
|
||||||
import routes from '../routes';
|
import routes from '../routes';
|
||||||
//Redux
|
//Redux
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
@ -129,8 +129,21 @@ const renderApp = (req, res, next) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
app
|
app
|
||||||
.get('*', renderApp);
|
.get('/{*splat}', renderApp);
|
||||||
|
|
||||||
app.listen(PORT, () => {
|
const server = app.listen(PORT, () => {
|
||||||
console.log(`Server running on port ${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');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -3,7 +3,7 @@ import webpackNodeExternals from 'webpack-node-externals';
|
|||||||
import WebpackShellPluginNext from 'webpack-shell-plugin-next';
|
import WebpackShellPluginNext from 'webpack-shell-plugin-next';
|
||||||
import { resolveTsAliases } from 'resolve-ts-aliases';
|
import { resolveTsAliases } from 'resolve-ts-aliases';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { Configuration } from 'webpack';
|
import webpack, { Configuration } from 'webpack';
|
||||||
const ROOT_DIR = path.resolve(__dirname);
|
const ROOT_DIR = path.resolve(__dirname);
|
||||||
const resolvePath = (...args: string[]) => path.resolve(ROOT_DIR, ...args);
|
const resolvePath = (...args: string[]) => path.resolve(ROOT_DIR, ...args);
|
||||||
const BUILD_DIR = resolvePath('build');
|
const BUILD_DIR = resolvePath('build');
|
||||||
@ -18,7 +18,18 @@ const config: Configuration = {
|
|||||||
mode: 'development',
|
mode: 'development',
|
||||||
name: 'server',
|
name: 'server',
|
||||||
entry: {
|
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: {
|
resolve: {
|
||||||
extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
|
extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
|
||||||
@ -49,7 +60,16 @@ const config: Configuration = {
|
|||||||
'options': {
|
'options': {
|
||||||
modules: {
|
modules: {
|
||||||
auto: /\.module\.\w+$/i,
|
auto: /\.module\.\w+$/i,
|
||||||
}
|
},
|
||||||
|
url: {
|
||||||
|
filter: (url) => {
|
||||||
|
// No procesar URLs absolutas que comienzan con /
|
||||||
|
if (url.startsWith('/')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'sass-loader',
|
'sass-loader',
|
||||||
@ -79,8 +99,11 @@ const config: Configuration = {
|
|||||||
libraryTarget: 'commonjs2',
|
libraryTarget: 'commonjs2',
|
||||||
},
|
},
|
||||||
node: false,
|
node: false,
|
||||||
externals: [webpackNodeExternals()],
|
externals: [webpackNodeExternals({
|
||||||
|
allowlist: ['webpack/hot/poll?1000']
|
||||||
|
})],
|
||||||
plugins: [
|
plugins: [
|
||||||
|
new webpack.HotModuleReplacementPlugin(),
|
||||||
new MiniCssExtractPlugin({
|
new MiniCssExtractPlugin({
|
||||||
filename: 'assets/app.css',
|
filename: 'assets/app.css',
|
||||||
}),
|
}),
|
||||||
|
@ -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 = {
|
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`],
|
entry: [`webpack-hot-middleware/client?path=${envConfig.PREFIX_URL}/reload_wss&timeout=2000&reload=true&autoConnect=true`, `${ROOT_DIR}/../src/frontend/index.tsx`],
|
||||||
output: {
|
output: {
|
||||||
@ -68,7 +74,16 @@ const config: Configuration = {
|
|||||||
'options': {
|
'options': {
|
||||||
modules: {
|
modules: {
|
||||||
auto: /\.module\.\w+$/i,
|
auto: /\.module\.\w+$/i,
|
||||||
}
|
},
|
||||||
|
url: {
|
||||||
|
filter: (url) => {
|
||||||
|
// No procesar URLs absolutas que comienzan con /
|
||||||
|
if (url.startsWith('/')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'sass-loader',
|
'sass-loader',
|
||||||
|
@ -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 = {
|
const frontendConfig = {
|
||||||
entry: {
|
entry: {
|
||||||
frontend: `${ROOT_DIR}/src/frontend/index.tsx`,
|
frontend: `${ROOT_DIR}/src/frontend/index.tsx`,
|
||||||
@ -73,7 +79,16 @@ const frontendConfig = {
|
|||||||
'options': {
|
'options': {
|
||||||
modules: {
|
modules: {
|
||||||
auto: /\.module\.\w+$/i,
|
auto: /\.module\.\w+$/i,
|
||||||
}
|
},
|
||||||
|
url: {
|
||||||
|
filter: (url) => {
|
||||||
|
// No procesar URLs absolutas que comienzan con /
|
||||||
|
if (url.startsWith('/')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'sass-loader',
|
'sass-loader',
|
||||||
@ -186,7 +201,16 @@ const serverConfig = {
|
|||||||
'options': {
|
'options': {
|
||||||
modules: {
|
modules: {
|
||||||
auto: /\.module\.\w+$/i,
|
auto: /\.module\.\w+$/i,
|
||||||
}
|
},
|
||||||
|
url: {
|
||||||
|
filter: (url) => {
|
||||||
|
// No procesar URLs absolutas que comienzan con /
|
||||||
|
if (url.startsWith('/')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'sass-loader',
|
'sass-loader',
|
||||||
|
@ -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 {
|
export default {
|
||||||
entry: './src/frontend/components/index.tsx',
|
entry: './src/frontend/components/index.tsx',
|
||||||
resolve: {
|
resolve: {
|
||||||
@ -71,7 +77,16 @@ export default {
|
|||||||
'options': {
|
'options': {
|
||||||
modules: {
|
modules: {
|
||||||
auto: /\.module\.\w+$/i,
|
auto: /\.module\.\w+$/i,
|
||||||
}
|
},
|
||||||
|
url: {
|
||||||
|
filter: (url) => {
|
||||||
|
// No procesar URLs absolutas que comienzan con /
|
||||||
|
if (url.startsWith('/')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'sass-loader',
|
'sass-loader',
|
||||||
|
Reference in New Issue
Block a user