@wang1212/create-web-app
Advanced tools
Comparing version 0.7.0 to 0.7.1
# Changelog | ||
## v0.6.4(2021-09-22) | ||
## v0.7.0 (2022-01-02) | ||
**This package is now pure ESM, read https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c.** | ||
- feat: convert command line parameters to interactive command line :recycle: 99a9e5e | ||
- feat(templates): add `eslint-plugin-tsdoc` plugin :sparkles: e1567f8 | ||
- build(templates): replace polyfill solution with `usage` mode :zap: 1569d00 | ||
- docs: update changelog 8375509 | ||
https://github.com/wang1212/create-web-app/compare/v0.6.4...v0.7.0 | ||
## v0.6.4 (2021-09-22) | ||
- perf(templates): add `web-vitals` to collect performance information :sparkles: c776958 | ||
@@ -9,3 +20,3 @@ | ||
## v0.6.3(2021-09-21) | ||
## v0.6.3 (2021-09-21) | ||
@@ -12,0 +23,0 @@ - chore(templates): add a polyfill solution based on `core-js@3` :ambulance: 65e9521 |
{ | ||
"name": "@wang1212/create-web-app", | ||
"version": "0.7.0", | ||
"version": "0.7.1", | ||
"keywords": [ | ||
@@ -5,0 +5,0 @@ "web-app", |
@@ -5,3 +5,2 @@ # Create Web App | ||
[![NPM VERSION](https://badgen.net/npm/v/@wang1212/create-web-app)](https://www.npmjs.com/package/@wang1212/create-web-app) | ||
![MINZIPPED SIZE](https://badgen.net/bundlephobia/minzip/@wang1212/create-web-app) | ||
![DOWNLOAD](https://badgen.net/npm/dt/@wang1212/create-web-app) | ||
@@ -8,0 +7,0 @@ ![LAST COMMIT](https://badgen.net/github/last-commit/wang1212/create-web-app) |
@@ -5,3 +5,2 @@ # 创建 Web App | ||
[![NPM VERSION](https://badgen.net/npm/v/@wang1212/create-web-app)](https://www.npmjs.com/package/@wang1212/create-web-app) | ||
![MINZIPPED SIZE](https://badgen.net/bundlephobia/minzip/@wang1212/create-web-app) | ||
![DOWNLOAD](https://badgen.net/npm/dt/@wang1212/create-web-app) | ||
@@ -8,0 +7,0 @@ ![LAST COMMIT](https://badgen.net/github/last-commit/wang1212/create-web-app) |
// see docs: https://eslint.org/docs/user-guide/configuring | ||
module.exports = { | ||
ignorePatterns: ['node_modules', 'src/assets/**/*', 'src/vendors/**/*', '**/*.spec.ts', '**/*.test.ts'], | ||
ignorePatterns: ['node_modules', 'build', 'docs', 'public', 'src/assets/**/*', 'src/vendors/**/*'], | ||
parser: '@typescript-eslint/parser', | ||
@@ -27,10 +27,7 @@ parserOptions: { | ||
], | ||
settings: {}, | ||
settings: { | ||
// https://github.com/amilajack/eslint-plugin-compat#adding-polyfills | ||
polyfills: [], | ||
}, | ||
rules: { | ||
'no-console': [ | ||
'error', | ||
{ | ||
allow: ['warn', 'error'], | ||
}, | ||
], | ||
'tsdoc/syntax': 'warn', | ||
@@ -37,0 +34,0 @@ }, |
@@ -19,2 +19,3 @@ /* eslint-disable */ | ||
const TerserPlugin = require('terser-webpack-plugin'); | ||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); | ||
const HtmlWebpackPlugin = require('html-webpack-plugin'); | ||
@@ -27,2 +28,4 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin'); | ||
const babelConfig = require('../.babelrc.js'); | ||
module.exports = ({ NODE_ENV, SRC_DIR, BUILD_DIR, isEnvDevelopment = NODE_ENV === 'development', isEnvProduction = !isEnvDevelopment }) => ({ | ||
@@ -107,3 +110,7 @@ mode: isEnvDevelopment ? 'development' : 'production', | ||
test: /\.([tj]s|mjs)$/i, | ||
exclude: /node_modules/, | ||
exclude: (path) => { | ||
// * Compile third-party dependencies !~path.search(/(lib1)|(lib2)|(lib3)/) | ||
// return ~path.search(/node_modules/) && !~path.search(/(@use-gesture)/); | ||
return ~path.search(/node_modules/); | ||
}, | ||
use: [ | ||
@@ -113,2 +120,7 @@ { | ||
options: { | ||
// https://github.com/babel/babel-loader/issues/925 | ||
// https://github.com/babel/babel-loader/issues/823 | ||
...babelConfig, | ||
babelrc: false, | ||
configFile: false, | ||
// This is a feature of `babel-loader` for webpack (not Babel itself). | ||
@@ -203,25 +215,26 @@ // It enables caching results in ./node_modules/.cache/babel-loader/ | ||
use: [ | ||
{ | ||
loader: 'image-webpack-loader', | ||
options: { | ||
disable: isEnvDevelopment, | ||
mozjpeg: { | ||
progressive: true, | ||
quality: 65, | ||
}, | ||
optipng: { | ||
enabled: false, | ||
}, | ||
pngquant: { | ||
quality: [0.65, 0.9], | ||
speed: 4, | ||
}, | ||
gifsicle: { | ||
interlaced: false, | ||
}, | ||
webp: { | ||
quality: 75, | ||
}, | ||
}, | ||
}, | ||
// install https://github.com/tcoopman/image-webpack-loader#install | ||
// { | ||
// loader: 'image-webpack-loader', | ||
// options: { | ||
// disable: isEnvDevelopment, | ||
// mozjpeg: { | ||
// progressive: true, | ||
// quality: 65, | ||
// }, | ||
// optipng: { | ||
// enabled: false, | ||
// }, | ||
// pngquant: { | ||
// quality: [0.65, 0.9], | ||
// speed: 4, | ||
// }, | ||
// gifsicle: { | ||
// interlaced: false, | ||
// }, | ||
// webp: { | ||
// quality: 75, | ||
// }, | ||
// }, | ||
// }, | ||
], | ||
@@ -237,2 +250,13 @@ }, | ||
new WorkerPlugin(), | ||
new ForkTsCheckerWebpackPlugin({ | ||
typescript: { | ||
enabled: false, | ||
}, | ||
eslint: { | ||
files: './src/**/*.{ts,js}', // required - same as command `eslint ./src/**/*.{ts,tsx,js,jsx} --ext .ts,.js` | ||
}, | ||
issue: { | ||
exclude: (issue) => issue.severity === 'warning', | ||
}, | ||
}), | ||
new CopyWebpackPlugin({ | ||
@@ -270,3 +294,3 @@ patterns: [ | ||
// This is necessary to emit hot updates (currently CSS only): | ||
isEnvDevelopment && new webpack.HotModuleReplacementPlugin(), | ||
// isEnvDevelopment && new webpack.HotModuleReplacementPlugin(), | ||
// File systems of different operating systems handle case differently, forcing case sensitivity | ||
@@ -273,0 +297,0 @@ isEnvDevelopment && new CaseSensitivePathsPlugin(), |
@@ -61,6 +61,6 @@ { | ||
"eslint-plugin-tsdoc": "^0.2.14", | ||
"fork-ts-checker-webpack-plugin": "^6.5.0", | ||
"html-loader": "^2.1.2", | ||
"html-webpack-plugin": "^5.3.2", | ||
"husky": "^7.0.2", | ||
"image-webpack-loader": "^7.0.1", | ||
"jest": "^27.1.0", | ||
@@ -67,0 +67,0 @@ "jsdoc": "^3.6.7", |
@@ -5,112 +5,102 @@ /* eslint-disable */ | ||
'use strict' | ||
'use strict'; | ||
// env | ||
const NODE_ENV = (process.env.NODE_ENV || 'production').trim() | ||
const NODE_ENV = (process.env.NODE_ENV || 'production').trim(); | ||
// configs | ||
const pathConfig = require('../config/path.config.js')(NODE_ENV) | ||
const pathConfig = require('../config/path.config.js')(NODE_ENV); | ||
// * Use del to delete files in the external project directory | ||
const del = require('del') | ||
const del = require('del'); | ||
// webpack tool | ||
const webpack = require('webpack') | ||
const webpack = require('webpack'); | ||
// first, clean build dir | ||
del([pathConfig.build], { force: true }) | ||
.then(() => { | ||
// eslint-disable-next-line | ||
console.log('--------- Clean up the build directory is complete ! -----------\n') | ||
.then(() => { | ||
console.log('--------- Clean up the build directory completed! -----------\n'); | ||
// webpack | ||
return new Promise((resolve, reject) => { | ||
/* 1. External dependence */ | ||
webpack( | ||
require('../config/webpack.dll.config')({ | ||
NODE_ENV, | ||
BUILD_DIR: pathConfig.build, | ||
}), | ||
(err, stats) => { | ||
if (err) { | ||
console.error(err.stack || err) | ||
if (err.details) { | ||
console.error(err.details) | ||
} | ||
reject(err) | ||
return | ||
} | ||
// webpack | ||
return new Promise((resolve, reject) => { | ||
/* 1. External dependence */ | ||
webpack( | ||
require('../config/webpack.dll.config')({ | ||
NODE_ENV, | ||
BUILD_DIR: pathConfig.build, | ||
}), | ||
(err, stats) => { | ||
if (err) { | ||
console.error(err.stack || err); | ||
if (err.details) { | ||
console.error(err.details); | ||
} | ||
reject(err); | ||
return; | ||
} | ||
const info = stats.toJson() | ||
const info = stats.toJson(); | ||
if (stats.hasErrors()) { | ||
console.error(info.errors) | ||
reject(info.errors) | ||
return | ||
} | ||
if (stats.hasErrors()) { | ||
console.error(info.errors); | ||
reject(info.errors); | ||
return; | ||
} | ||
if (stats.hasWarnings()) { | ||
console.warn(info.warnings) | ||
} | ||
if (stats.hasWarnings()) { | ||
console.warn(info.warnings); | ||
} | ||
// eslint-disable-next-line | ||
console.log( | ||
stats.toString({ | ||
colors: true, | ||
modules: false, | ||
children: false, | ||
}) | ||
) | ||
console.log( | ||
stats.toString({ | ||
// https://webpack.js.org/configuration/stats/#stats-presets | ||
colors: true, | ||
preset: 'minimal', | ||
}) | ||
); | ||
resolve(200) | ||
} | ||
) | ||
}) | ||
}) | ||
.then((data) => { | ||
/* 2. Business code */ | ||
if (data !== 200) throw new Error(data) | ||
console.log('DLL has been compiled. \n'); | ||
webpack( | ||
require('../config/webpack.config')({ | ||
NODE_ENV, | ||
SRC_DIR: pathConfig.src, | ||
BUILD_DIR: pathConfig.build, | ||
}), | ||
(err, stats) => { | ||
if (err) throw err | ||
resolve(200); | ||
} | ||
); | ||
}); | ||
}) | ||
.then((data) => { | ||
/* 2. Business code */ | ||
if (data !== 200) throw new Error(data); | ||
// eslint-disable-next-line | ||
console.log( | ||
stats.toString({ | ||
colors: true, | ||
assetsSort: 'chunks', | ||
modules: false, | ||
children: false, | ||
excludeAssets: [ | ||
/vendors/, | ||
/assets/, | ||
(assetName) => { | ||
return ['manifest.json', 'robots.txt', 'favicon.ico', 'logo192.png', 'logo512.png'].includes(assetName) | ||
}, | ||
], | ||
}) | ||
) | ||
webpack( | ||
require('../config/webpack.config')({ | ||
NODE_ENV, | ||
SRC_DIR: pathConfig.src, | ||
BUILD_DIR: pathConfig.build, | ||
}), | ||
(err, stats) => { | ||
if (err) throw err; | ||
console.log('\n') | ||
console.log('Finished, build successful! :)') | ||
console.log('\n') | ||
console.log('(Press Ctrl+C to stop...)') | ||
} | ||
) | ||
console.log( | ||
stats.toString({ | ||
// https://webpack.js.org/configuration/stats/#stats-presets | ||
colors: true, | ||
preset: 'minimal', | ||
}) | ||
); | ||
// exit | ||
;[('SIGINT', 'SIGTERM')].forEach(function (sig) { | ||
process.on(sig, function () { | ||
process.exit() | ||
}) | ||
}) | ||
}) | ||
.catch((err) => { | ||
console.error(err) | ||
}) | ||
console.log('\n'); | ||
console.log('Finished, build successful! :)'); | ||
console.log('\n'); | ||
console.log('(Press Ctrl+C to stop...)'); | ||
} | ||
); | ||
['SIGINT', 'SIGTERM'].forEach(function (sig) { | ||
process.on(sig, function () { | ||
process.exit(); | ||
}); | ||
}); | ||
}) | ||
.catch((err) => { | ||
console.error(err); | ||
}); |
@@ -24,4 +24,3 @@ /* eslint-disable */ | ||
.then(() => { | ||
// eslint-disable-next-line | ||
console.log('--------- Clean up the build directory is complete ! -----------\n'); | ||
console.log('--------- Clean up the build directory completed! -----------\n'); | ||
@@ -58,11 +57,12 @@ // webpack | ||
// eslint-disable-next-line | ||
console.log( | ||
stats.toString({ | ||
// https://webpack.js.org/configuration/stats/#stats-presets | ||
colors: true, | ||
modules: false, | ||
children: false, | ||
preset: 'minimal', | ||
}) | ||
); | ||
console.log('DLL has been compiled. \n'); | ||
resolve(200); | ||
@@ -72,2 +72,4 @@ } | ||
}); | ||
// | ||
}) | ||
@@ -83,6 +85,6 @@ .then((data) => { | ||
BUILD_DIR: pathConfig.build, | ||
}) | ||
}), | ||
() => {} | ||
); | ||
// dev server config | ||
const devServer = new WebpackDevServer( | ||
@@ -98,13 +100,5 @@ { | ||
stats: { | ||
// https://webpack.js.org/configuration/stats/#stats-presets | ||
colors: true, | ||
assetsSort: 'chunks', | ||
modules: false, | ||
children: false, | ||
excludeAssets: [ | ||
/vendors/, | ||
/assets/, | ||
(assetName) => { | ||
return ['manifest.json', 'robots.txt', 'favicon.ico', 'logo192.png', 'logo512.png'].includes(assetName); | ||
}, | ||
], | ||
preset: 'minimal', | ||
}, | ||
@@ -116,11 +110,5 @@ }, | ||
// * '0.0.0.0' makes all ips accessible | ||
devServer.listen(serverConfig.port, '0.0.0.0', (err) => { | ||
if (err) throw err; | ||
devServer.start(); | ||
console.log('Starting the development server...\n'); | ||
}); | ||
// exit | ||
[('SIGINT', 'SIGTERM')].forEach(function (sig) { | ||
['SIGINT', 'SIGTERM'].forEach(function (sig) { | ||
process.on(sig, function () { | ||
@@ -127,0 +115,0 @@ devServer.close(); |
@@ -8,8 +8,11 @@ /* App entry file */ | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access | ||
window.root.innerHTML = ` | ||
<h1>App running !</h1> | ||
<p>${view}</p> | ||
`; | ||
const $root = document.getElementById('root'); | ||
if ($root) { | ||
$root.innerHTML = ` | ||
<h1>App running !</h1> | ||
<p>${view}</p> | ||
`; | ||
} | ||
// If you want to start measuring performance in your app, pass a function | ||
@@ -22,2 +25,2 @@ // to log results (for example: reportWebVitals(console.log)) | ||
// Learn more about service workers: https://bit.ly/CRA-PWA | ||
serviceWorker.register(); | ||
serviceWorker.register(undefined); |
/* eslint-disable */ | ||
// @ts-nocheck | ||
@@ -16,116 +17,116 @@ // This optional code is used to register a service worker. | ||
const isLocalhost = Boolean( | ||
window.location.hostname === 'localhost' || | ||
// [::1] is the IPv6 localhost address. | ||
window.location.hostname === '[::1]' || | ||
// 127.0.0.0/8 are considered localhost for IPv4. | ||
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/) | ||
) | ||
window.location.hostname === 'localhost' || | ||
// [::1] is the IPv6 localhost address. | ||
window.location.hostname === '[::1]' || | ||
// 127.0.0.0/8 are considered localhost for IPv4. | ||
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/) | ||
); | ||
export function register(config) { | ||
if (location.protocol != 'file:' && 'serviceWorker' in navigator) { | ||
// The URL constructor is available in all browsers that support SW. | ||
const publicUrl = new URL('.', window.location.href) | ||
if (publicUrl.origin !== window.location.origin) { | ||
// Our service worker won't work if PUBLIC_URL is on a different origin | ||
// from what our page is served on. This might happen if a CDN is used to | ||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374 | ||
return | ||
} | ||
if (location.protocol != 'file:' && 'serviceWorker' in navigator) { | ||
// The URL constructor is available in all browsers that support SW. | ||
const publicUrl = new URL('.', window.location.href); | ||
if (publicUrl.origin !== window.location.origin) { | ||
// Our service worker won't work if PUBLIC_URL is on a different origin | ||
// from what our page is served on. This might happen if a CDN is used to | ||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374 | ||
return; | ||
} | ||
window.addEventListener('load', () => { | ||
const swUrl = './service-worker.js' | ||
window.addEventListener('load', () => { | ||
const swUrl = './service-worker.js'; | ||
if (isLocalhost) { | ||
// This is running on localhost. Let's check if a service worker still exists or not. | ||
checkValidServiceWorker(swUrl, config) | ||
if (isLocalhost) { | ||
// This is running on localhost. Let's check if a service worker still exists or not. | ||
checkValidServiceWorker(swUrl, config); | ||
// Add some additional logging to localhost, pointing developers to the | ||
// service worker/PWA documentation. | ||
navigator.serviceWorker.ready.then(() => { | ||
console.log('This web app is being served cache-first by a service ' + 'worker. To learn more, visit https://bit.ly/CRA-PWA') | ||
}) | ||
} else { | ||
// Is not localhost. Just register service worker | ||
registerValidSW(swUrl, config) | ||
} | ||
}) | ||
} | ||
// Add some additional logging to localhost, pointing developers to the | ||
// service worker/PWA documentation. | ||
navigator.serviceWorker.ready.then(() => { | ||
console.log('This web app is being served cache-first by a service ' + 'worker. To learn more, visit https://bit.ly/CRA-PWA'); | ||
}); | ||
} else { | ||
// Is not localhost. Just register service worker | ||
registerValidSW(swUrl, config); | ||
} | ||
}); | ||
} | ||
} | ||
function registerValidSW(swUrl, config) { | ||
navigator.serviceWorker | ||
.register(swUrl) | ||
.then((registration) => { | ||
registration.onupdatefound = () => { | ||
const installingWorker = registration.installing | ||
if (installingWorker == null) { | ||
return | ||
} | ||
installingWorker.onstatechange = () => { | ||
if (installingWorker.state === 'installed') { | ||
if (navigator.serviceWorker.controller) { | ||
// At this point, the updated precached content has been fetched, | ||
// but the previous service worker will still serve the older | ||
// content until all client tabs are closed. | ||
console.log('New content is available and will be used when all ' + 'tabs for this page are closed. See https://bit.ly/CRA-PWA.') | ||
navigator.serviceWorker | ||
.register(swUrl) | ||
.then((registration) => { | ||
registration.onupdatefound = () => { | ||
const installingWorker = registration.installing; | ||
if (installingWorker == null) { | ||
return; | ||
} | ||
installingWorker.onstatechange = () => { | ||
if (installingWorker.state === 'installed') { | ||
if (navigator.serviceWorker.controller) { | ||
// At this point, the updated precached content has been fetched, | ||
// but the previous service worker will still serve the older | ||
// content until all client tabs are closed. | ||
console.log('New content is available and will be used when all ' + 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'); | ||
// Execute callback | ||
if (config && config.onUpdate) { | ||
config.onUpdate(registration) | ||
} | ||
} else { | ||
// At this point, everything has been precached. | ||
// It's the perfect time to display a | ||
// "Content is cached for offline use." message. | ||
console.log('Content is cached for offline use.') | ||
// Execute callback | ||
if (config && config.onUpdate) { | ||
config.onUpdate(registration); | ||
} | ||
} else { | ||
// At this point, everything has been precached. | ||
// It's the perfect time to display a | ||
// "Content is cached for offline use." message. | ||
console.log('Content is cached for offline use.'); | ||
// Execute callback | ||
if (config && config.onSuccess) { | ||
config.onSuccess(registration) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}) | ||
.catch((error) => { | ||
console.error('Error during service worker registration:', error) | ||
}) | ||
// Execute callback | ||
if (config && config.onSuccess) { | ||
config.onSuccess(registration); | ||
} | ||
} | ||
} | ||
}; | ||
}; | ||
}) | ||
.catch((error) => { | ||
console.error('Error during service worker registration:', error); | ||
}); | ||
} | ||
function checkValidServiceWorker(swUrl, config) { | ||
// Check if the service worker can be found. If it can't reload the page. | ||
fetch(swUrl, { | ||
headers: { 'Service-Worker': 'script' }, | ||
}) | ||
.then((response) => { | ||
// Ensure service worker exists, and that we really are getting a JS file. | ||
const contentType = response.headers.get('content-type') | ||
if (response.status === 404 || (contentType != null && contentType.indexOf('javascript') === -1)) { | ||
// No service worker found. Probably a different app. Reload the page. | ||
navigator.serviceWorker.ready.then((registration) => { | ||
registration.unregister().then(() => { | ||
window.location.reload() | ||
}) | ||
}) | ||
} else { | ||
// Service worker found. Proceed as normal. | ||
registerValidSW(swUrl, config) | ||
} | ||
}) | ||
.catch(() => { | ||
console.log('No internet connection found. App is running in offline mode.') | ||
}) | ||
// Check if the service worker can be found. If it can't reload the page. | ||
fetch(swUrl, { | ||
headers: { 'Service-Worker': 'script' }, | ||
}) | ||
.then((response) => { | ||
// Ensure service worker exists, and that we really are getting a JS file. | ||
const contentType = response.headers.get('content-type'); | ||
if (response.status === 404 || (contentType != null && contentType.indexOf('javascript') === -1)) { | ||
// No service worker found. Probably a different app. Reload the page. | ||
navigator.serviceWorker.ready.then((registration) => { | ||
registration.unregister().then(() => { | ||
window.location.reload(); | ||
}); | ||
}); | ||
} else { | ||
// Service worker found. Proceed as normal. | ||
registerValidSW(swUrl, config); | ||
} | ||
}) | ||
.catch(() => { | ||
console.log('No internet connection found. App is running in offline mode.'); | ||
}); | ||
} | ||
export function unregister() { | ||
if ('serviceWorker' in navigator) { | ||
navigator.serviceWorker.ready | ||
.then((registration) => { | ||
registration.unregister() | ||
}) | ||
.catch((error) => { | ||
console.error(error.message) | ||
}) | ||
} | ||
if ('serviceWorker' in navigator) { | ||
navigator.serviceWorker.ready | ||
.then((registration) => { | ||
registration.unregister(); | ||
}) | ||
.catch((error) => { | ||
console.error(error.message); | ||
}); | ||
} | ||
} |
/* eslint-disable sonarjs/no-duplicate-string */ | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-nocheck | ||
/** | ||
@@ -272,3 +274,3 @@ * @see https://github.com/GoogleChrome/web-vitals#readme | ||
} | ||
}, true); | ||
}); | ||
}) | ||
@@ -275,0 +277,0 @@ .catch(() => {}); |
{ | ||
"compilerOptions": { | ||
"target": "ES5", | ||
"sourceMap": true, | ||
"jsx": "preserve", | ||
"rootDir": ".", | ||
"resolveJsonModule": true, | ||
"esModuleInterop": true, | ||
"strict": true, | ||
// "noImplicitAny": false | ||
}, | ||
"include": ["src", "scripts", "config", ".eslintrc.js"], | ||
"exclude": ["src/assets/**/*", "src/vendors/**/*", "**/*.spec.ts", "**/*.test.ts"] | ||
"compilerOptions": { | ||
"target": "ES5", | ||
"sourceMap": true, | ||
"jsx": "preserve", | ||
"rootDir": ".", | ||
"resolveJsonModule": true, | ||
"esModuleInterop": true, | ||
"strict": true | ||
// "noImplicitAny": false | ||
}, | ||
"include": ["src", "scripts", ".eslintrc.js"], | ||
"exclude": ["src/assets/**/*", "src/vendors/**/*"] | ||
} |
// see docs: https://eslint.org/docs/user-guide/configuring | ||
module.exports = { | ||
ignorePatterns: ['node_modules', 'src/assets/**/*', 'src/vendors/**/*', '**/*.spec.ts', '**/*.test.ts'], | ||
ignorePatterns: ['node_modules', 'build', 'docs', 'public', 'src/assets/**/*', 'src/vendors/**/*'], | ||
parser: '@typescript-eslint/parser', | ||
@@ -35,10 +35,6 @@ parserOptions: { | ||
}, | ||
// https://github.com/amilajack/eslint-plugin-compat#adding-polyfills | ||
polyfills: ['Promise'], | ||
}, | ||
rules: { | ||
'no-console': [ | ||
'error', | ||
{ | ||
allow: ['warn', 'error'], | ||
}, | ||
], | ||
'tsdoc/syntax': 'warn', | ||
@@ -45,0 +41,0 @@ }, |
@@ -20,2 +20,3 @@ /* eslint-disable */ | ||
const TerserPlugin = require('terser-webpack-plugin'); | ||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); | ||
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); | ||
@@ -28,2 +29,4 @@ const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); | ||
const babelConfig = require('../.babelrc.js'); | ||
module.exports = ({ NODE_ENV, SRC_DIR, BUILD_DIR, isEnvDevelopment = NODE_ENV === 'development', isEnvProduction = !isEnvDevelopment }) => ({ | ||
@@ -109,3 +112,7 @@ mode: isEnvDevelopment ? 'development' : 'production', | ||
test: /\.([tj]sx?|mjs)$/i, | ||
exclude: /node_modules/, | ||
exclude: (path) => { | ||
// * Compile third-party dependencies !~path.search(/(lib1)|(lib2)|(lib3)/) | ||
// return ~path.search(/node_modules/) && !~path.search(/(@use-gesture)/); | ||
return ~path.search(/node_modules/); | ||
}, | ||
use: [ | ||
@@ -115,2 +122,7 @@ { | ||
options: { | ||
// https://github.com/babel/babel-loader/issues/925 | ||
// https://github.com/babel/babel-loader/issues/823 | ||
...babelConfig, | ||
babelrc: false, | ||
configFile: false, | ||
// This is a feature of `babel-loader` for webpack (not Babel itself). | ||
@@ -205,25 +217,26 @@ // It enables caching results in ./node_modules/.cache/babel-loader/ | ||
use: [ | ||
{ | ||
loader: 'image-webpack-loader', | ||
options: { | ||
disable: isEnvDevelopment, | ||
mozjpeg: { | ||
progressive: true, | ||
quality: 65, | ||
}, | ||
optipng: { | ||
enabled: false, | ||
}, | ||
pngquant: { | ||
quality: [0.65, 0.9], | ||
speed: 4, | ||
}, | ||
gifsicle: { | ||
interlaced: false, | ||
}, | ||
webp: { | ||
quality: 75, | ||
}, | ||
}, | ||
}, | ||
// install https://github.com/tcoopman/image-webpack-loader#install | ||
// { | ||
// loader: 'image-webpack-loader', | ||
// options: { | ||
// disable: isEnvDevelopment, | ||
// mozjpeg: { | ||
// progressive: true, | ||
// quality: 65, | ||
// }, | ||
// optipng: { | ||
// enabled: false, | ||
// }, | ||
// pngquant: { | ||
// quality: [0.65, 0.9], | ||
// speed: 4, | ||
// }, | ||
// gifsicle: { | ||
// interlaced: false, | ||
// }, | ||
// webp: { | ||
// quality: 75, | ||
// }, | ||
// }, | ||
// }, | ||
], | ||
@@ -239,2 +252,13 @@ }, | ||
new WorkerPlugin(), | ||
new ForkTsCheckerWebpackPlugin({ | ||
typescript: { | ||
enabled: false, | ||
}, | ||
eslint: { | ||
files: './src/**/*.{ts,tsx,js,jsx}', // required - same as command `eslint ./src/**/*.{ts,tsx,js,jsx} --ext .ts,.tsx,.js,.jsx` | ||
}, | ||
issue: { | ||
exclude: (issue) => issue.severity === 'warning', | ||
}, | ||
}), | ||
new CopyWebpackPlugin({ | ||
@@ -273,3 +297,3 @@ patterns: [ | ||
// This is necessary to emit hot updates (currently CSS only): | ||
isEnvDevelopment && new webpack.HotModuleReplacementPlugin(), | ||
// isEnvDevelopment && new webpack.HotModuleReplacementPlugin(), | ||
// File systems of different operating systems handle case differently, forcing case sensitivity | ||
@@ -276,0 +300,0 @@ isEnvDevelopment && new CaseSensitivePathsPlugin(), |
@@ -76,6 +76,6 @@ { | ||
"eslint-plugin-tsdoc": "^0.2.14", | ||
"fork-ts-checker-webpack-plugin": "^6.5.0", | ||
"html-loader": "^2.1.2", | ||
"html-webpack-plugin": "^5.3.2", | ||
"husky": "^7.0.2", | ||
"image-webpack-loader": "^7.0.1", | ||
"jest": "^27.1.0", | ||
@@ -82,0 +82,0 @@ "jsdoc": "^3.6.7", |
@@ -5,112 +5,102 @@ /* eslint-disable */ | ||
'use strict' | ||
'use strict'; | ||
// env | ||
const NODE_ENV = (process.env.NODE_ENV || 'production').trim() | ||
const NODE_ENV = (process.env.NODE_ENV || 'production').trim(); | ||
// configs | ||
const pathConfig = require('../config/path.config.js')(NODE_ENV) | ||
const pathConfig = require('../config/path.config.js')(NODE_ENV); | ||
// * Use del to delete files in the external project directory | ||
const del = require('del') | ||
const del = require('del'); | ||
// webpack tool | ||
const webpack = require('webpack') | ||
const webpack = require('webpack'); | ||
// first, clean build dir | ||
del([pathConfig.build], { force: true }) | ||
.then(() => { | ||
// eslint-disable-next-line | ||
console.log('--------- Clean up the build directory is complete ! -----------\n') | ||
.then(() => { | ||
console.log('--------- Clean up the build directory completed! -----------\n'); | ||
// webpack | ||
return new Promise((resolve, reject) => { | ||
/* 1. External dependence */ | ||
webpack( | ||
require('../config/webpack.dll.config')({ | ||
NODE_ENV, | ||
BUILD_DIR: pathConfig.build, | ||
}), | ||
(err, stats) => { | ||
if (err) { | ||
console.error(err.stack || err) | ||
if (err.details) { | ||
console.error(err.details) | ||
} | ||
reject(err) | ||
return | ||
} | ||
// webpack | ||
return new Promise((resolve, reject) => { | ||
/* 1. External dependence */ | ||
webpack( | ||
require('../config/webpack.dll.config')({ | ||
NODE_ENV, | ||
BUILD_DIR: pathConfig.build, | ||
}), | ||
(err, stats) => { | ||
if (err) { | ||
console.error(err.stack || err); | ||
if (err.details) { | ||
console.error(err.details); | ||
} | ||
reject(err); | ||
return; | ||
} | ||
const info = stats.toJson() | ||
const info = stats.toJson(); | ||
if (stats.hasErrors()) { | ||
console.error(info.errors) | ||
reject(info.errors) | ||
return | ||
} | ||
if (stats.hasErrors()) { | ||
console.error(info.errors); | ||
reject(info.errors); | ||
return; | ||
} | ||
if (stats.hasWarnings()) { | ||
console.warn(info.warnings) | ||
} | ||
if (stats.hasWarnings()) { | ||
console.warn(info.warnings); | ||
} | ||
// eslint-disable-next-line | ||
console.log( | ||
stats.toString({ | ||
colors: true, | ||
modules: false, | ||
children: false, | ||
}) | ||
) | ||
console.log( | ||
stats.toString({ | ||
// https://webpack.js.org/configuration/stats/#stats-presets | ||
colors: true, | ||
preset: 'minimal', | ||
}) | ||
); | ||
resolve(200) | ||
} | ||
) | ||
}) | ||
}) | ||
.then((data) => { | ||
/* 2. Business code */ | ||
if (data !== 200) throw new Error(data) | ||
console.log('DLL has been compiled. \n'); | ||
webpack( | ||
require('../config/webpack.config')({ | ||
NODE_ENV, | ||
SRC_DIR: pathConfig.src, | ||
BUILD_DIR: pathConfig.build, | ||
}), | ||
(err, stats) => { | ||
if (err) throw err | ||
resolve(200); | ||
} | ||
); | ||
}); | ||
}) | ||
.then((data) => { | ||
/* 2. Business code */ | ||
if (data !== 200) throw new Error(data); | ||
// eslint-disable-next-line | ||
console.log( | ||
stats.toString({ | ||
colors: true, | ||
assetsSort: 'chunks', | ||
modules: false, | ||
children: false, | ||
excludeAssets: [ | ||
/vendors/, | ||
/assets/, | ||
(assetName) => { | ||
return ['manifest.json', 'robots.txt', 'favicon.ico', 'logo192.png', 'logo512.png'].includes(assetName) | ||
}, | ||
], | ||
}) | ||
) | ||
webpack( | ||
require('../config/webpack.config')({ | ||
NODE_ENV, | ||
SRC_DIR: pathConfig.src, | ||
BUILD_DIR: pathConfig.build, | ||
}), | ||
(err, stats) => { | ||
if (err) throw err; | ||
console.log('\n') | ||
console.log('Finished, build successful! :)') | ||
console.log('\n') | ||
console.log('(Press Ctrl+C to stop...)') | ||
} | ||
) | ||
console.log( | ||
stats.toString({ | ||
// https://webpack.js.org/configuration/stats/#stats-presets | ||
colors: true, | ||
preset: 'minimal', | ||
}) | ||
); | ||
// exit | ||
;[('SIGINT', 'SIGTERM')].forEach(function (sig) { | ||
process.on(sig, function () { | ||
process.exit() | ||
}) | ||
}) | ||
}) | ||
.catch((err) => { | ||
console.error(err) | ||
}) | ||
console.log('\n'); | ||
console.log('Finished, build successful! :)'); | ||
console.log('\n'); | ||
console.log('(Press Ctrl+C to stop...)'); | ||
} | ||
); | ||
['SIGINT', 'SIGTERM'].forEach(function (sig) { | ||
process.on(sig, function () { | ||
process.exit(); | ||
}); | ||
}); | ||
}) | ||
.catch((err) => { | ||
console.error(err); | ||
}); |
@@ -24,4 +24,3 @@ /* eslint-disable */ | ||
.then(() => { | ||
// eslint-disable-next-line | ||
console.log('--------- Clean up the build directory is complete ! -----------\n'); | ||
console.log('--------- Clean up the build directory completed! -----------\n'); | ||
@@ -58,11 +57,12 @@ // webpack | ||
// eslint-disable-next-line | ||
console.log( | ||
stats.toString({ | ||
// https://webpack.js.org/configuration/stats/#stats-presets | ||
colors: true, | ||
modules: false, | ||
children: false, | ||
preset: 'minimal', | ||
}) | ||
); | ||
console.log('DLL has been compiled. \n'); | ||
resolve(200); | ||
@@ -72,2 +72,4 @@ } | ||
}); | ||
// | ||
}) | ||
@@ -83,6 +85,6 @@ .then((data) => { | ||
BUILD_DIR: pathConfig.build, | ||
}) | ||
}), | ||
() => {} | ||
); | ||
// dev server config | ||
const devServer = new WebpackDevServer( | ||
@@ -98,13 +100,5 @@ { | ||
stats: { | ||
// https://webpack.js.org/configuration/stats/#stats-presets | ||
colors: true, | ||
assetsSort: 'chunks', | ||
modules: false, | ||
children: false, | ||
excludeAssets: [ | ||
/vendors/, | ||
/assets/, | ||
(assetName) => { | ||
return ['manifest.json', 'robots.txt', 'favicon.ico', 'logo192.png', 'logo512.png'].includes(assetName); | ||
}, | ||
], | ||
preset: 'minimal', | ||
}, | ||
@@ -116,11 +110,5 @@ }, | ||
// * '0.0.0.0' makes all ips accessible | ||
devServer.listen(serverConfig.port, '0.0.0.0', (err) => { | ||
if (err) throw err; | ||
devServer.start(); | ||
console.log('Starting the development server...\n'); | ||
}); | ||
// exit | ||
[('SIGINT', 'SIGTERM')].forEach(function (sig) { | ||
['SIGINT', 'SIGTERM'].forEach(function (sig) { | ||
process.on(sig, function () { | ||
@@ -127,0 +115,0 @@ devServer.close(); |
@@ -26,3 +26,3 @@ /** | ||
*/ | ||
async getSigned(): void { | ||
async getSigned(): Promise<void> { | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call | ||
@@ -43,3 +43,3 @@ const { data, error } = await apiGetSignedUser(); | ||
*/ | ||
async signIn(payload: { account: string; password: string }): void { | ||
async signIn(payload: { account: string; password: string }): Promise<void> { | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call | ||
@@ -69,3 +69,3 @@ const { error } = await apiSignIn(payload); | ||
*/ | ||
async signOut(): void { | ||
async signOut(): Promise<void> { | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call | ||
@@ -72,0 +72,0 @@ const { error } = await apiSignOut(); |
/* eslint-disable */ | ||
// @ts-nocheck | ||
// This optional code is used to register a service worker. | ||
@@ -15,116 +16,116 @@ // register() is not called by default. | ||
const isLocalhost = Boolean( | ||
window.location.hostname === 'localhost' || | ||
// [::1] is the IPv6 localhost address. | ||
window.location.hostname === '[::1]' || | ||
// 127.0.0.0/8 are considered localhost for IPv4. | ||
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/) | ||
) | ||
window.location.hostname === 'localhost' || | ||
// [::1] is the IPv6 localhost address. | ||
window.location.hostname === '[::1]' || | ||
// 127.0.0.0/8 are considered localhost for IPv4. | ||
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/) | ||
); | ||
export function register(config) { | ||
if (location.protocol != 'file:' && 'serviceWorker' in navigator) { | ||
// The URL constructor is available in all browsers that support SW. | ||
const publicUrl = new URL('.', window.location.href) | ||
if (publicUrl.origin !== window.location.origin) { | ||
// Our service worker won't work if PUBLIC_URL is on a different origin | ||
// from what our page is served on. This might happen if a CDN is used to | ||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374 | ||
return | ||
} | ||
if (location.protocol != 'file:' && 'serviceWorker' in navigator) { | ||
// The URL constructor is available in all browsers that support SW. | ||
const publicUrl = new URL('.', window.location.href); | ||
if (publicUrl.origin !== window.location.origin) { | ||
// Our service worker won't work if PUBLIC_URL is on a different origin | ||
// from what our page is served on. This might happen if a CDN is used to | ||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374 | ||
return; | ||
} | ||
window.addEventListener('load', () => { | ||
const swUrl = `./service-worker.js` | ||
window.addEventListener('load', () => { | ||
const swUrl = `./service-worker.js`; | ||
if (isLocalhost) { | ||
// This is running on localhost. Let's check if a service worker still exists or not. | ||
checkValidServiceWorker(swUrl, config) | ||
if (isLocalhost) { | ||
// This is running on localhost. Let's check if a service worker still exists or not. | ||
checkValidServiceWorker(swUrl, config); | ||
// Add some additional logging to localhost, pointing developers to the | ||
// service worker/PWA documentation. | ||
navigator.serviceWorker.ready.then(() => { | ||
console.log('This web app is being served cache-first by a service ' + 'worker. To learn more, visit https://bit.ly/CRA-PWA') | ||
}) | ||
} else { | ||
// Is not localhost. Just register service worker | ||
registerValidSW(swUrl, config) | ||
} | ||
}) | ||
} | ||
// Add some additional logging to localhost, pointing developers to the | ||
// service worker/PWA documentation. | ||
navigator.serviceWorker.ready.then(() => { | ||
console.log('This web app is being served cache-first by a service ' + 'worker. To learn more, visit https://bit.ly/CRA-PWA'); | ||
}); | ||
} else { | ||
// Is not localhost. Just register service worker | ||
registerValidSW(swUrl, config); | ||
} | ||
}); | ||
} | ||
} | ||
function registerValidSW(swUrl, config) { | ||
navigator.serviceWorker | ||
.register(swUrl) | ||
.then((registration) => { | ||
registration.onupdatefound = () => { | ||
const installingWorker = registration.installing | ||
if (installingWorker == null) { | ||
return | ||
} | ||
installingWorker.onstatechange = () => { | ||
if (installingWorker.state === 'installed') { | ||
if (navigator.serviceWorker.controller) { | ||
// At this point, the updated precached content has been fetched, | ||
// but the previous service worker will still serve the older | ||
// content until all client tabs are closed. | ||
console.log('New content is available and will be used when all ' + 'tabs for this page are closed. See https://bit.ly/CRA-PWA.') | ||
navigator.serviceWorker | ||
.register(swUrl) | ||
.then((registration) => { | ||
registration.onupdatefound = () => { | ||
const installingWorker = registration.installing; | ||
if (installingWorker == null) { | ||
return; | ||
} | ||
installingWorker.onstatechange = () => { | ||
if (installingWorker.state === 'installed') { | ||
if (navigator.serviceWorker.controller) { | ||
// At this point, the updated precached content has been fetched, | ||
// but the previous service worker will still serve the older | ||
// content until all client tabs are closed. | ||
console.log('New content is available and will be used when all ' + 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'); | ||
// Execute callback | ||
if (config && config.onUpdate) { | ||
config.onUpdate(registration) | ||
} | ||
} else { | ||
// At this point, everything has been precached. | ||
// It's the perfect time to display a | ||
// "Content is cached for offline use." message. | ||
console.log('Content is cached for offline use.') | ||
// Execute callback | ||
if (config && config.onUpdate) { | ||
config.onUpdate(registration); | ||
} | ||
} else { | ||
// At this point, everything has been precached. | ||
// It's the perfect time to display a | ||
// "Content is cached for offline use." message. | ||
console.log('Content is cached for offline use.'); | ||
// Execute callback | ||
if (config && config.onSuccess) { | ||
config.onSuccess(registration) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}) | ||
.catch((error) => { | ||
console.error('Error during service worker registration:', error) | ||
}) | ||
// Execute callback | ||
if (config && config.onSuccess) { | ||
config.onSuccess(registration); | ||
} | ||
} | ||
} | ||
}; | ||
}; | ||
}) | ||
.catch((error) => { | ||
console.error('Error during service worker registration:', error); | ||
}); | ||
} | ||
function checkValidServiceWorker(swUrl, config) { | ||
// Check if the service worker can be found. If it can't reload the page. | ||
fetch(swUrl, { | ||
headers: { 'Service-Worker': 'script' }, | ||
}) | ||
.then((response) => { | ||
// Ensure service worker exists, and that we really are getting a JS file. | ||
const contentType = response.headers.get('content-type') | ||
if (response.status === 404 || (contentType != null && contentType.indexOf('javascript') === -1)) { | ||
// No service worker found. Probably a different app. Reload the page. | ||
navigator.serviceWorker.ready.then((registration) => { | ||
registration.unregister().then(() => { | ||
window.location.reload() | ||
}) | ||
}) | ||
} else { | ||
// Service worker found. Proceed as normal. | ||
registerValidSW(swUrl, config) | ||
} | ||
}) | ||
.catch(() => { | ||
console.log('No internet connection found. App is running in offline mode.') | ||
}) | ||
// Check if the service worker can be found. If it can't reload the page. | ||
fetch(swUrl, { | ||
headers: { 'Service-Worker': 'script' }, | ||
}) | ||
.then((response) => { | ||
// Ensure service worker exists, and that we really are getting a JS file. | ||
const contentType = response.headers.get('content-type'); | ||
if (response.status === 404 || (contentType != null && contentType.indexOf('javascript') === -1)) { | ||
// No service worker found. Probably a different app. Reload the page. | ||
navigator.serviceWorker.ready.then((registration) => { | ||
registration.unregister().then(() => { | ||
window.location.reload(); | ||
}); | ||
}); | ||
} else { | ||
// Service worker found. Proceed as normal. | ||
registerValidSW(swUrl, config); | ||
} | ||
}) | ||
.catch(() => { | ||
console.log('No internet connection found. App is running in offline mode.'); | ||
}); | ||
} | ||
export function unregister() { | ||
if ('serviceWorker' in navigator) { | ||
navigator.serviceWorker.ready | ||
.then((registration) => { | ||
registration.unregister() | ||
}) | ||
.catch((error) => { | ||
console.error(error.message) | ||
}) | ||
} | ||
if ('serviceWorker' in navigator) { | ||
navigator.serviceWorker.ready | ||
.then((registration) => { | ||
registration.unregister(); | ||
}) | ||
.catch((error) => { | ||
console.error(error.message); | ||
}); | ||
} | ||
} |
/* eslint-disable sonarjs/no-duplicate-string */ | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-nocheck | ||
/** | ||
@@ -272,3 +274,3 @@ * @see https://github.com/GoogleChrome/web-vitals#readme | ||
} | ||
}, true); | ||
}); | ||
}) | ||
@@ -275,0 +277,0 @@ .catch(() => {}); |
{ | ||
"compilerOptions": { | ||
"target": "ES5", | ||
"sourceMap": true, | ||
"jsx": "preserve", | ||
"rootDir": ".", | ||
"resolveJsonModule": true, | ||
"esModuleInterop": true, | ||
"strict": true, | ||
// "noImplicitAny": false | ||
}, | ||
"include": ["src", "scripts", "config", ".eslintrc.js"], | ||
"exclude": ["src/assets/**/*", "src/vendors/**/*", "**/*.spec.ts", "**/*.test.ts"] | ||
"compilerOptions": { | ||
"target": "ES5", | ||
"sourceMap": true, | ||
"jsx": "preserve", | ||
"rootDir": ".", | ||
"resolveJsonModule": true, | ||
"esModuleInterop": true, | ||
"strict": true | ||
// "noImplicitAny": false | ||
}, | ||
"include": ["src", "scripts", ".eslintrc.js"], | ||
"exclude": ["src/assets/**/*", "src/vendors/**/*"] | ||
} |
Sorry, the diff of this file is not supported yet
249430
3394
63