mirror of
https://github.com/aleleba/create-react-ssr.git
synced 2025-01-09 05:26:58 -06:00
PR-421183: Adding Cypress and updating packages.
This commit is contained in:
parent
f3f0095674
commit
a4dcc2c391
13
.github/workflows/npm-publish.yml
vendored
13
.github/workflows/npm-publish.yml
vendored
@ -14,7 +14,18 @@ jobs:
|
|||||||
registry-url: https://registry.npmjs.org/
|
registry-url: https://registry.npmjs.org/
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm test
|
- run: npm test
|
||||||
|
cypress-run:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
# Install NPM dependencies, cache them correctly
|
||||||
|
# and run all Cypress tests
|
||||||
|
- name: Cypress run
|
||||||
|
uses: cypress-io/github-action@v5.x.x # use the explicit version number
|
||||||
|
with:
|
||||||
|
build: npm run build
|
||||||
|
start: npm start
|
||||||
publish-npm:
|
publish-npm:
|
||||||
needs: build
|
needs: build
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
12
.github/workflows/npm-test.yml
vendored
12
.github/workflows/npm-test.yml
vendored
@ -20,6 +20,18 @@ jobs:
|
|||||||
registry-url: https://registry.npmjs.org/
|
registry-url: https://registry.npmjs.org/
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm test
|
- run: npm test
|
||||||
|
cypress-run:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
# Install NPM dependencies, cache them correctly
|
||||||
|
# and run all Cypress tests
|
||||||
|
- name: Cypress run
|
||||||
|
uses: cypress-io/github-action@v5.x.x # use the explicit version number
|
||||||
|
with:
|
||||||
|
build: npm run build
|
||||||
|
start: npm start
|
||||||
test-build-package:
|
test-build-package:
|
||||||
needs: test
|
needs: test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -8,8 +8,9 @@ Tech(Library or Framework) | Version |
|
|||||||
--- | --- |
|
--- | --- |
|
||||||
React (Render Library) | 18.2.0
|
React (Render Library) | 18.2.0
|
||||||
Redux (Global State Management) | 4.2.1
|
Redux (Global State Management) | 4.2.1
|
||||||
React Router DOM (Routing) | 6.8.1
|
React Router DOM (Routing) | 6.8.2
|
||||||
Jest (Testing) | 29.4.3
|
Jest (Testing) | 29.4.3
|
||||||
|
Cypress (E2E Testing) | 12.7.0
|
||||||
Typescript | 4.9.5
|
Typescript | 4.9.5
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
12
cypress.config.ts
Normal file
12
cypress.config.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { defineConfig } from 'cypress';
|
||||||
|
export default defineConfig({
|
||||||
|
env: {},
|
||||||
|
e2e: {
|
||||||
|
/*setupNodeEvents(on, config) {
|
||||||
|
// implement node event listeners here
|
||||||
|
},*/
|
||||||
|
baseUrl: 'http://localhost',
|
||||||
|
specPattern: 'cypress/e2e/**/*.{js,jsx,ts,tsx}',
|
||||||
|
experimentalRunAllSpecs: true,
|
||||||
|
},
|
||||||
|
});
|
20
cypress/e2e/App.test.ts
Normal file
20
cypress/e2e/App.test.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
describe('Initial Component Tests', () => {
|
||||||
|
it('Will show the Initial Component page.', () => {
|
||||||
|
cy.visit('/');
|
||||||
|
cy.get('a').contains('Other Component');
|
||||||
|
});
|
||||||
|
it('Will Redirect to Other Component page.', () => {
|
||||||
|
cy.visit('/');
|
||||||
|
cy.get('a').contains('Other Component').click();
|
||||||
|
cy.get('a').contains('Initial Component');
|
||||||
|
});
|
||||||
|
it('Will show the Other Component page.', () => {
|
||||||
|
cy.visit('/other-component');
|
||||||
|
cy.get('a').contains('Initial Component');
|
||||||
|
});
|
||||||
|
it('Will Redirect to Initial Component page.', () => {
|
||||||
|
cy.visit('/other-component');
|
||||||
|
cy.get('a').contains('Initial Component').click();
|
||||||
|
cy.get('a').contains('Other Component');
|
||||||
|
});
|
||||||
|
});
|
5
cypress/fixtures/example.json
Normal file
5
cypress/fixtures/example.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"name": "Using fixtures to represent data",
|
||||||
|
"email": "hello@cypress.io",
|
||||||
|
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||||
|
}
|
37
cypress/support/commands.ts
Normal file
37
cypress/support/commands.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/// <reference types="cypress" />
|
||||||
|
// ***********************************************
|
||||||
|
// This example commands.ts shows you how to
|
||||||
|
// create various custom commands and overwrite
|
||||||
|
// existing commands.
|
||||||
|
//
|
||||||
|
// For more comprehensive examples of custom
|
||||||
|
// commands please read more here:
|
||||||
|
// https://on.cypress.io/custom-commands
|
||||||
|
// ***********************************************
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This is a parent command --
|
||||||
|
// Cypress.Commands.add('login', (email, password) => { ... })
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This is a child command --
|
||||||
|
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This is a dual command --
|
||||||
|
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This will overwrite an existing command --
|
||||||
|
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||||
|
//
|
||||||
|
// declare global {
|
||||||
|
// namespace Cypress {
|
||||||
|
// interface Chainable {
|
||||||
|
// login(email: string, password: string): Chainable<void>
|
||||||
|
// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
|
||||||
|
// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
|
||||||
|
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
20
cypress/support/e2e.ts
Normal file
20
cypress/support/e2e.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// ***********************************************************
|
||||||
|
// This example support/e2e.ts is processed and
|
||||||
|
// loaded automatically before your test files.
|
||||||
|
//
|
||||||
|
// This is a great place to put global configuration and
|
||||||
|
// behavior that modifies Cypress.
|
||||||
|
//
|
||||||
|
// You can change the location of this file or turn off
|
||||||
|
// automatically serving support files with the
|
||||||
|
// 'supportFile' configuration option.
|
||||||
|
//
|
||||||
|
// You can read more here:
|
||||||
|
// https://on.cypress.io/configuration
|
||||||
|
// ***********************************************************
|
||||||
|
|
||||||
|
// Import commands.js using ES2015 syntax:
|
||||||
|
import './commands'
|
||||||
|
|
||||||
|
// Alternatively you can use CommonJS syntax:
|
||||||
|
// require('./commands')
|
@ -1,17 +1,18 @@
|
|||||||
const { pathsToModuleNameMapper } = require("ts-jest");
|
const { pathsToModuleNameMapper } = require('ts-jest');
|
||||||
const { compilerOptions } = require("./tsconfig");
|
const { compilerOptions } = require('./tsconfig');
|
||||||
|
|
||||||
const aliases = pathsToModuleNameMapper(compilerOptions.paths, {
|
const aliases = pathsToModuleNameMapper(compilerOptions.paths, {
|
||||||
prefix: "<rootDir>"
|
prefix: '<rootDir>'
|
||||||
})
|
});
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
setupFilesAfterEnv: ['<rootDir>/setupTest.ts'],
|
setupFilesAfterEnv: ['<rootDir>/setupTest.ts'],
|
||||||
testEnvironment: "jsdom",
|
testEnvironment: 'jsdom',
|
||||||
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json"],
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
|
||||||
moduleNameMapper: {
|
modulePathIgnorePatterns: ['<rootDir>/cypress/'],
|
||||||
...aliases,
|
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",
|
...aliases,
|
||||||
"\\.(css|sass|scss|less)$": "identity-obj-proxy",
|
'\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/src/__mocks__/fileMock.ts',
|
||||||
}
|
'\\.(css|sass|scss|less)$': 'identity-obj-proxy',
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
2908
package-lock.json
generated
2908
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
19
package.json
19
package.json
@ -1,18 +1,21 @@
|
|||||||
{
|
{
|
||||||
"name": "@aleleba/create-react-ssr",
|
"name": "@aleleba/create-react-ssr",
|
||||||
"version": "3.7.0",
|
"version": "3.8.0",
|
||||||
"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 --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",
|
||||||
"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",
|
||||||
|
"cy:open": "npx cypress open",
|
||||||
|
"cy:run": "cypress run"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -41,7 +44,7 @@
|
|||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-redux": "^8.0.5",
|
"react-redux": "^8.0.5",
|
||||||
"react-router-dom": "^6.8.1",
|
"react-router-dom": "^6.8.2",
|
||||||
"react-router-hash-link": "^2.4.3",
|
"react-router-hash-link": "^2.4.3",
|
||||||
"redux": "^4.2.1",
|
"redux": "^4.2.1",
|
||||||
"webpack": "^5.75.0",
|
"webpack": "^5.75.0",
|
||||||
@ -70,14 +73,14 @@
|
|||||||
"@testing-library/react": "^14.0.0",
|
"@testing-library/react": "^14.0.0",
|
||||||
"@testing-library/user-event": "^14.4.3",
|
"@testing-library/user-event": "^14.4.3",
|
||||||
"@types/jest": "^29.4.0",
|
"@types/jest": "^29.4.0",
|
||||||
"@types/node": "^18.14.0",
|
"@types/node": "^18.14.4",
|
||||||
"@types/react": "^18.0.28",
|
"@types/react": "^18.0.28",
|
||||||
"@types/react-dom": "^18.0.11",
|
"@types/react-dom": "^18.0.11",
|
||||||
"@types/webpack": "^5.28.0",
|
"@types/webpack": "^5.28.0",
|
||||||
"@types/webpack-hot-middleware": "^2.25.6",
|
"@types/webpack-hot-middleware": "^2.25.6",
|
||||||
"@types/webpack-node-externals": "^3.0.0",
|
"@types/webpack-node-externals": "^3.0.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.53.0",
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
"@typescript-eslint/parser": "^5.53.0",
|
"@typescript-eslint/parser": "^5.54.0",
|
||||||
"babel-jest": "^29.4.3",
|
"babel-jest": "^29.4.3",
|
||||||
"babel-loader": "^9.1.2",
|
"babel-loader": "^9.1.2",
|
||||||
"clean-webpack-plugin": "^4.0.0",
|
"clean-webpack-plugin": "^4.0.0",
|
||||||
@ -85,7 +88,8 @@
|
|||||||
"copy-webpack-plugin": "^11.0.0",
|
"copy-webpack-plugin": "^11.0.0",
|
||||||
"css-loader": "^6.7.3",
|
"css-loader": "^6.7.3",
|
||||||
"css-minimizer-webpack-plugin": "^4.2.2",
|
"css-minimizer-webpack-plugin": "^4.2.2",
|
||||||
"eslint": "^8.34.0",
|
"cypress": "^12.7.0",
|
||||||
|
"eslint": "^8.35.0",
|
||||||
"eslint-plugin-react": "^7.32.2",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"eslint-webpack-plugin": "^4.0.0",
|
"eslint-webpack-plugin": "^4.0.0",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
@ -101,7 +105,6 @@
|
|||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
"terser-webpack-plugin": "^5.3.6",
|
"terser-webpack-plugin": "^5.3.6",
|
||||||
"ts-jest": "^29.0.5",
|
"ts-jest": "^29.0.5",
|
||||||
"ts-loader": "^9.4.2",
|
|
||||||
"typescript": "^4.9.5",
|
"typescript": "^4.9.5",
|
||||||
"url-loader": "^4.1.1",
|
"url-loader": "^4.1.1",
|
||||||
"webpack-cli": "^5.0.1",
|
"webpack-cli": "^5.0.1",
|
||||||
|
12
setupTest.ts
12
setupTest.ts
@ -5,16 +5,16 @@
|
|||||||
import '@testing-library/jest-dom';
|
import '@testing-library/jest-dom';
|
||||||
|
|
||||||
//import fetch Mock
|
//import fetch Mock
|
||||||
import fetchMock from "jest-fetch-mock";
|
import fetchMock from 'jest-fetch-mock';
|
||||||
fetchMock.enableMocks();
|
fetchMock.enableMocks();
|
||||||
|
|
||||||
//Fixing Pollyfill for react-slick
|
//Fixing Pollyfill for react-slick
|
||||||
window.matchMedia =
|
window.matchMedia =
|
||||||
window.matchMedia ||
|
window.matchMedia ||
|
||||||
function() {
|
function() {
|
||||||
return {
|
return {
|
||||||
matches: false,
|
matches: false,
|
||||||
addListener: function() {},
|
addListener: () => {/**/},
|
||||||
removeListener: function() {}
|
removeListener: () => {/**/}
|
||||||
};
|
};
|
||||||
};
|
};
|
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||||
//Dependencies of Server
|
//Dependencies of Server
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import webpack from 'webpack';
|
import webpack from 'webpack';
|
||||||
@ -28,6 +29,8 @@ const { ENV, PORT, PREFIX_URL, ONLY_EXACT_PATH } = config;
|
|||||||
|
|
||||||
const routesUrls = routes.map( route => route.path );
|
const routesUrls = routes.map( route => route.path );
|
||||||
|
|
||||||
|
const isWin = process.platform === 'win32';
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
// @ts-ignore:next-line
|
// @ts-ignore:next-line
|
||||||
@ -46,20 +49,23 @@ if(ENV === 'development'){
|
|||||||
}));
|
}));
|
||||||
}else{
|
}else{
|
||||||
const baseUrl = __dirname.replace(/\/server(.*)/,'');
|
const baseUrl = __dirname.replace(/\/server(.*)/,'');
|
||||||
|
const baseUrlWin = __dirname.replace(/\\server(.*)/,'');
|
||||||
const fullURL = `${baseUrl}` ;
|
const fullURL = `${baseUrl}` ;
|
||||||
|
const fullURLWin = `${baseUrlWin}` ;
|
||||||
app
|
app
|
||||||
.use((req, res, next) => {
|
.use((req, res, next) => {
|
||||||
if(!req.hashManifest) req.hashManifest = getHashManifest();
|
if(!req.hashManifest) req.hashManifest = getHashManifest();
|
||||||
next();
|
next();
|
||||||
})
|
})
|
||||||
.use(express.static(fullURL))
|
.use(express.static(isWin ? fullURLWin : fullURL))
|
||||||
.use(helmet())
|
.use(helmet())
|
||||||
.use(helmet.permittedCrossDomainPolicies())
|
.use(helmet.permittedCrossDomainPolicies())
|
||||||
.use(helmet({
|
.use(helmet({
|
||||||
contentSecurityPolicy: {
|
contentSecurityPolicy: {
|
||||||
directives: {
|
directives: {
|
||||||
...helmet.contentSecurityPolicy.getDefaultDirectives(),
|
...helmet.contentSecurityPolicy.getDefaultDirectives(),
|
||||||
'script-src': ['\'self\'', '\'unsafe-inline\''],//"example.com"
|
'script-src': ['\'self\'', '\'unsafe-inline\''], //"example.com"
|
||||||
|
'connectSrc': ['\'self\'', '\'unsafe-inline\'', 'localhost:*']
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
@ -72,8 +78,8 @@ const setResponse = (html, preloadedState, manifest) => {
|
|||||||
const mainBuild = manifest ? manifest['frontend.js'] : 'assets/app.js';
|
const mainBuild = manifest ? manifest['frontend.js'] : 'assets/app.js';
|
||||||
const vendorBuild = manifest ? manifest['vendors.js'] : 'assets/vendor.js';
|
const vendorBuild = manifest ? manifest['vendors.js'] : 'assets/vendor.js';
|
||||||
const manifestJson = manifest ? `<link rel="manifest" href="${manifest['manifest.json']}">` : '';
|
const manifestJson = manifest ? `<link rel="manifest" href="${manifest['manifest.json']}">` : '';
|
||||||
const memoryFs = compiler.outputFileSystem
|
const memoryFs = compiler.outputFileSystem;
|
||||||
const haveVendor = haveVendorsCss(manifest, memoryFs)
|
const haveVendor = haveVendorsCss(manifest, memoryFs);
|
||||||
|
|
||||||
return(`
|
return(`
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { config } from '../../config';
|
import { config } from '../../config';
|
||||||
|
|
||||||
const { ENV } = config
|
const { ENV } = config;
|
||||||
|
|
||||||
|
const isWin = process.platform === 'win32';
|
||||||
|
|
||||||
export const getHashManifest = () => {
|
export const getHashManifest = () => {
|
||||||
try {
|
try {
|
||||||
const baseUrl = __dirname.replace(/\/server(.*)/,'');
|
const baseUrl = __dirname.replace(/\/server(.*)/,'');
|
||||||
|
const baseUrlWin = __dirname.replace(/\\server(.*)/,'');
|
||||||
const fullURL = `${baseUrl}/assets/manifest-hash.json`;
|
const fullURL = `${baseUrl}/assets/manifest-hash.json`;
|
||||||
const readFileData = JSON.parse(fs.readFileSync(fullURL).toString());
|
const fullURLWin = `${baseUrlWin}\\assets\\manifest-hash.json`;
|
||||||
return readFileData
|
const readFileData = isWin ? JSON.parse(fs.readFileSync(fullURLWin).toString()) : JSON.parse(fs.readFileSync(fullURL).toString());
|
||||||
|
return readFileData;
|
||||||
}catch(err){
|
}catch(err){
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
@ -17,12 +21,13 @@ export const getHashManifest = () => {
|
|||||||
export const haveVendorsCss = (manifest, memoryFs) => {
|
export const haveVendorsCss = (manifest, memoryFs) => {
|
||||||
try {
|
try {
|
||||||
const baseUrl = __dirname.replace(/\/server(.*)/,'');
|
const baseUrl = __dirname.replace(/\/server(.*)/,'');
|
||||||
const fullURL = `${baseUrl}${manifest ? `/${manifest['vendors.css']}` : '/build/assets/vendors.css'}`;
|
const baseUrlWin = __dirname.replace(/\\server(.*)/,'');
|
||||||
|
const fullURL = `${isWin ? baseUrlWin : baseUrl}${manifest ? `/${manifest['vendors.css']}` : '/build/assets/vendors.css'}`;
|
||||||
ENV === 'production' && fs.readFileSync(fullURL).toString();
|
ENV === 'production' && fs.readFileSync(fullURL).toString();
|
||||||
ENV === 'development' && memoryFs.readFileSync(fullURL).toString();
|
ENV === 'development' && memoryFs.readFileSync(fullURL).toString();
|
||||||
return true
|
return true;
|
||||||
}catch(err){
|
}catch(err){
|
||||||
// console.error(err);
|
// console.error(err);
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
@ -51,6 +51,7 @@
|
|||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules",
|
"node_modules",
|
||||||
"build",
|
"build",
|
||||||
"PRNameGenerator.ts"
|
"PRNameGenerator.ts",
|
||||||
|
"cypress.config.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
||||||
import webpackNodeExternals from 'webpack-node-externals';
|
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 { Configuration } from 'webpack';
|
||||||
const ROOT_DIR = path.resolve(__dirname);
|
const ROOT_DIR = path.resolve(__dirname);
|
||||||
@ -11,84 +11,80 @@ const scriptExtensions = /\.(tsx|ts|js|jsx|mjs)$/;
|
|||||||
const styleExtensions = /\.(css|less|styl|scss|sass|sss)$/;
|
const styleExtensions = /\.(css|less|styl|scss|sass|sss)$/;
|
||||||
const fontsExtensions = /\.(eot|otf|ttf|woff|woff2)$/;
|
const fontsExtensions = /\.(eot|otf|ttf|woff|woff2)$/;
|
||||||
const fontsAndImagesExtensions = /\.(png|jpg|jpeg|gif|svg|ico|mp4|avi|ttf|otf|eot|woff|woff2|pdf)$/;
|
const fontsAndImagesExtensions = /\.(png|jpg|jpeg|gif|svg|ico|mp4|avi|ttf|otf|eot|woff|woff2|pdf)$/;
|
||||||
const alias = resolveTsAliases(path.resolve("tsconfig.json"));
|
const alias = resolveTsAliases(path.resolve('tsconfig.json'));
|
||||||
|
|
||||||
const config: Configuration = {
|
const config: Configuration = {
|
||||||
target: 'node',
|
target: 'node',
|
||||||
mode: 'development',
|
mode: 'development',
|
||||||
name: 'server',
|
name: 'server',
|
||||||
entry: {
|
entry: {
|
||||||
server: `${ROOT_DIR}/src/server/index.ts`,
|
server: `${ROOT_DIR}/src/server/index.ts`,
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
|
extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
|
||||||
alias,
|
alias,
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.(tsx|ts)$/, loader: "ts-loader",
|
test: scriptExtensions,
|
||||||
exclude: /node_modules/
|
use: {
|
||||||
},
|
loader: 'babel-loader',
|
||||||
{
|
},
|
||||||
test: scriptExtensions,
|
exclude: /node_modules/,
|
||||||
use: {
|
},
|
||||||
loader: 'babel-loader',
|
{
|
||||||
},
|
// Preprocess our own style files
|
||||||
exclude: [/node_modules/, /src\/frontend/],
|
test: styleExtensions,
|
||||||
},
|
exclude: /node_modules/,
|
||||||
{
|
use: [
|
||||||
// Preprocess our own style files
|
{
|
||||||
test: styleExtensions,
|
loader: MiniCssExtractPlugin.loader,
|
||||||
exclude: /node_modules/,
|
options: {
|
||||||
use: [
|
emit: false,
|
||||||
{
|
}
|
||||||
loader: MiniCssExtractPlugin.loader,
|
},
|
||||||
options: {
|
'css-loader',
|
||||||
emit: false,
|
'sass-loader',
|
||||||
}
|
|
||||||
},
|
|
||||||
'css-loader',
|
|
||||||
'sass-loader',
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: fontsAndImagesExtensions,
|
test: fontsAndImagesExtensions,
|
||||||
loader: 'file-loader',
|
loader: 'file-loader',
|
||||||
options: {
|
options: {
|
||||||
name: 'assets/[name].[ext]',
|
name: 'assets/[name].[ext]',
|
||||||
emitFile: false,
|
emitFile: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: fontsExtensions,
|
test: fontsExtensions,
|
||||||
loader: 'url-loader',
|
loader: 'url-loader',
|
||||||
options: {
|
options: {
|
||||||
name: 'assets/fonts/[name].[ext]',
|
name: 'assets/fonts/[name].[ext]',
|
||||||
esModule: false,
|
esModule: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
path: BUILD_DIR,
|
path: BUILD_DIR,
|
||||||
filename: '[name].js',
|
filename: '[name].js',
|
||||||
libraryTarget: 'commonjs2',
|
libraryTarget: 'commonjs2',
|
||||||
},
|
},
|
||||||
node: false,
|
node: false,
|
||||||
externals: [webpackNodeExternals()],
|
externals: [webpackNodeExternals()],
|
||||||
plugins: [
|
plugins: [
|
||||||
new MiniCssExtractPlugin({
|
new MiniCssExtractPlugin({
|
||||||
filename: 'assets/app.css',
|
filename: 'assets/app.css',
|
||||||
}),
|
}),
|
||||||
new WebpackShellPluginNext({
|
new WebpackShellPluginNext({
|
||||||
onBuildEnd: {
|
onBuildEnd: {
|
||||||
scripts: ['node build/server.js'],
|
scripts: ['node build/server.js'],
|
||||||
blocking: false,
|
blocking: false,
|
||||||
parallel: true
|
parallel: true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config
|
export default config;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { config as envConfig } from './config';
|
import { config as envConfig } from './config';
|
||||||
@ -6,12 +7,12 @@ import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
|||||||
import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
|
import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
|
||||||
import ESLintPlugin from 'eslint-webpack-plugin';
|
import ESLintPlugin from 'eslint-webpack-plugin';
|
||||||
import CopyPlugin from 'copy-webpack-plugin';
|
import CopyPlugin from 'copy-webpack-plugin';
|
||||||
import { resolveTsAliases } from "resolve-ts-aliases";
|
import { resolveTsAliases } from 'resolve-ts-aliases';
|
||||||
|
|
||||||
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');
|
||||||
const alias = resolveTsAliases(path.resolve("tsconfig.json"));
|
const alias = resolveTsAliases(path.resolve('tsconfig.json'));
|
||||||
|
|
||||||
const copyPatterns = [
|
const copyPatterns = [
|
||||||
{
|
{
|
||||||
@ -26,12 +27,12 @@ const copyPatterns = [
|
|||||||
{
|
{
|
||||||
from: `${ROOT_DIR}/../public/logo512.png`, to: '',
|
from: `${ROOT_DIR}/../public/logo512.png`, to: '',
|
||||||
},
|
},
|
||||||
]
|
];
|
||||||
|
|
||||||
if(fs.existsSync(`${ROOT_DIR}/../public/img`)){
|
if(fs.existsSync(`${ROOT_DIR}/../public/img`)){
|
||||||
copyPatterns.push({
|
copyPatterns.push({
|
||||||
from: `${ROOT_DIR}/../public/img`, to: 'assets/img',
|
from: `${ROOT_DIR}/../public/img`, to: 'assets/img',
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const config: Configuration = {
|
const config: Configuration = {
|
||||||
@ -118,4 +119,4 @@ const config: Configuration = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config
|
export default config;
|
||||||
|
@ -10,14 +10,14 @@ import { WebpackManifestPlugin } from 'webpack-manifest-plugin';
|
|||||||
import { CleanWebpackPlugin } from 'clean-webpack-plugin';
|
import { CleanWebpackPlugin } from 'clean-webpack-plugin';
|
||||||
import ESLintPlugin from 'eslint-webpack-plugin';
|
import ESLintPlugin from 'eslint-webpack-plugin';
|
||||||
import CopyPlugin from 'copy-webpack-plugin';
|
import CopyPlugin from 'copy-webpack-plugin';
|
||||||
import { resolveTsAliases } from "resolve-ts-aliases";
|
import { resolveTsAliases } from 'resolve-ts-aliases';
|
||||||
|
|
||||||
const ROOT_DIR = path.resolve(__dirname);
|
const ROOT_DIR = path.resolve(__dirname);
|
||||||
const resolvePath = (...args) => path.resolve(ROOT_DIR, ...args);
|
const resolvePath = (...args) => path.resolve(ROOT_DIR, ...args);
|
||||||
const BUILD_DIR = resolvePath('build');
|
const BUILD_DIR = resolvePath('build');
|
||||||
const { InjectManifest } = require('workbox-webpack-plugin');
|
const { InjectManifest } = require('workbox-webpack-plugin');
|
||||||
const nodeExternals = require('webpack-node-externals');
|
const nodeExternals = require('webpack-node-externals');
|
||||||
const alias = resolveTsAliases(path.resolve("tsconfig.json"));
|
const alias = resolveTsAliases(path.resolve('tsconfig.json'));
|
||||||
|
|
||||||
const copyPatterns = [
|
const copyPatterns = [
|
||||||
{
|
{
|
||||||
@ -33,12 +33,12 @@ const copyPatterns = [
|
|||||||
from: `${ROOT_DIR}/public/logo512.png`, to: '',
|
from: `${ROOT_DIR}/public/logo512.png`, to: '',
|
||||||
},
|
},
|
||||||
|
|
||||||
]
|
];
|
||||||
|
|
||||||
if(fs.existsSync(`${ROOT_DIR}/public/img`)){
|
if(fs.existsSync(`${ROOT_DIR}/public/img`)){
|
||||||
copyPatterns.push({
|
copyPatterns.push({
|
||||||
from: `${ROOT_DIR}/public/img`, to: 'assets/img',
|
from: `${ROOT_DIR}/public/img`, to: 'assets/img',
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const frontendConfig = {
|
const frontendConfig = {
|
||||||
@ -149,7 +149,7 @@ const serverConfig = {
|
|||||||
entry: {
|
entry: {
|
||||||
server: './src/server/index.ts',
|
server: './src/server/index.ts',
|
||||||
},
|
},
|
||||||
target: "node",
|
target: 'node',
|
||||||
externals: [nodeExternals()],
|
externals: [nodeExternals()],
|
||||||
output: {
|
output: {
|
||||||
path: path.resolve(__dirname, 'build'),
|
path: path.resolve(__dirname, 'build'),
|
||||||
|
Loading…
Reference in New Issue
Block a user